Upgrade to Pro — share decks privately, control downloads, hide ads and more …

あなたのPHPアプリ、ログはでてますか?あるいはログをだしてますか? / Are you writing a log? Or just out a log?

uzulla
June 24, 2023

あなたのPHPアプリ、ログはでてますか?あるいはログをだしてますか? / Are you writing a log? Or just out a log?

PHPカンファレンス福岡 2023
2023/06/24
uzulla

uzulla

June 24, 2023
Tweet

More Decks by uzulla

Other Decks in Programming

Transcript

  1. ͋ͳͨͷPHPΞϓϦɺϩά͸Ͱͯ·͔͢ʁ
    ͋Δ͍͸ϩάΛͩͯ͠·͔͢ʁ
    — PHPΧϯϑΝϨϯε෱Ԭ 2023
    — 2023/06/24
    — uzulla

    View Slide

  2. ࣗݾ঺հ
    — ࠷ۙΞϝϦΧԣஅ͖ͯͨ͠uzullaͰ͢
    — PHP͕ಘҙͳϑϦʔͷԿͰ΋԰Ͱ͢
    άάͬͯ΋Β͑Ε͹ૣ͍
    — PRαϙʔτ΍ϊϕϧςΟ੍࡞୅ߦͱ͔΋ͯ͠·͢
    — ͓࢓ࣄ͓଴͓ͪͯ͠Γ·͢

    View Slide

  3. DISCLAIMER
    — ҆қʹ͜ͷεϥΠυͷਅࣅΛ͢Δͳ
    — ·ͣɺݱ৔ͷઌୡ͕͜͏ͤΑͱݴ͑͹ै͑
    — վֵ͸ɺνʔϜͰ߹ҙΛͱͬͯɺνʔϜͰ΍Ζ͏

    View Slide

  4. վֵͱվળ
    — վֵͱ͸ɺطଘΛʮཪ੾Δʯ͜ͱ
    — վળͱ͸ɺطଘͷԆ௕Ͱྑ͘͢Δ͜ͱ
    — ·ͣ͸γεςϜͷվળΛߟ͑Δ
    — (ίʔυͰ͸ͳ͍ɺγεςϜશମ)
    — ৽نͷ࣌ʹ͸վֵ͠΍͍͢
    — (ίϯϙʔωϯτ୯ҐͰ΋)
    — ࠓʮେྔʯʹ໰୊͕͋ΔͳΒɺ·ͣݮΒͯ͠ΈΑ͏
    — തଧ͸શһͰૉפශʹͳΔ֮ޛΛ΋ͬͯ΍Ζ͏Ͷ

    View Slide

  5. ͓Ͷ͕͍
    — γχΞ(ʁ)Ͱ͓Ջͳօ͞Μ͸
    — ʮ͜Ε͸ಉҙʯ
    — ʮ͜Ε͸͋Γ͑Μʯ
    — ͱ͔͍ͩ͘͞
    — एख͸൑அͰ͖ͳ͍

    View Slide

  6. ࠓճͷωλόϨ
    ϩά͸ʮߦಈʯͱηοτͰ͋Δ

    View Slide

  7. ϩάɺͬͯ͠·͔͢ʁ
    — ஌͍ͬͯΔਓʁ

    View Slide

  8. ϩάྫ(Apache Access log)
    127.0.0.1 - - [11/Jun/2023:10:30:15 +0000] "GET /index.html HTTP/1.1" 200 1234
    — 127.0.0.1ɿϦϞʔτͷIPΞυϨε
    — -ɿϦϞʔτϢʔβʔ໊ʢແࢦఆ͸ϋΠϑϯͰஔ͖׵͑ΒΕΔʣ
    — -ɿϦϞʔτೝূϢʔβʔ໊ʢແࢦఆ͸ϋΠϑϯͰஔ͖׵͑ΒΕΔʣ
    — [11/Jun/2023:10:30:15 +0000]ɿΞΫηε͕ൃੜͨ͠೔࣌ɺܗ͕ࣜ࠷ѱʂ
    — "GET /index.html HTTP/1.1"ɿHTTPϝιουɺPATHɺϓϩτίϧͱόʔδϣϯ
    — 200ɿHTTPεςʔλείʔυ
    — 1234ɿϨεϙϯεͷαΠζʢόΠτʣ

    View Slide

  9. ϩάͱ͍͑͹ΞΫηεϩά
    — ͳͥͳΒɺݹདྷ͸ඞͣ͋ͬͨ
    — ʮΤϥʔϩάʁग़ͳ͍͜ͱ΋ଟ͔ͬͨͳ(Ϩϯαό࣌୅Λࢥ͍ग़͠ͳ͕Β)ʯ
    — ʮ͜ΜͳϩάΈͨ͜ͱͳ͍ͳʯʮApacheͰ͢·Μʯ
    — ʮΞΫηεϩάͬͯϛυϧ΢ΣΞͰ͢ΑͶʯʮ͸͍ʯ
    — ࠷ۙ͸Google Analyticsͱ͔ͰݟΔ͠ɺ
    ຊ౰ʹࠔͬͨͱ͖͘Β͍͔͠ݟͳ͍͔΋
    — ߏ଄Խ͞Ε͍ͯΔ͕ɺඪ४͸ͳ͍
    — ApacheɺnginxɺPHPͷ-SͰҟͳΔ͠ɺେ఍ΧελϜͰ͖Δ
    — ͱ͍͏͔ɺApacheͷaccess logܗࣜ΋΄΅͔ͭΘΕͯͳͯ͘ɺCustomLogͷ
    combinedܗ͕ࣜී௨

    View Slide

  10. Ͱɺϩάͱ͸ʁ
    — ͳΜΒ͔ͷΠϕϯτ࣌ʹ࢒͞ΕΔϝοηʔδ
    — ਓؒ΍ػց͕ಡΉͨΊʹ࢒͢
    — ྺ࢙తʹςΩετͷ͜ͱ͕ଟ͍
    — ͳΜ͔ͩΜͩҰߦͷ͜ͱ͕ଟ͍͕ɺGrep͠΍͍͔͢ΒͩΖ͏
    — ߏ଄Խ͞Ε͍ͯΔ
    — ೔෇ͱ͔ɺIPͱ͔ɺUAͱ͔৭ʑͳϝλσʔλ
    — ύʔεͷͨΊʹJSONɺLTSVͳͲॲཧ͠΍͍͢΋ͷʹ͢Δ͜ͱ΋

    View Slide

  11. ԿͰݟͯ·͢ʁ
    — ʮงғؾʯ
    — ϑΝΠϧΛcatɾtailɺgrep
    — Τεύʔɺ͋Δ͍͸ϩάͷ໛༷
    — Slack௨஌
    — ϩάϓϥοτϑΥʔϜ౳Ͱू໿ͯ͠ݕࡧ
    — ML/AIʹΑΔΞϊʔϚϦʔ௨஌

    View Slide

  12. ͦΕ͸ࣗ෼Ͱͭͬͨ͘΋ͷͰ͔͢ʁ
    — ઌഐ͕ͭͬͨ͘
    — ࣗ෼͕ͦ͏ͨ͠

    View Slide

  13. ϩάɺΈͯ·͔͢ʁ
    — ݟͯΔਓɺखΛ͍͋͛ͯͩ͘͞

    View Slide

  14. ʮΤϥʔϩάΈͯ·͔͢ʂʯ
    — Apache΍php-fpm͔Βग़ͯ͘Δ͍ΘΏΔΤϥʔϩά
    — ʮྫΛڍ͛ΔΑΓɺࣗࣾͷΤϥʔϩάΈͯΈ·͠ΐ͏ɺ॓୊ͳʂʂʂʯ
    ʮखൈ͖Ͱ͸ʁʯ
    — ઃܭɾίʔυ͕ؒҧͬͨΓɺDBʹ઀ଓͰ͖ͳ͔ͬͨΓ͢Δͱग़Δ΍ͭ
    — ಈ͔ͳ͍ͷͰɺϩάҎલʹؾͮ͘
    — ʮಈ͍ͨɺϤγʂʂʯ=> ཪͰେྔͷNOTICE,WARN,STRICT,DEPRECATED
    — ͭ·Γɺݟͯͳ͍ਓ͸ࠓ͙͢൓লͯ͠΄͍͠
    — PHPͷΤϥʔϩά͸ʮൃใଆʯͷϨϕϧௐ੔͕Ͱ͖ΔΘ͚Ͱ͸ͳ͍ͷͰɺࣺͯΒΕ͕
    ͪ
    (ϨϕϧΛมߋ͢Δͱɺݟ͑ͳ͘ͳΔ)
    — (ࠓճͷओ୊Ͱ͸ͳ͍(͕ݴΘͣʹ͍ΒΕͳ͍ͷ͕PHPerͰ͋Δ)

    View Slide

  15. PHPͷΤϥʔϩάͰͳ͍ϩά(΍΍͍͜͠)
    — ΍ͬͱͰ͕͢ɺࠓճ͸͜Εͷ࿩ʹͳΓ·͢
    — ʮΤϯδχΞ͕ɺҙਤతʹग़͢ϩάʯ
    — ΞϓϦέʔγϣϯϩάɺ౳ͱݴΘΕΔ͜ͱ΋͋ΔΆ͍͕ਖ਼໊ࣜশΛ͠Βͳ͍
    — (ͳ͓ɺFWͷΤϥʔϩά͸PHPͷΤϥʔϩάͱಉ͡Α͏ͳ૝ఆͰ͢)

    View Slide

  16. ࠶౓ͷΦν: ϩάઃܭ͸ΞΫγϣϯ͔Β͸͡ΊΑ
    — ʮͦͷϩάɺԿͷͨΊʹͰ͍ͯ·͔͢ʁʯ
    — ʮ͍ͭʯɺʮͲ͜Ͱʯɺʮͳʹ͕ʯɺ͸ଟ෼͋Γͦ͏
    — ʮԿΛʯɺʮͲ͏͢Δ͔ʁʯ͸͖·ͬͯ·͔͢ʁ

    View Slide

  17. ʮΤϥʔ͕ൃੜ͠·ͨ͠ʂʯ
    — …ͱ͍͏Τϥʔ(ਅإ)
    — স͍ͬͯΔ৔߹Ͱ͸ͳ͍Ͱ͢Αʁ
    — Ωϛ͸Έͨ͜ͱ͕͋Δ͔ʂʁ

    View Slide

  18. Զ͸͋Δʂ͍ͬͯ͏͔ॻ͍
    ͨ͜ͱ΋͋Δʂ
    ͩΕ΋͕͔͜͜Β࢝ΊΔͷ
    ͰͦΕ͸໰୊Ͱ͸ͳ͍ʂ

    View Slide

  19. Ͱ͸ɺϩάͷྫΛ͔͍͜͠AI܅ʹͩͯ͠΋Β͍·ͨ͠ʂ
    — Failed to connect to the database server
    — Incorrect username or password
    — The requested resource could not be found
    — You do not have permission to access this resource
    — The user exceeded the rate limit for this resource

    View Slide

  20. ԶͳΒApproveͤΜͧ
    — ʮThisͬͯͳʹʁɺThe userͬͯ୭ʁʯ
    — ରԠ͢ΔͨΊͷ৘ใ͕ͨΓͳ͍
    — ϦΫΤετIDͱ͔ɺϩάΠϯϢʔβʔͱ͔ͦ͏͍͏ͷೖΕͨํ͕ྑ͍
    - {ͳΜΒ͔ΞΠςϜ} could not be found
    - UID:234 does not have permission to access resource_id: abc
    - UID:123 exceeded the rate limit for resource: def
    — ͨͩ͠ɺେྔʹϩά͕Ͱ͓ͯΓɺͦΕͷू໿Λ͍ͯ͠Δ৔߹͸രൃతʹ૿͑Δ͜ͱ͕͋Δ
    (·͋ɺͦΕ͸ઌʹ௚ͨ͠ํ͕ྑ͍ͷͰ͸…)

    View Slide

  21. ϙΠϯτ
    ίϯςΩετΛࣺͯΔͳ

    View Slide

  22. ʮͦͷͱ͖Ͳ͏͔ͩͬͨʯ
    — ࠶ݱ΍ௐ͕ࠪͰ͖·͔͢ʁ
    — ʮ୭͕ӨڹΛड͚͔ͨϩάΛΈ͍ͯͩ͘͞ʯʮͦ͜ʹͳ͚Ε͹ͳ͍Ͱ͢Ͷʯ
    — ʮ࠶ൃ͸͠·ͤΜ͔ʁʯʮࢁצͰͳ͓ͨ͠ͷͰ࣍Λ଴ͪ·͠ΐ͏ʯ
    — ͋Δ͚ͩग़ͤ͹ྑ͍Θ͚Ͱ΋ͳ͍ɻಡΈͮΒ͍͠ɺݸਓ৘ใ΋͋Δ͠ɺDisk΋͋;ΕΔ
    ͠
    — ࢲʮ͕Μ͹Εɺͳ͓༗ঈͰ૬ஊʹ͸ͷΕ·͢ʯ

    View Slide

  23. ͦͯ͠ɺ๨ΕͣʹΞΫγϣϯʹͭͳ͛Ζʂ
    — ʮ͜͏ͯ͠΄͍͠ͳʯͱࢥͬͯ΋ɺॻ͔ͳ͍ͱ·ͣͭͨΘΒͳ͍
    — ʮյΕͨϑΝΠϧΛফͤʯͱ͔ϩάʹॻ͍͓ͯ͘·Ͱ͋Δ
    — खॱॻ΍όάνέ౳ͱͭͳ͕͍ͬͯΔ͜ͱ͕๬·͍͠
    — ͳ͓ɺURL͸มΘΔͷͰɺݕࡧ༻ʹIDʹ͢Δํ͕ྑ͍
    — ID͸࿈൪΍UUID͕ྑ͍
    — ҙຯΛ΋ͨͤΔͷ͸ݸਓతʹΞϯνύλʔϯ
    — (ϦϑΝΫλ͠ʹ͘͘ͳΔ)
    — …͕ɺͳ͔ͥΈΜͳIDʹҙຯΛ͕࣋ͨͤͨΔ͠…·͋΍ͬͯΈͯ΋͍͍ͷͰ͸…
    — Զ͸͓קΊ͠ͳ͍͚Ͳͳʂʂ

    View Slide

  24. > Error: Error
    ͳʹ͕Τϥʔͳͷʁʁʁ
    > Error: User Information update.
    …Ͳ͜Ͱʁ୭͕ʁ
    > Error: User update fail. user_id: 1
    ͏ʔΜ…͜ͷϝοηʔδ͸ɺͲ͜ͷ৔ॴ͚ͩͬͳ…શจݕࡧ͠Α͏͔…ʁ·͋໘౗͔ͩΒΈͳ͔ͬͨ͜ͱʹ͢Δ͔ʁ
    > Error: User update fail. user_id: 1 on /path/to/Some.php:123
    ;ʔΜɺ͜ͷϑΝΠϧ͔…ͳΜͱͳ͘Θ͔Γͦ͏ͩͳ…Ͱ΋·͋ݟͳ͔ͬͨ͜ͱʹ͍͍ͯ͠ͷ͔Θ͔ΒΜͳ
    > Emerg: Update user order record fail. user_id: 1 on /path/to/Some.php:123
    Emergʁͬͯ͜ͱ͸க໋తΤϥʔ͔ʂͩΕ͔͜ΕͲ͏͢Ε͹͍͍͔ͬͯ͠ΔʁͱΓ͋͑ͣίʔυಡΜͰௐࠪ͢Δ͔…ʂ
    > Emerg: Update user order record fail. user_id: 1 on /path/to/Some.php:123 see OpDoc:ABC123
    க໋తΤϥʔͩʂDocΈͯΈΑ͏ʂ…ͳΔ΄Ͳ·ͣCR͞Μʹ࿈བྷ͔ɺϢʔβʔ͠Β΂ͯୈҰใʂͦͷޙӡ༻ͰΧόʔ͔ʂ

    View Slide

  25. ʮ͋Εʁ͜Ε͸؂ࢹͰ͸ʁʯʮͦ͏Ͱ͢ʯ
    — ٯʹɺ؂ࢹ͕ແ͍ͳΒϩά͸ԿͷͨΊʹʁ
    — (؂ࢹʹ͸ɺࣄޙͷௐࠪ΋ؚΊ·͢)
    — ੋඇ؂ࢹͷॻ੶ΛಡΉͱྑ͍ͱࢥ͍·͢ɺࠓճ͸؂ࢹʹ͍ͭͯ͸ਂ۷Γ͸͠ͳ͍

    View Slide

  26. ͞ΒͳΔయܕతͳίϯςΩετɾϝλσʔλ
    — ϑΝΠϧͱߦ൪߸ɺελοΫτϨʔε͸౰વ͓໾ཱͪ৘ใ
    — ઈରʹඞཁͳ΋ͷ͸ϩΨʔͷϋϯυϥͰࣗಈతʹೖΕΔͷ΋ྑ͍
    — ϩΨʔͰϩάϝοηʔδΛՃ޻͠ɺఆܗͰೖΕΔͳͲ
    — ϋϯυϥʹ͍ͭͯ͸ɺmonologͷυΩϡϝϯτ΍ɺ͓͗͞ΜͷτʔΫΛݟ͍ͯͩ͘͞
    — ࠷ۙ͸NewRelicͱ͔DataDogͱ͔ͷAPM͍ΕͯΔͱࣗಈతʹूΊͯ͘ΕΔɺศརʂ
    — ຊ౰ʹศརͳͷͰɺૉ௚ʹۚΛ෷ͬͯߦ͘ͷ͕ྑ͍ͱࢥ͍·͢ɻ
    — ϙϯʂͱͰͨΤϥʔʹͦ͏͍ͬͨίϯςΩετ͕ࣗಈͰ͍ͭͯ͘ΕΔɺ࠷ߴ

    View Slide

  27. ΞΫγϣϯ͕͖·ΔͱɺϩάϨϕϧ͕ܾ·Δ
    − ී௨ͷϩΨʔ͸ϩάϨϕϧΛ࣋ͭ
    - DEBUG
    - INFO
    - NOTICE
    - WARNING
    - ERROR
    - CRITICAL
    - ALERT
    - EMERGENCY

    View Slide

  28. Ϩϕϧ͸ΞΫγϣϯ࣌ͷτϦΞʔδͰ͋Δ
    — ۓٸɺଈԠɺܦա؍࡯ɺͲ͏Ͱ΋͍͍ɺ։ൃ༻ͱ͔
    — ·͋σϑΥϧτ͸ΤϥʔͰ͢ΑͶɺͳ͔ͥ͠ΒΜ͕ɻ
    — ͜Ε͕੔උ͞Ε͍ͯͳ͍ͱແࢹʹͭͳ͕Δ
    — શ෦͕Errorͩͱ…
    ʮͳΜ͔ΤϥʔͰͯ·͚͢Ͳ…ʁʯ
    ʮ͋ͬ͜ͷΤϥʔ͸ແࢹ͍͍ͯ͠ΤϥʔͳΜͰʯ
    ʮ͔ͦͬʙʙ(ͦΜͳ͜ͱΘ͔Δ͔ʂೋ౓ͱݟͳ͍Θʂ)ʯ
    — ͋ͳ͔ͨ͠ղΒͳ͍ͱɺपΓ͸αϙʔτͰ͖ͳ͍
    — ʮ͜Ε͸ଈԠ͕ඞཁͰͨ͠ʂͳΜͰແࢹͨ͠ΜͰ͔͢ʂʯ
    ʮ͠ΒΜ͕ͳ(͋͋ʂ͢Έ·ͤΜͰͨ͠ʂࠓޙؾΛ͚ͭ·͢ʂ)ʯ

    View Slide

  29. ϩάϨϕϧ͸ͪΌΜͱ͚ͭ
    Α͏ͳʂ
    ҰਓͰ։ൃɺӡ༻ɺ24/365
    ରԠ͢ΔͳΒϤγʂʂ

    View Slide

  30. ͱ͸͍͑Ή͔͍ͣ͠ɺԹ౓͕ࠩ͋Δ
    — νʔϜͰ߹ҙΛऔΔඞཁ͕͋Δ
    — ྫ:ʮਂ໷ʹ͖ͨͨى͜͞ΕΔ΂͖͔ʁʯσʔλ͕յΕଓ͚Δʁ
    — ྫ:ʮ࣍ͷӦۀ೔Ͱྑ͍ʯӨڹൣғ͕޿͕Δʁ
    — ྫ:ʮϦτϥΠͰ௚ΔʯਓؒͷରԠ͕…ඞཁɾෆཁʁ
    — ͜͏͍͏ͷΛɺ૝૾ͯ͠ϩάϨϕϧʹϚοϓͯ͠Թ౓ײΛܾΊΔ
    — ͜ͷ͋ͨΓ͸ޙͰ΋ม͑ΒΕΔ
    — ϩάϨϕϧͷ෼ྨΛޙͰม͑Δͷ͸େม͕ͩɺ
    ϩάϨϕϧʹରԠ͢Δߦಈ͸ม͑΍͍͢
    — ͱΓ͋͑ͣ৭ʑߟ͑ͯΈͯ΄͍͠

    View Slide

  31. Ͱɺϩάͷൃใ(ൃੜ)͸Ͳ͜Ͱ͢Δʁ
    — جຊతʹ͸ɺ(͍ΘΏΔ)ίϯτϩʔϥ΍υϝΠϯ૚Ͱൃੜͤ͞Δ΂͖ͩͱʮࢲ͸ʯࢥ͏
    — ͦΕ͕ʮͲ͏ѻΘΕΔ͔ʯ൑அͰ͖Δ૚
    — ࢀরϖʔδͷDBΫΤϦࣦഊͱ͔Ͳ͏Ͱ΋Α͍͕ɺ
    ܾࡁͷDBΫΤϦࣦഊ͸Ϡό͍ͳͲ͋Δ
    — ϥΠϒϥϦ΍ϨϙδτϦ૚ͱ͔Ԟਂ͘Ͱ΍Δͱ΍΍͍͜͠
    — ʮϩΨʔΛҾ਺Ͱύεͯ͠ߦ͚Δൣғʯ͕ແ೉ͱࢥ͏
    — ϥΠϒϥϦ౳Ͱ͸ΤϥʔͳΒྫ֎Λͳ͛ɺ্Ґʹ೚ͤͨํ͕ྑ͍
    — ͦͷͨΊʹ΋ಠࣗྫ֎ͱ͔ॻ͜͏
    — ʮྫ֎͸ݏ͍ͳΜͰ͢Αʯ
    ʮ͡Ό͍͍͋Τϥʔදݱํ๏͓͑ͯ͘͠Εɺ-1ฦ͢ͱ͔͸ແ͠ͳʂʯ

    View Slide

  32. ۩ମతͳϩΨʔ(ϩάΛൃੜͤ͞Δ΋ͷ)ʹ͍ͭͯ
    — جຊ͸monologɺσϑΝΫτελϯμʔυ
    — monolog͸֦ுੑ͕ߴ͍
    — ϓϩηοαɺϋϯυϥɺϑΥʔϚολΛొ࿥ɾࣗ࡞Ͱ͖Δ
    — Ճ޻ɺϝλσʔλऩू෇༩ɺૹ৴(อଘ)ͳͲ͕ࣗ༝ʹ
    — ͜ͷޙͷ͓͗͞ΜͷτʔΫΛΈͯ͘Ε
    — ϩΨʔ͸ෳ਺࡞ΕΔ
    — ͜ͷϨϕϧҎԼ͸ແࢹ͢ΔϩΨʔ
    — ͜ͷϨϕϧͳΒSlackʹඈ͹͢ϩΨʔ
    — ౳
    — ·͋ɺ࠷ڧͰ͢ɻߟ͑Δ͘Β͍ͳΒmonologͰ

    View Slide

  33. Slack௨஌ྫ
    // ϩΨʔΛ࡞੒
    $log = new Logger('slack_logger');
    // ϑΝΠϧϋϯυϥΛ௥Ճ
    $log->pushHandler(new StreamHandler('/path/to/log'));
    // SlackϋϯυϥΛ௥ՃʢϩάϨϕϧ͕ΫϦςΟΧϧͷ৔߹ͷΈʣ
    $log->pushHandler(new SlackWebhookHandler($slackWebhookUrl), Logger::CRITICAL);
    // ϩάϝοηʔδΛه࿥
    $log->error('Slackʹඈ͹ͳ͍');
    $log->critical('SlackʹඈͿ');

    View Slide

  34. ϩΨʔ͸ෳ਺ੜ੒͞ΕΔલఏʹ
    — ʮελςΟοΫʹίʔϧ͢Δͱศརʂʯ͸Ξϯνύλʔϯ
    — UnitTestͰʮ͜͜Ͱ͸null ϩΨʔʯͱ͔͍ͨ͠
    — Feature Flagͱ૬ੑ΋Α͍
    — ϦϦʔε௚ޙɺ͜ͷػೳ͚ͩϩάϨϕϧ͸ม͍͑ͨͱ͔͋Δ
    — ίʔυͷԞਂ͘ͰϩάϨϕϧΛIF෼ذ͢Δͷ͸ਖ਼ؾͰ͸ͳ͘ɺFeature୯ҐͰϨϕϧΛม
    ͑ͨϩΨʔΛInjectͰ͖ͨ΄͏͕ศར
    — ࠷ѱɺϝοηʔδʹPrefixͱ͔ɺಠࣗϩάϨϕϧͱ͔ɺϋϯυϥͰվมͱ͔΋͋Δ
    ͕ɺ͏ʔΜ…
    — ϩΨʔࣗମΛࠩ͠ସ͑ͨ΄͏͕Ͳ͏ߟ͑ͯ΋҆શ

    View Slide

  35. class SomeFeature{
    public function __construct(Logger $logger){}
    public function run();
    }
    // == in prod
    $log = new Logger('slack_logger');
    $log->pushHandler(new StreamHandler('path/to/log'));
    $log->pushHandler(new SlackWebhookHandler($slackWebhookUrl));
    $some = new SomeFeature($log); // SlackͱϑΝΠϧʹอଘ
    // == in tests
    $log = new Logger('null_logger');
    $log->pushHandler(new NullHandler());
    $some = new SomeFeature($log); // ڏۭʹফ͑Δ

    View Slide

  36. ϩά͸ΠϕϯτͰ͋ΓɺଟॏͳετϦʔϜ
    — ϩά͸Πϕϯτ(Ϩίʔυ)Ͱ͋ΓɺʮҰߦͷςΩετʯͰ͸ͳ͍
    — SourceͱFilterͱSinkΛߟ͑Δ
    — Source͸ൃใɺ͜͜·Ͱઆ໌ͨ͠ͱ͓Γ
    — Filter͸ࣗಈతʹ೔෇͍ΕͨΓɺ੔ܗͨ͠ΓɺJSONʹͨ͠Γ
    — Sink͸ϑΝΠϧͩͬͨΓɺసૹͩͬͨΓɺ௨஌ͩͬͨΓ
    — ଟஈɾଟॏʹͰ͖Δ
    — monologͷத͚ͩͰͳ͘ɺେମͷϩάج൫͸ͦ͏͍ͬͨ֓೦͕͋Δ(΋ͬͱߴ౓͚ͩ
    Ͳɺ·͋جຊతͳߟ͑ํͱͯ͠)
    — ͜ͷ͋ͨΓ͸͜ͷޙͷ͓͗͞ΜͷτʔΫΛݟ͍ͯͩ͘͞
    — ʮMonologͷ࣮૷ʹֶͿInterfaceͷ࢖͍Ͳ͜Ζʯ

    View Slide

  37. // == ͋ΔPHPͷத…
    +-------------+
    | Source |
    +-------------+
    |
    v
    +-------------+
    | Filter |
    +-------------+
    |
    v
    +-------------+
    | Sink |
    +-------------+

    View Slide

  38. // == ͋ΔPHPͷத…
    +-------------+
    | Source |
    +-------------+
    |
    v
    +-------------+
    | Filter |
    +-------------+
    |
    v
    +-------------+
    | Sink |
    +-------------+
    |
    // == ͔͜͜Βɺผͷϩάج൫΁…
    v
    +-------------+
    | Source |
    +-------------+
    |
    v
    +-------------+
    | Filter |
    +-------------+
    |
    v
    +-------------+
    | Sink |
    +-------------+

    View Slide

  39. (লུ)
    |
    v
    +-------------+
    | Sink |
    +-------------+
    |
    // == ෼ذ΍ίϐʔ(ෳ੡ͷૹ৴)΋͋ΔΑʂ
    ├----------------------┐
    v v
    +-------------+ +-------------+
    | Source | | Source |
    +-------------+ +-------------+
    | |
    v v
    +-------------+ +-------------+
    (লུ)

    View Slide

  40. ΰουϩΨʔ໰୊
    — ϑϥΫλϧ(ೖΕࢠ)ͳߟ͑ํΛͤͣɺ۪௚ʹίʔυΛॻ͘ͱ஍ࠈͰ͢
    — ʮͳΜͰͦΜͳந৅తͳ͜ͱΛ͠ͳ͍ͱ͍͚ͳ͍ͷʁ͜͜ʹSlackʹૹ৴͔͚ͬͯ͹͍͍
    ͡ΌΜʯʮͦ͏͢Δͱͳɺෛ࠴Λະདྷʹ͓͘Δ͜ͱʹͳΔΜ͡Όʯ
    — (୹ظతʹͦ͏͢Δͱ͔ɺϨΨγʔίʔυ͔ͩΒ͔ͨ͠ͳ͘͸Θ͔Δ͕ɺ৽نͰ͸Ϡό
    ͍)
    — ৼΔ෣͍Λਂ͘ʹॻ͖ࠐΉͳʂ
    — ʮ͜͜ͷΤϥʔ͸Slack௨஌͍ͨ͠ʯΛϋʔυίʔυͯ͠͸μϝ
    — ʮ͜Ε͸ΫϦςΟΧϧʯ(Source)=>ʮΫϦςΟΧϧ͸Slack΁ʯ(sink)ͱ͍ͨ͠
    — ͪΌΜͱؔ৺Λ෼཭͠Α͏ͳ

    View Slide

  41. ͦ΋ͦ΋ू໿͠ͳ͍ͱ΍ͬͯΒΕͳ͍ΜͩΑʂ
    — ݱ୅͸ϗετ͕ෳ਺͋Δ͠…ू໿͠ͳ͍ͱ͖͍ͭͰ͠ΐৗࣝతʹߟ͑ͯ…
    — ϩά؅ཧɾղੳج൫Λ׆༻ͤΑ
    — FluentdͰNewRelicʹ͓͘Δͱ͔
    stderrΛCloudWatch Logsʹ͓͘Γ͜ΜͰͱ͔
    — ֎෦Խ͢Δ͜ͱͰؾܰʹมߋͰ͖Δ͠ɺσϓϩΠແ͠ʹௐ੔΋Ͱ͖Δ

    View Slide

  42. ༨ஊ
    — ࢲʮίϯϑΟάͬͯͱ͜ΖʹεοͱṖͷσϑΥϧτ͕ઃఆ͞Ε͍ͯͯɺͦΕ͕ਆͷ͓ݴ༿
    ͔ͩΒௐ੔͍ͯ͠ͳ͍ɺͱ͍͏Α͏ͳݱ৔ͰDisk fullԿ౓΋ݟͨɻ࠷ѱʂʂʯ
    — ͪΌ·΄ΓʮͦΕ͸LaravelΛͪΌΜͱ࢖͑ͳ͍ਓ͕ѱ͍Ͱ͢Αʯ
    — Laravelϓϩͷ໊ݴͰ͢
    — ϩά͸ن໛ʹൺྫ͢Δ͠ɺͪΌΜͱઃఆ͢Δඞཁ͕͋ΓɺLaravel͸σϑΥϧτͩͱ
    monologΛ΄ͱΜͲௐڭͯ͠ͳ͍ͷͰΈͳ͞Μ͕ͪΌΜͱͯ͋͛͠Δඞཁ͕͋Δ͔Β
    Ͷʁʁʁ
    — (શ͍ͬͯ͘͡ͳ͍ͷʹແࣄͳͷ͸ɺଟ෼τϥώοΫ͕ແ͍͔ΒͳͷͰɺૣΊʹରԠͯ͠
    ͓͜͏ͳʂ)

    View Slide

  43. 'channels' => [
    'stack' => [
    'driver' => 'stack',
    'channels' => ['single'],
    ],
    'single' => [
    'driver' => 'single',
    'path' => storage_path('logs/laravel.log'),
    'level' => 'debug',
    ],

    View Slide

  44. ϩάͷΑ͋͘Δ᠘
    — ʮ͍ΕΕ͹͍ΕΔ΄Ͳ௥͍͔͚΍͍͢ʂʯ
    — => ͋Δҙຯͦ͏͕ͩɺϊΠζ͕૿͑Δ
    ϩά͕؂ࢹͱ࿈ܞ͢Δ͔Βʹ͸΄Ͳ΄Ͳ͕ྑ͍
    ϩάϨϕϧͱ૊Έ߹Θͤͯߟ͑ͯ
    — ʮϑΝαʔυ΍ελςΟοΫϝιουͰͲ͔͜ΒͰ΋ݺ΂ͯศརʂʯํࣜ
    — => কདྷతʹ͸(େ఍)ͭΒ͍ͷͰɺςετ΍ϨΨγʔίʔυҎ֎Ͱ͸΍Ίͨํ͕ྑ͍
    (ςετͰϩάʁʁʁ)
    — ʮDI͸ʁʯʮDIͰ࡞ΔϨϕϧͳΒ…͍΍…͔͠͠…ʯ
    — =>ϩΨʔ͕Ұຊ͔͠ͳͯ͘ྑ͍ͳΒྑ͍ͷͰ͸
    (΋ͪΖΜɺ΍Ε͹ෳ਺࡞Δ͜ͱ͸Ͱ͖ΔͩΖ͏ɺؾΛ͚ͭͯ࢖͍ͬͯͬͯ͘Ε)

    View Slide

  45. ༨ஊ
    — ྫ֎͠ʹ͍͘ॴͬͯ͋ΔΑͶ…
    — ExcepionΛฦͬͯ͢Ͳ͏Ͱ͔͢ʁҟ୺Ͱ͔͢Ͷʁ
    function getSome(): Some|null|Exception {}
    — ʮ࢖ͬͯΔΜͰ͔͢ʁʯʮ໧ൿ͠·͢ʯ

    View Slide

  46. ͱ͜ΖͰɺόον͸ʁ
    — جຊ͸ಉ༷͕ͩɺͦͷ্ͰUNIXͷCLIϓϩάϥϜͷྲّྀʹ৐ͬऔΔ΂͖
    — εςʔλείʔυ͸ΩνϯͱͤΑ
    — CronͷྲّྀʹଇΔͳͲ
    — ʮΤϥʔͰͳ͍ͳΒɺԿ΋ग़͞ͳ͍ʯ
    — PHPͷΤϥʔϩάͷग़ྗઌΛϩάϑΝΠϧʹ͢Δͱը໘ʹͰͣɺؾ͔ͮͳ͍͜ͱ͕͋Δ
    ٯʹɺSTDERRʹͩ͢ͱɺϩάͷసૹ͕໘౗ͳ͜ͱ΋͋Δ
    — monologͷग़ྗϋϯυϥ͸ࣗ༝ʹελοΫͰ͖ΔͷͰศར
    — ϩάϑΝΠϧʹͩͭͭ͠ɺSTDERRʹग़͢ͱ͔΋Ͱ͖Δ
    — ͦ΋ͦ΋ʮCLIϓϩάϥϜʯͳͷ͔ͩΒɺPHPࣗମͰ͕Μ͹Βͳ͍ͷ΋खɺී௨ͷCLIͱ
    ͯ͠ॻ͖ɺjournald(syslog+cron),fluentd(౳)ͳͲͷ૊Έ߹Θͤ

    View Slide

  47. ͰʂϩάΛΈͯ·͔͢ʁ
    — ࣮͸৭ʑݟΔʮ֯౓ʯ͕͋Δ
    — ଈԠ͢Δϩά
    — ࣌ܥྻɾ࣌ؒൣғͰݟΔϩά
    — ͨΊͯɺΧ΢ϯτղੳ͢Δϩά
    — ͞ΒʹͦΕͷෳ߹…

    View Slide

  48. ଈԠɺΞϥʔτ
    — ͙͢͞·֬ೝɾ௚͞ͳ͍ͱ͍͚ͳ͍Τϥʔ
    — લఏͱͯ͠ɺͩΕ΋Τϥʔϩά͸Έͳ͍ͷͰ͋Δʂ(ਅإ)
    — ۤ৘͕དྷͯɺݟΔ
    — ͦΜͳ͜ͱͰΑ͍ͷͩΖ͏͔ɺ͍΍ɺΑ͘ͳ͍ͩΖ͏
    — ͭ·Γɺʮϩά͕དྷ͍ʯͷ࣌୅
    — ϝʔϧ͢ΔɺSlackʹ౤͛ΔɺPagerDutyͱ͔͔ͭ͏
    — ϩάϓϥοτϑΥʔϜ΍monologͷϋϯυϥΛ࢖͏
    — ݟͨ͋ͱɺΞΫγϣϯΛ͠·͠ΐ͏
    — Կ΋͠ͳ͍ϩάͳΒফ͢ɻͰͳ͍ͱ͞ΒʹΑ·Εͳ͘ͳΔ

    View Slide

  49. View Slide

  50. View Slide

  51. ࣌ܥྻɾ࣌ؒൣғͰݟΔϩά
    — ϩάϓϥοτϑΥʔϜΛ͔ͭ͏ͷ͕ఆ൪
    — NඵؒʹMճΞϥʔτ͕͕͋ͬͨΒͲ͏ߟ͑ͯ΋͓͔͍͠
    — ʮͨ·ͨ·ࣦഊ(ِཅੑ)ʯ͸ଟ͍ͷͰɺ࿈ଓNճͰʙͱ͍͏৚͕݅΄͍͠ࣄ͸ଟ͍
    — ͕ɺηϧϑώʔϧ͢Δ΋ͷ͸௨஌͢Δඞཁͳ͍
    — NewRelicͩͱɺNRQLͳͲͰࣜΛఆٛͰ͖Δ
    => ৚݅ͷᮢ஋Λ͑ͨ͜ΒΞϥʔτ
    — ࣗલͰ࡞Δࣄ΋Ͱ͖Δ͕ɺSaaSΛ͔ͭͬͨ΄͏͕ૣ͍
    — FluentdͳͲϩάసૹͳͲͷઃఆ͕ඞཁ(ͳ৔߹΋)

    View Slide

  52. View Slide

  53. ͨΊͯɺ෼ੳ
    — ҟৗऴྃͷΤϥʔ͸र͏ͷ͕؆୯ͩΖ͏(ग़ͳ͍ʁग़ͦ͏ʂ)
    — ʮਖ਼ৗऴྃ͠·͕ͨ͠ͳ͍ʯ͜ͱ͸؂ࢹͰ͖Δ͔ʁ
    — ʮ։࢝͠·ͨ͠ʯͱ͔ϩά͍Βͳ͘Ͷ͑ʁ͓ͬͯ΋͏(ओ؍)͚ͲɺͪΌΜͱಈ͍͍ͯΔ͔
    Ͳ͏͔஌Γ͍ͨ(ຊؾͰͦ͏ࢥͬͯΔ)ͳΒඞཁ͔΋
    — ͜͏͍͏ͷ͸ϩάϓϥοτϑΥʔϜΛ࢖Θͳ͍ͱ؂ࢹɾूܭͰ͖ͳ͍
    — ࣮ߦ࣌ؒͱ͔΋ɺूܭͰ͖Ε͹ҙຯ͋ΔΑͶ
    — Ͱ΋͜Ε͸ϊΠδʔʹͳΓ͕ͪɺϩάϨϕϧ͸͛͞Α͏ɻ

    View Slide

  54. μογϡϘʔυԽ
    — ͞Βʹɺݟ͑ํΛม͑ͯΈΔͳͲ͕͋Δ
    — ϝτϦΫεʹͯ͠ΈΔɺʮ೏͍ʯΛײ͡Δ
    — ͋ΔσϓϩΠΛڥʹͯ͠૿͑ͨͱ͔
    — ͜Ε͸ϩάج൫΍ɺूܭͷγεςϜ͕ඞཁͰɺԿ౓΋ݴ͏͚ͲࣗલͰ΍Δͷ͸ͩΔ͍
    — ͜ͷ͋ͨΓ͸؂ࢹͷ͸ͳ͠ʹͳΔͷͰɺࠓճ͸ྦͷׂѪ

    View Slide

  55. View Slide

  56. ·ͱΊ
    — ʮϩά͸ɺԿ͔Λ͢ΔͨΊʯɺͦ͏͍͏ൃ૝Ͱॻ͜͏
    — ͱ͍ͬͯ΋ɺਓؒ͸ϩάΛݟͳ͍ͷͰʮϩά͕དྷ͍ʯͷ࣌୅
    — ͦ͏͢Δͱɺ৭ʑͳ΋ͷ͕ੜ͖ͯ͘Δ
    — ϩΨʔղੳɺϩά؅ཧπʔϧɺΞάϦήʔλΛ׆༻͢Δͱߴ౓ͳ͜ͱͰ͖Δ
    — (࠷ѱɺmonolog͚ͩͰ΋৭ʑͰ͖Δ)
    — ྑ͍ϩάઃܭͯ͠ɺྑ͍ӡ༻͍ͯ͜͠͏ͳʂʂ

    View Slide