ããã«ã¡ã¯ããã®ã¥ããæšé²éšãããã³ããšã³ããšã³ãžãã¢ã®æŠç°ã§ãã 仿¥ã¯ Datadog, Lighthouse ã䜿ã£ãã¯ã©ã€ã¢ã³ãããã©ãŒãã³ã¹èšæž¬ã«åãçµãã§ããããšããã話ã§ãã mediba ã§ã¯ webpagetest ã䜿ã£ã宿å®è¡ãšèšæž¬ã以åããè¡ã£ãŠããŸãã DataStudioãšGASã§WebPagetestã®èšæž¬çµæãã°ã©ãåãã uknmr/gas-webpagetest 玹ä»èšäº: gas-webpagetestã§WebPagetestã®ããã©ãŒãã³ã¹èšæž¬ãèªååãå¯èŠåãã 1 ã§ã®åãçµã¿ãããŒã¹ã«ãã clasp ã§ GAS ã®ãœãŒã¹ã³ãŒã管çã»ãããã€ãå®çŸããããã®ä»çµã¿ã webpagetest Lighthouse test ãšé£æºããã¡ããªã¯ã¹ã®ååŸãŸã§ç¶²çŸ
ãããã®ã 2 ã«ãªããŸãã ä»åã¯å°ã webpagetest ãšã¯è¶£åãå€ã㊠Lighthouse ã«ãã宿å®è¡ãšããã©ãŒãã³ã¹å€ååŸ Datadog API ãå©çšããã«ã¹ã¿ã ã¡ããªã¯ã¹ãžã® POST Datadog ã«ããå¯èŠå ã«ã€ããŠã玹ä»ããŸãã 宿œã«å¿
èŠãªãã® Datadog (Pro Plan or Enterprise Plan ã§ã®å¥çŽ) Node.js v10.13 以äžïŒçŸæç¹ïŒãChrome ãã€ã³ã¹ããŒã«ãããŠããå®è¡ç°å¢ Lighthouse 宿å®è¡ããä»çµã¿ è¶
ç°¡åãªèª¬æã§ãã Datadog ãšã¯? -> ã·ã¹ãã ç£èŠã®ããã® SaaS Lighthouse ãšã¯? -> ã¯ã©ã€ã¢ã³ãããã©ãŒãã³ã¹ã®ã¹ã³ã¢ãªã³ã°ããŒã« ã§ãã Lighthouse ã«ãã宿å®è¡ãšããã©ãŒãã³ã¹å€ååŸ webpagetest ã§ã¯ãªããªã Lighthouse ãªã®ã webpagetest ãå©çšããå Žåãèªåã®ãã©ã€ããŒãã€ã³ã¹ã¿ã³ã¹ãšããŠç«ãŠãããšãå¯èœã§ãããã³ã¹ããšã®å
Œãåãã§ãããªãã¯ã€ã³ã¹ã¿ã³ã¹ãšããŠååšãããªãŒãžã§ã³ãå©çšãããšããã·ãŒã³ãã©ãããŠããããŸããä»åã¯ãããã¯ã·ã§ã³ç°å¢ãšãããªãã¯ã«é²èЧãäžå¯èœã§ããã¹ããŒãžã³ã°ç°å¢ã®2ç°å¢ãæœçã«åãããŠæ¯èŒãããå¿
èŠããããããã©ãããŠããã®å¶éãã¯ãªã¢ã§ããŸããã ã¹ããŒãžã³ã°ç°å¢ãæ£åžžã«é²èЧã§ããïŒ=ãªã¯ãšã¹ããåãä»ããããïŒ Lighthouse å®è¡ã®ããã«å¿
èŠãª Node.js v10 以äžãåäœãã Lighthouse å®è¡ã®ããã« Chrome ãåäœãã ãããã宿çã«å®è¡ãã 以äžãå®çŸããããšãå¿
èŠããã§ãã ã©ãã§ Lighthouse 宿çã«åããã ã©ã³ã¿ã€ã ã Node.js v10.x ã«ãã lambda ããã㯠CodeBuild ã§ã¹ã¯ãªãããå®è¡ã宿ã¹ã±ãžã¥ãŒãªã³ã°ã CloudWatch Events ã«ãããšããããšãå¯èœããã§ããäžåºŠ CodeBuild æ³å®ã§ã³ã¹ããèšç®ããŠã¿ãŸããCodeBuild ã® OS image 㯠Chrome ãçŽ ã§å
¥ã£ãŠããŸãã ãå²ãšãªãã§ãå
¥ãæããããŸãã æé - AWS CodeBuild | AWS æ¯æããããããªè©Šç®ã®æ¡ä»¶ ãã€ãªãŒã§24åå®è¡æ³å® ãã«ãã«ãããæé 5 å ã€ã³ã¹ã¿ã³ã¹ã¿ã€ãã«äžçªé«ãã¯ã©ã¹ 1ååäœã§ 0.02 USD 24å/day * 30day * 5 å * 0.02 USD = 72 USD çŸæç¹ã¬ãŒãã§ 7,827 åãèªåãæ¯æããã£ãŠãããå°é£ãããåºããããšèšããããšåºããªãéé¡ãªã®ã§ä»å㯠AWS ç°å¢ã§ã®å®è¡ã諊ããŸãã ããããèããçµæãã»ãŒãŒãã³ã¹ãã§ä»äžããããéžæããã®ã¯ Travis CI ã§ããããšãã£ãŠãåŒç€Ÿã§ã¯ Travis CI Enterprise ã AWS ç°å¢äžã§åäœãããŠãããããã§å®è¡ãããæ³å®ã§ãïŒãªã®ã§è©³çްãè©°ãããããšãŒãã³ã¹ãã§ã¯ãªãã®ã§ããïŒã ãã æ®å¿µãªãã宿å®è¡ãå¶ãã Travis Cron Jobs ã¯ãªããžããªã®ãã©ã³ãæ¯ã«ããã¥ã¢ã«ã§æå®ããå¿
èŠãããã®ã§ããã¯æ®å¿µãªæãã«ãªããŸãã人éããããã GUI ããæå®ããŠå®æå®è¡ãå®çŸããããšã«ããŸãã Lighthouse ã¹ã¯ãªãã ããã³ããšã³ããšã³ãžãã¢ã®æ¹ã§ããš Chrome Devtools -> audit ã Lighthouse ã CLI ããå©çšããããšã¯äžåºŠã¯ãã£ãŠã¿ãããšããããšæãã®ã§ãããä»åã¯ããèŠãã¹ã³ã¢ãã»ããããã§ã¯ãªãç¹å®ã®ããã©ãŒãã³ã¹ã¡ããªã¯ã¹ãååŸããããšããæå³ã§ããå人çã«ã絶察çãªã¹ã³ã¢ãªã³ã°ãå
šãŠã ãšæã£ãŠããŸããã èšæž¬ãæ¯èŒãåäžããŠããããäžçªéèŠã§ãããšæã£ãŠããŸã ã ããã°ã©ããã«ã« Ligththouse ãæäœããŠãããŸããã å®ã¯ã»ãšãã©ããã¥ã¡ã³ãã«ãã£ããããã®ã§ ãåèã«ååŸããŠããã©ãŒãã³ã¹å€ãããéããŠã¿ãŸãã const lighthouse = require('lighthouse'); const log = require('lighthouse-logger'); const chromeLauncher = require('chrome-launcher'); const opts = { chromeFlags: ["--headless", "--disable-gpu"], logLevel: "info" }; log.setLevel(opts.logLevel); launchChromeAndRunLighthouse("https://stg.example.com", opts).then(results => { // äžæŠæšæºåºåã«è¡šç€º console.table(results); }); function launchChromeAndRunLighthouse(url, opts, config = null) { return chromeLauncher.launch({chromeFlags: opts.chromeFlags}).then(chrome => { opts.port = chrome.port; return lighthouse(url, opts, config).then(results => { // results.lhr ã¯ããèŠãã¹ã³ã¢ãªã³ã°ã®å
ããŒã¿ // https://github.com/GoogleChrome/lighthouse/blob/master/types/lhr.d.ts const { "time-to-first-byte": ttfb, "first-contentful-paint": fcp, "first-meaningful-paint": fmp, "speed-index": speedindex, interactive, metrics, } = results.lhr.audits; return chrome.kill().then(() =>({ TTFB: Math.round(ttfb.numericValue), FIRST_PAINT: metrics.details.items[0].observedFirstPaint, FMP: Math.round(fmp.numericValue), FCP: Math.round(fcp.numericValue), SPEED_INDEX: Math.round(speedindex.numericValue), TTI: Math.round(interactive.numericValue), })); }); }); } Lighthouse å®è¡æã® Promise.resolve ã§è¿åŽããã results ã¯åå®çŸ©ããã ãæšä»ã®ãšãã£ã¿è£å®ã®æ©æµãåãããšå€§å€ DX ãè¯ãã®ã§ãããå¿
èŠãªæ°å€ã¯æ£çŽã©ãã«æ ŒçŽãããŠãããæ¢ãã»ããªãã®ã§ãCLI ã§äžåºŠ JSON ãã¡ã€ã«ãææç©ãšããŠå®è¡ããŠããæ¢ãã®ãäžçªæã£åãæ©ãã§ããåãåãããã¹ã¯ãªãŒã³ã·ã§ããã®æ
å ±ã Base64 ã§ãšã³ã³ãŒãããæ ŒçŽãããŠãã ã®ã§éã£ã工倫ãã§ãããã§ã¯ãããŸãã ãããŸã§ã§ Lighthouse åŽã®æºåã¯æŽã£ãã®ã§æ¬¡ã« Datadog åŽãæºåããŸãã Datadog API ãå©çšããã«ã¹ã¿ã ã¡ããªã¯ã¹ãžã® POST ãããããªã Datadog ãéžã¶ã®ã æ
åœãããããã¯ãã®ã·ã¹ãã ã¢ãã¿ãªã³ã°ãšããŠçŸåšå©çšããŠããïŒä»ã®ãããžã§ã¯ãã§ã®å©çšå®çžŸããããŸãïŒãã€ã³ãã°ã¬ãŒã·ã§ã³ã API 飿ºã«ã€ããŠåŠã³ãããšããã®ãšãå€ã®ãããããšå¯èŠåã Datadog äžæ¬ã«ãã¡ããã°äŸ¿å©ã ãèŠããšããå°ãªããŠããããããïŒ ãšããã®ã倧ããªã¢ãããŒã·ã§ã³ã§ãã ç§ã掻åããã¡ã€ã³ãã£ãŒã«ãã¯ããã³ããšã³ããªã®ã§ãããããŒã ã§ã¯å±äººåãé¿ããããç£èŠãã¢ã©ãŒã察å¿ã»èª¿æ»ãå«ããã¢ããéããŠæé»ç¥ããªããããšããåãçµã¿ãããŠããç¹ã Datadog ãåè£ã«ããçç±ã§ãã Datadog API ãšã«ã¹ã¿ã ã¡ããªã¯ã¹ã®å©ç𠿬¡ã¯Datadog API ã䜿ã£ãŠã«ã¹ã¿ã ã¡ããªã¯ã¹ãäœã POST ããŸããããŸã㯠API key, APP key ãå¿
èŠã«ãªã£ãŠããŸãã ããã²ãŒã·ã§ã³ãã Intergrations -> APIs API key, APP key ååŸ å®éã«ãªã¯ãšã¹ããéãé㯠node-dogapi ãšããã®ãããã®ã§ãã¡ããå©çšããŠã¿ãŸãã åæå const datadog = require("dogapi"); // ç°å¢å€æ°ã« Datadog API key, Datadog App key ãã»ãããããŠããæ³å® datadog.initialize({ api_key: process.env.DATADOG_API_KEY, app_key: process.env.DATADOG_APP_KEY, }); ã«ã¹ã¿ã ã¡ããªã¯ã¹ãžã®éä¿¡ ä»»æã®æååãã«ã¹ã¿ã ã¡ããªã¯ã¹åãšããŠãåéããå€ãããããããŠãããŸãããªã以äžã®ã³ãŒãã¯å
ã»ã©åºåã«çµæã衚瀺ãããããã¯ã§å©çšããæ³å®ã§ããã¿ã°åã«é¢ããŠã¯ç¹å®ã®èŠçŽ ã«çŽã¥ãçµã蟌ã¿ãç®çãšããŠå©çšãæšå¥šããŠããããã§ãå
¬åŒã«ãããéããããã¯ã·ã§ã³ç°å¢ãã¹ããŒãžã³ã°ç°å¢ã®çš®å¥ãšããŠã¿ã®ã³ã°ããŸããã¿ã°ã®ã«ãŒã«ãšããŠã¯ <KEY>:<VALUE> ãšããã«ãŒã«ã«ãªããŸãã åç
§ const { TTFB, FIRST_PAINT, FMP, FCP, SPEED_INDEX, TTI, } = results; const tags = "env:staging"; datadog.metric.send_all([ { metric: "webperf.measure.ttfb", points: TTFB, tags, }, { metric: "webperf.measure.first_paint", points: FIRST_PAINT, tags, }, { metric: "webperf.measure.fmp", points: FMP, tags, }, { metric: "webperf.measure.fcp", points: FCP, tags, }, { metric: "webperf.measure.speed_index", points: SPEED_INDEX, tags, }, { metric: "webperf.measure.tti", points: TTI, tags, }, ], (err, results) => { if (err) { console.log(`Error: ${JSON.stringify()}`); process.exit(1); } console.log(`Results: ${JSON.stringify(results, null, 4)}`); }); ãããŸã§ã®ãã®å®è¡ã§ããã° Datadog ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹ã«å€ãããããããå¯èŠåããããŒã¿ã¯åºæ¥ãããšã«ãªããŸãã Datadog ã«ããå¯èŠå ããã·ã¥ããŒããäœæ æ°ããããã·ã¥ããŒããäœæãã°ã©ããäœãæºåãããŸãã Timeborad: æç³»åã«ã€ãã³ãã°ã©ããé²èЧãã¬ã€ã¢ãŠããèªå Screenboard: ã¹ããŒã¿ã¹ãã°ã©ããªã©ããŒã¿ãšããŠæ··åããããã®åãã§ã¬ã€ã¢ãŠãããã¬ãã·ãã« 2ã€ããéžã¹ãŸããã奜ããªæ¹ãéžãã§èª¿æŽããŠãã ããã ããã·ã¥ããŒãã«ãŠã£ãžã§ããã远å ã°ã©ãã§å¯èŠåããå Žå㯠Timeseries ãšãããŠã£ãžã§ããã䜿çšããŸãã ãŠã£ãžã§ããã§ããããšãããã¿ã°ã§ã®çµã蟌ã¿ãªæ°ãããŸããããã¿ã°ããµãžã§ã¹ããããªããªã©ããŸããããªãããã§ããã </> ã¢ã€ã³ã³ãæŒäžã㊠raw text ã§ã®å€æŽã«åãæ¿ãããš avg:webperf.measure.ttfb{key:value} ã®ãããªå
¥åãå¯èœã«ãªãã®ã§è©ŠããŠã¿ããšè¯ããããããŸããã æè¿ããèããããªããã©ãŒãã³ã¹ããžã§ãããéŸå€ãšããŠå®ããŠãéŸå€ãããªãŒããŒããã Warning 衚瀺ã«ããããªããã€éŸå€ãè¶
ããéã«ã¢ãã¿ãªã³ã°ã«ãã£ãŠ Slack ã«éç¥ãããšãã£ãããšãå¯èœã§ãã Google Developers Japan: ããã©ãŒãã³ã¹ããžã§ããã®ãçŽ¹ä» - ãŠã§ãããã©ãŒãã³ã¹ã®ããã®äºç®ç®¡ç ããã·ã¥ããŒãã¯ä»ã®ãšããã·ã³ãã«ã§ãããããªæãã«ãªã£ãŠããŸãã æ¥ã
ããããããã°ã©ããå¯èŠåã远ãããããæ°å€ãšãéèŠèŠãããå€ã»ããžã§ãããå®ããŠãã«ãã«ãšè¡šç€ºãããèŠæ ãã¯ãããããŸãããå®åã«äºè¶³ãããã®ã«ãªã£ãŠããŸãã ãŸãšã Lighthouse ããç¹å®ã®å€ãååŸãDatadog API ã䜿ã£ãã«ã¹ã¿ã ã¡ããªã¯ã¹ãžã® POSTãDatadog å
ã§ã®å¯èŠåã«ã€ããŠæžãããŠããã ããŸããã Datadog ã®ã«ã¹ã¿ã ã¡ããªã¯ã¹å©çšã¯ Pro/Enterprise ãã©ã³ã®ã¿ ææ©ãäœã³ã¹ãã§å®æå®è¡ããããªã CI ã®ãµãŒãã¹å©çšãæ€èš Lighthouse ã®å®è¡çµæããã¯ããã©ãŒãã³ã¹å€ããã®ä»ïŒã¹ã¯ã·ã§ãªã©ïŒãååŸã§ãã Datadog API ã®å©çšã¯ç°¡åïŒåçš®èšèªã®ã©ã€ãã©ãªçãæã£ãŠããå
å®ïŒ ããã·ã¥ããŒããæ°è»œã§ç°¡åã«å¯èŠåã§ãã ä»å㯠Datadog ã®ãã©ã³æ¬¡ç¬¬ãšãããšããããããŸããããŸãã¯äœã³ã¹ãã§ããã©ãŒãã³ã¹å®æèšæž¬ãããã©ãŒãã³ã¹ããžã§ããã®èšå®ãªã©ã«åãçµãã§ã¿ãŠã¯ãããã§ããããã