
ãã¹ãŠã®éçºè
ã¯ãã¢ããªã±ãŒã·ã§ã³ã«ãã°ãããããŠãŒã¶ãŒãå¿
èŠãªããšãå®è¡ã§ããªãç¶æ³ãèªèããŠããŸãã çç±ã¯ç°ãªããŸãããŠãŒã¶ãŒãééã£ãããŒã¿ãå
¥åãããã€ã³ã¿ãŒãããæ¥ç¶ãé
ãããªã©ã§ãã ãã®ã³ã°ã·ã¹ãã ããªããã°ããããã®ãšã©ãŒã解æããããšã¯é£ãããæã«ã¯äžå¯èœã§ãã äžæ¹ããã®ã³ã°ã·ã¹ãã ã¯ãã·ã¹ãã å
ã®åé¡é åã®åªããææšã§ãã ç§ã®ãããžã§ã¯ãã§ãã®ã³ã°ã·ã¹ãã ãæ§ç¯ããæ¹æ³ã説æããŸãïŒã¯ãïŒã ãã®èšäºã§ã¯ãElasticsearch + Logstash + Kibanaããã³Prometheusãšãããããã¢ããªã±ãŒã·ã§ã³ã«çµ±åããæ¹æ³ã«ã€ããŠèª¬æããŸãã
2GISã¯ãçµç¹ã®Webãããããã³ãã£ã¬ã¯ããªã§ãã äŒç€Ÿã«ã¯ãåçãå²åŒãããŽãªã©ã®è¿œå ã³ã³ãã³ããããå ŽåããããŸãã ãããŠãããžãã¹ãªãŒããŒããã®è¯ããã®ã管çããã®ã䟿å©ã§ããããã«ãå人ã¢ã«ãŠã³ããäœæãããŸããã å人ã¢ã«ãŠã³ãã䜿çšãããšã次ã®ããšãã§ããŸãã
- çµç¹ã®é£çµ¡å
ãè¿œå ãŸãã¯å€æŽãã
- åçãããŽãã¢ããããŒããã
- çµç¹ãéãããšãã®ãŠãŒã¶ãŒã®è¡åãªã©ã確èªããŸãã
ç§ã®ã¢ã«ãŠã³ãã¯ãããã¯ãšã³ããšããã³ããšã³ãã®2ã€ã®ãããžã§ã¯ãã§æ§æãããŠããŸãã ããã¯ãšã³ãã¯ãYii 1ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠãPHPããŒãžã§ã³5.6ã§èšè¿°ãããŠããŸãïŒã¯ããã¯ãïŒã ç§ãã¡ã¯ç©æ¥µçã«omposerã䜿çšããŠããããžã§ã¯ãå
ã®äŸåé¢ä¿ã管çããPSR-4ãåå空éãç¹æ§ã«åŸã£ãŠã¯ã©ã¹ãèªåããŒãããŸãã å°æ¥ãPHPã®ããŒãžã§ã³ã7ã«ã¢ããã°ã¬ãŒãããäºå®ã§ãã NginxãWebãµãŒããŒãšããŠäœ¿çšããããŒã¿ãMongoDBãšPostgreSQLã«ä¿åããŸãã ããã³ããšã³ãã¯JavaScriptã§èšè¿°ãããŠããã Catbeeã®æºåã®ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠããŸãã ããã¯ãšã³ãã¯ãããã³ããšã³ãçšã®APIãæäŸããŸãã ããã«ã¬ããŒãã§ã¯ãããã¯ãšã³ãã«ã€ããŠã®ã¿èª¬æããŸãã
ãããçµ±åã®å³ã§ãã æ空ãæãåºãããŸãã ããèŠããšãåæäžæãèŠããŸãã

å€éšãµãŒãã¹ã¯ç°çš®ã§ã-ãããã¯ãç¬èªã®æè¡ã¹ã¿ãã¯ãšAPIã䜿çšããŠãå€æ°ã®ããŒã ã«ãã£ãŠéçºãããŸãã çµ±åã·ããªãªã¯éèªæã§ã-æåã«1ã€ã®ãµãŒãã¹ã«è¡ããããŒã¿ãååŸããããžãã¹ããžãã¯ã課ããæ°ããããŒã¿ã§ããã«ããã€ãã®ãµãŒãã¹ã«è¡ããçããçµã¿åãããŠããã³ããšã³ãã«çµæãäžããŸãã ãŸãããŠãŒã¶ãŒãåé¡ãæ±ããŠãããããšãã°åºåãã£ã³ããŒã³ã延é·ãããªã©ã®ç®çãéæã§ããªãå Žåããã®ã³ã°ã·ã¹ãã ããªããšåé¡ã®å Žæãææ¡ã§ããŸãã-ããŒã¿ãå€éšãµãŒãã¹ã«èª€ã£ãŠéä¿¡ããããåçã誀ã£ãŠè§£éããããå€éšãµãŒãã¹ãå©çšã§ããªããã誀ã£ãŠããžãã¹ããžãã¯ã課ããŸãã
ãšã©ãŒãã°ããããŸããããæ°ãããµãŒãã¹ã®åºçŸã«ãããçµ±åã远跡ããæ°ããªåé¡ã«é¢ããæè¡ãµããŒããªã¯ãšã¹ãã«å¯Ÿå¿ããããšããŸããŸãå°é£ã«ãªããŸããã ãã®ããããã°ã·ã¹ãã ã®æ°ããèŠä»¶ãéçºããŸããã
- ãšã©ãŒã«é¢ããããå€ãã®ã³ã³ããã¹ããå¿
èŠã§ã-äœãçºçããã©ã®ãŠãŒã¶ãŒã§ãããã
- 䟿å©ãªæ¹æ³ã§çä¿¡ãªã¯ãšã¹ããåéããŸãã
- ã¡ãœãããé·æéå¿çããå Žåã¯ãããŒã ã«éç¥ããå¿
èŠããããŸãã
ãšã©ãŒãã°
æŽå²çã«ãåœç€Ÿã¯ãã°ãåéããŠè¡šç€ºããããã«ã Elasticsearch + Logstash + Kibanaãã¯ãããžãŒã¹ã¿ãã¯ïŒç¥ããŠELKïŒã䜿çšããŠããŸãã Elasticsearch-å
šææ€çŽ¢æ©èœãåããNoSQLããã¥ã¡ã³ããªããžããªã Logstashã¯ãTCP / UDPãããã³ã«ãä»ããŠãã°ãåä¿¡ããRedisããã¡ãã»ãŒãžãèªã¿åããElasticsearchã«ä¿åããããã«æ§æãããŠããŸãã Kibanaã¯ãåéãããããŒã¿ãæ€çŽ¢ããã³è¡šç€ºããããã®èŠèŠçãªã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŸãã
ã¯ã©ã€ã¢ã³ãã§äœãåé¡ãçºçããå Žåã圌ã¯åé¡ã®èª¬æãšãšãã«ã¢ã«ãŠã³ããããã¯ãã«ã«ãµããŒãã«é£çµ¡ããŸãã ãšã©ãŒãã®ã³ã°ããããŸãããããŠãŒã¶ãŒã®ã¡ãŒã«ãAPIã¡ãœããã®åŒã³åºããåŒã³åºãã¹ã¿ãã¯ã¯ãããŸããã§ããã ã¡ãã»ãŒãžã«ã¯ãããªã¯ãšã¹ãã誀ã£ãçµæãè¿ããŸããããšãã圢åŒã®æªåŠçã®äŸå€ããã®è¡ã®ã¿ããããŸããã ãã®ãããã¯ã©ã€ã¢ã³ããé£çµ¡ããæéãšããŒã¯ãŒãã§åé¡ãæ€çŽ¢ããŸããããããã¯å¿
ãããæ£ç¢ºã§ã¯ãããŸããã§ãã-ã¯ã©ã€ã¢ã³ãã¯1æ¥ã§é£çµ¡ãåãããšãã§ããæ¯æŽããã®ã¯éåžžã«å°é£ã§ããã
èŠçã®åŸãç§ãã¡ã¯äœããããå¿
èŠããããšå€æããå¿
èŠãªæ
å ±ãè¿œå ããŸãã-ãŠãŒã¶ãŒã®ã¡ãŒã«ãAPIã¡ãœããããªã¯ãšã¹ãæ¬æãã³ãŒã«ã¹ã¿ãã¯ããªã¯ãšã¹ããåŠçããã³ã³ãããŒã©ãŒãšã¢ã¯ã·ã§ã³ã ãã®çµæããã¯ãã«ã«ãµããŒããšç§ãã¡èªèº«ã®ç掻ãç°¡çŽ åããŸãã-ãŠãŒã¶ãŒã®ã¡ãŒã«ãå²åŒãããã°ãšã³ããªãèŠã€ããŠåé¡ã«å¯ŸåŠããŸãã ã©ã®ãŠãŒã¶ãŒãåé¡ãèµ·ãããããã©ã®ã¡ãœãããåŒã³åºããããããããŠã³ãŒãã®ã©ã®éšåããããåŠçããããæ£ç¢ºã«ææ¡ããŠããŸãã æµéææã«ããæ¯èŒãªãïŒ
ã¢ããªã±ãŒã·ã§ã³ãã°ã¬ã€ãã°æ¡åŒµãã°åœ¢åŒïŒç¥ããŠGELFïŒã§UDPã§å®è¡ãããŠãããšãã«ãšã©ãŒã¡ãã»ãŒãžãéä¿¡ããŸãã ãã®åœ¢åŒã¯ãäžè¬çãªã¢ã«ãŽãªãºã ã§ã¡ãã»ãŒãžãå§çž®ããŠéšåã«åå²ã§ãããããã¢ããªã±ãŒã·ã§ã³ããLogstashã«éä¿¡ããããã©ãã£ãã¯ã®éãæžããããšãã§ããç¹ã§åªããŠããŸãã UDPãããã³ã«ã¯ã¡ãã»ãŒãžé
ä¿¡ãä¿èšŒããŸããããå¿çæéã«æå°éã®ãªãŒããŒãããã課ãããããã®ãªãã·ã§ã³ãé©ããŠããŸãã ã¢ããªã±ãŒã·ã§ã³ã§ã¯ã gelf-phpã©ã€ãã©ãªã䜿çšããŸããããã¯ãããŸããŸãªåœ¢åŒãšãããã³ã«ã§ãã°ãéä¿¡ããæ©èœãæäŸããŸãã PHPã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããããšããå§ãããŸãã
çµè«-ã¢ããªã±ãŒã·ã§ã³ãå€éšãŠãŒã¶ãŒãšé£æºããæ°ããªæè¡ãµããŒãã®è³ªåãžã®åçãæ¢ãå¿
èŠãããå Žåã¯ãã¯ã©ã€ã¢ã³ããšãã®ã¢ã¯ã·ã§ã³ãèå¥ããã®ã«åœ¹ç«ã€æ
å ±ãèªç±ã«è¿œå ããŠãã ããã
ã¡ãã»ãŒãžã®äŸïŒ
{ "user_email": "test@test.ru", "api_method": "orgs/124345/edit", "method_type": "POST", "payload": "{'name': ' '}", "controller": "branches/update", "message": "Undefined index: 'name' File: /var/www/protected/controllers/BranchesController.php Line: 50" }
ãã®ã³ã°ã®ãªã¯ãšã¹ã
æ§é åããã圢åŒã®ãªã¯ãšã¹ãã®ãã®ã³ã°ãšçµ±èšæ
å ±ã®åéããªãã£ããããã©ã®ã¡ãœãããæãé »ç¹ã«åŒã³åºãããã©ã®ãããå¿çãããã¯æ確ã§ã¯ãããŸããã§ããã ããã«ããã次ã®ããšãã§ããŸããã§ããã
- ã¡ãœããã®èš±å®¹å¯èœãªå¿çæéãæšå®ããŸãã
- ãã¬ãŒãã®åå ã¯ãç§ãã¡ã®åŽã«ããã®ããå€éšãµãŒãã¹ã®åŽã«ããã®ãïŒæ空ã®ã¹ããŒã ãèŠããŠããŸããïŒïŒ
- ã©ãããã°ã³ãŒããæé©åããŠå¿çæéãççž®ã§ããŸããã
ãã®ã¿ã¹ã¯ã®äžç°ãšããŠã次ã®åé¡ã解決ããå¿
èŠããããŸããã
- ãã®ã³ã°çšã®å¿çãã©ã¡ãŒã¿ãŒã®éžæ
- ãã©ã¡ãŒã¿ãŒãLogstashã«éä¿¡ãã
Nginx WebãµãŒããŒã䜿çšããã¢ã¯ã»ã¹ãã°ããã¡ã€ã«ã«æžã蟌ãããšãã§ããŸãã æåã®åé¡ã解決ããããã«ãæ§æã«ãã°ãä¿åããããã®æ°ãã圢åŒã瀺ãããŸããã
log_format main_logstash '{' '"time_local": "$time_local",' '"request_method": "$request_method",' '"request_uri": "$request_uri",' '"request_time": "$request_time",' '"upstream_response_time": "$upstream_response_time",' '"status": "$status",' '"request_id": "$request_id"' '}'; server { access_log /var/log/nginx/access.log main_logstash; }
ã»ãšãã©ã®ã¡ããªãã¯ã¯ã質åãæèµ·ãããã®ã§ã¯ãªããšæããŸããæãèå³æ·±ããã®ã$ request_idã«ã€ããŠè©³ãã説æããŸãã ããã¯ããªã¯ãšã¹ãããšã«Nginxã«ãã£ãŠçæãããäžæã®èå¥åãããŒãžã§ã³4 UUIDã§ãã ãªã¯ãšã¹ãå
ã®ãã®ããããŒãå€éšãµãŒãã¹ã«è»¢éããä»ã®ãµãŒãã¹ã®ãã°ã§ãªã¯ãšã¹ãã®å¿çã远跡ã§ããŸãã ä»ã®ãµãŒãã¹ã®åé¡ãæ€çŽ¢ãããšãã«éåžžã«äŸ¿å©ã§ã-æéã®æ¯èŒã¯ãããŸãããåŒã³åºãããã¡ãœããã®URLã
Logstashã«ãã°ãéä¿¡ããã«ã¯ã BeaverãŠãŒãã£ãªãã£ã䜿çšããŸãã ãã°ãéä¿¡ããäºå®ã®ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ããŒãã«ã€ã³ã¹ããŒã«ãããŸãã æ§æã¯ãæ°ãããã°ãåä¿¡ããããã«è§£æããããã¡ã€ã«ã瀺ããåã¡ãã»ãŒãžãšãšãã«éä¿¡ããããã£ãŒã«ãã瀺ãããŸãã ã¡ãã»ãŒãžã¯Redisã¯ã©ã¹ã¿ãŒã«éä¿¡ãããããããLogstashãããŒã¿ãåéããŸãã Beaverã®èšå®ã¯æ¬¡ã®ãšããã§ãã
[/var/log/nginx/access.log] type: nginx_accesslog add_field: team,lk,project,backend tags: nginx_json
Logstashã®ãã£ãŒã«ããã¿ã€ãããã³ã¿ã°ä»ãããããšã«ãããå€ã«å¿ããŠããã°ã®ãã£ã«ã¿ãªã³ã°ãšåŠçãè¡ãããããããããã®å€ãç¬èªã®ãã®ã«ããããšãã§ããŸãã ããã«ãããŒã ãšãããžã§ã¯ãã®ãã£ãŒã«ããè¿œå ããŠããã°ãå±ããããŒã ãšãããžã§ã¯ããèå¥ã§ããããã«ããŸãã
ã¢ã¯ã»ã¹ãã°ãåéããããšãåŠãã ã®ã§ãSLAã¡ãœããã®å®çŸ©ã«é²ã¿ãŸããã ãµãŒãã¹æäŸã®ã¬ãã«ã«é¢ããåæã§ããSLAã¯ããã®å Žåãã¡ãœããã®å¿çæéã®95ããŒã»ã³ã¿ã€ã«ã0.4ç§ä»¥äžã§ããããšãä¿èšŒããŸãã 蚱容æéã«åãŸããªãå Žåãã¢ããªã±ãŒã·ã§ã³ã®ããããã®çµ±åãé
ããªããé¢é£ããããŒã ã«åããããã³ãŒãã«äœããã®åé¡ããããæé©åãå¿
èŠã§ããããšãæå³ããŸãã
ã¢ã¯ã»ã¹ãã°ã®åéã«é¢ããçµè«-æãé »ç¹ã«åŒã³åºãããã¡ãœãããšãããã®èš±å®¹å¯èœãªå¿çæéã決å®ããŸããã
以äžã¯ã枬å®ãããã¡ãœããã®1ã€ã«é¢ããã¬ããŒãã®äŸã§ãã æå-å¿çæéãšå¹³åå¿çæéã®50ã95ã99ããŒã»ã³ã¿ã€ã«ã¯äœã§ããïŒ

å¿çã¹ããŒã¿ã¹ãã£ãŒãïŒ

äžå®æéã®å¹³åå¿çæéïŒ

SLAããŒã ã¢ã©ãŒã
ãã°ãåéããåŸãé床ã®äœäžã«ã€ããŠããã«èª¿ã¹ãå¿
èŠããããšããèããåŸãããŸããã Kibanaã§ãã©ãŠã¶ãåžžã«éãããŸãŸã«ããF5ãæŒããŠã95ããŒã»ã³ã¿ã€ã«ã®çŸåšã®å€ãšæå¹ãªå€ãæ¯èŒããããšã¯ãããŸãå®çšçã§ã¯ãªãããšãå€æããŸããã ãããã£ãŠãã¢ã©ãŒããçæããããã«ãPrometheusã·ã¹ãã ãšã®çµ±åãè¿œå ããŸããã Prometheusã¯ãå®è¡äžã®ã¢ããªã±ãŒã·ã§ã³ã®ã¡ããªãã¯ãåéãä¿åãåæããããã®ãªãŒãã³ãœãŒã¹ã·ã¹ãã ã§ãã ããã¥ã¡ã³ãã®ããå
¬åŒãµã€ã ã
ããªã¬ãŒãçºçããå Žåãé»åã¡ãŒã«ã§ã¢ã©ãŒããéä¿¡ã§ãããšããç¹ã§ãã·ã¹ãã ãæ°ã«å
¥ããŸããã ãã®æ©äŒã¯ããµãŒããŒãžã®ã¢ã¯ã»ã¹ã«åé¡ããªããã¢ã©ãŒããçæããã«ã¹ã¿ã ã¹ã¯ãªãããèšè¿°ããããšãªããããã«äœ¿çšã§ããŸãã ã·ã¹ãã ã¯Goã§èšè¿°ãããŠãããäœæè
ã¯SoundCloudã§ãã GoãPHPãPythonãLuaãCïŒãErlangãHaskellãªã©ãããŸããŸãªèšèªã§ã¡ããªãã¯ãåéããããã®ã©ã€ãã©ãªããããŸãã
Prometheusãã€ã³ã¹ããŒã«ããŠå®è¡ããæ¹æ³ã«ã€ããŠã¯èª¬æããŸããã ããã«èå³ãããã°ã èšäºãèªãããšããå§ãããŸã ã ç§ãã¡ã«ãšã£ãŠå®éã«éèŠãªãã€ã³ãã«çŠç¹ãåœãŠãŸãã
çµ±åã¹ããŒã ã¯æ¬¡ã®ããã«ãªããŸããã¢ãã¬ã¹ã®ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã¯äžé£ã®ã¡ããªãã¯ãæäŸããPrometheusã¯ãã®ã¢ãã¬ã¹ã«ç§»åããŠããªããžããªã®ã¡ããªãã¯ãååŸããŠä¿åããŸãã

ã¡ããªãã¯ãã©ã®ããã«èŠãããèŠãŠã¿ãŸãããã

- ååã¯ã調æ»å¯Ÿè±¡ã®ç¹æ§ã®èå¥åã§ãã ããšãã°ãçä¿¡ãªã¯ãšã¹ãã®æ°ã
- äžåºŠã®ã¡ããªãã¯ã«ã¯ç¹å®ã®æå³ããããŸãã ã¡ããªãã¯ãåéãããšããæéãããã¡ããŠã¹ãäžãããŸãã
- ã¡ããªãã¯ã«ã¯ã©ãã«ãä»ããããšãã§ããŸãã åéãããæ°ã«é¢ããè¿œå æ
å ±ãå«ãŸããŠããŸãã ãã®äŸã¯ãã¢ããªã±ãŒã·ã§ã³ããŒããšAPIã¡ãœããã瀺ããŠããŸãã ã©ãã«ã®äž»ãªæ©èœã¯ãã©ãã«ãæ€çŽ¢ããŠå¿
èŠãªããŒã¿ãµã³ãã«ãäœæã§ããããšã§ãã
æéå€åœ¢åŒã®ããŒã¿ã¹ãã¢ã¯ãæç³»åããŒã¿ããŒã¹ãšåŒã°ããŸãã ããã¯ãæå€ã¡ããªãã¯ãæ ŒçŽããããã®é«åºŠã«å°éåãããNoSQLãªããžããªã§ãã ããšãã°ããµã€ãã®åå10æã1æ¥ã1é±éãªã©ã®ãŠãŒã¶ãŒæ°ã 解決ãããã¿ã¹ã¯ã®è©³çŽ°ãšã¹ãã¬ãŒãžæ¹æ³ã«ããããã®ãããªããŒã¿ããŒã¹ã¯é«æ§èœã§ã³ã³ãã¯ããªããŒã¿ã¹ãã¬ãŒãžãæäŸããŸãã
Prometheusã¯ãããã€ãã®ã¿ã€ãã®ã¡ããªãã¯ããµããŒãããŠããŸãã CounterãšåŒã°ããæåã®ã¿ã€ããæ€èšããŠãã ããã æ°ãã枬å®ã®ã«ãŠã³ã¿ãŒã®å€ã¯åžžã«å€§ãããªããŸãã å±¥æŽå
šäœã®çä¿¡ãªã¯ãšã¹ãã®ç·æ°ã枬å®ããã®ã«çæ³çã§ã-ä»æ¥ã§ã¯åèšãªã¯ãšã¹ãã100ã§ãææ¥ã¯80ã«æžå°ããããšã¯ã§ããŸããã
ããããå¿çæéã®æž¬å®ã¯ã©ãã§ããããïŒ ããã¯å¿
ãããæé·ããããã§ã¯ãªããããã«ãèœã¡ãŠãã°ããã®éäžå®ã®ã¬ãã«ã«ãªãããã®åŸæé·ããå¯èœæ§ããããŸãã å€æŽã¯10ç§æªæºã§çºçããå¯èœæ§ããããåãªã¯ãšã¹ãã®å¿çæéãå€æŽãããã€ããã¯ã¹ã確èªããããšèããŠããŸãã 幞ããªããšã«ããã¹ãã°ã©ã ã®ã¿ã€ãããããŸãã 圢æã®ããã«ãå¿çæéã枬å®ããééã決å®ããå¿
èŠããããŸãã ãã®äŸã§ã¯ã0.1ã0.5ç§ããããŸãããããã¯ãã¹ãŠInfinityãšèŠãªãããŸãã
ãã¹ãã°ã©ã ã®åæç¶æ
ã¯æ¬¡ã®ãšããã§ãã
api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.1"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.2"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.3"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.4"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.5"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="+Inf"} 0 api_request_time_sum{node="api1.2gis.com",handler="/users"} 0 api_request_time_count{node="api1.2gis.com",handler="/users"} 0
ééã®å€ããšã«ãç¹å®ã®ã«ãŒã«ã«åŸã£ãŠã«ãŠã³ã¿ãŒãäœæããŸãã
- ååã«ã¯_bucketæ¥å°ŸèŸãå«ãŸããŠããå¿
èŠããããŸã
- ééã®å€ã瀺ããã¡ã€ã«ã©ãã«ãå¿
èŠã§ãã ããã«ãå€ã+ Infã®ã«ãŠã³ã¿ãŒãå¿
èŠã§ãã
- æ¥å°ŸèŸ_sumããã³_countãæã€ã«ãŠã³ã¿ãŒãå¿
èŠã§ãã ãã¹ãŠã®å¿çã®åèšæéãšãªã¯ãšã¹ãã®æ°ãä¿åããŸãã PrometheusããŒã«ã䜿çšãã95ããŒã»ã³ã¿ã€ã«ã®äŸ¿å©ãªèšç®ã«å¿
èŠã§ãã
ãã¹ãã°ã©ã ãå¿çæéã§æ£ããåããæ¹æ³ãèããŠã¿ãŸãããã ãããè¡ãã«ã¯ãã©ãã«leã®å€ãå¿çæé以äžã§ããã·ãªãŒãºãèŠã€ãããããã1å¢ãããŸãã ã¡ãœããã0.4ç§ã§å¿çãããšããŸãã ã©ãã«leã0.4以äžã®ã«ãŠã³ã¿ãŒãèŠã€ããå€ã«1ãè¿œå ããŸãã
api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.1"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.2"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.3"} 0 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.4"} 1 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="0.5"} 1 api_request_time_bucket{node="api1.2gis.com",handler="/users",le="+Inf"} 1 api_request_time_sum{node="api1.2gis.com",handler="/users"} 0.4 api_request_time_count{node="api1.2gis.com",handler="/users"} 1

ã¡ãœããã0.1ç§ãæ
åœããå Žåããã¹ãŠã®ã·ãªãŒãºãå¢ãããŸãã 0.6ç§ã®è²¬ä»»ãããå Žåã¯ãå€ã+ Infãã§ã®ã¿ã«ãŠã³ã¿ãå¢ãããŸãã ã«ãŠã³ã¿ãŒapi_request_time_sumããã³api_request_time_countãå¢ããããšãå¿ããªãã§ãã ããã ãã¹ãã°ã©ã ã䜿çšããŠãå¿çæéã枬å®ã§ããŸããå¿çæéã¯ãå€ãã®å Žåçæéã§å€åããŸãã
Prometheusã¯ãã¹ã±ãŒã«ãšçµæã®æŠèŠãšãã2ã€ã®ã¿ã€ãã®ã¡ããªãã¯ããµããŒãããŠããŸãã ã¹ã±ãŒã«ã¯ãå€ãå¢æžã§ããç¹æ§ãè¡šããŸãã ãã®ãããªææšã¯ããåœã§ã¯æž¬å®ãããªããããã¿ã¹ã¯ã§ã¯äœ¿çšããŸããã çµæã®æŠèŠã¯ãã¢ããªã±ãŒã·ã§ã³åŽã§èšç®ãããåäœãä¿åããé«åºŠãªãã¹ãã°ã©ã ã§ãã çè«çã«ã¯ã95ããŒã»ã³ã¿ã€ã«ãã€ãŸã0.95åäœãèšç®ããããšã¯å¯èœã§ãããããã«ãããã¯ã©ã€ã¢ã³ãåŽã§ã«ãŠã³ãã³ãŒããè¿œå ãããã¬ããŒãã®æè»æ§ã倱ãããŸããèšç®ãããåäœã®ã¿ã䜿çšã§ããŸãã ãããã£ãŠã圌ãã¯ãã¹ãã°ã©ã ãéžæããŸããã
Luaèšèªã®Nginxã§ãã¹ãã°ã©ã çæãå®è£
ããŸããã GitHubã§å®æãããããžã§ã¯ããèŠã€ããŸãããããã¯ãNginxæ§æã§æ¥ç¶ãããäžèšã®æ¹æ³ã§ãã¹ãã°ã©ã ãçæããŸãã æãé »ç¹ã«åŒã³åºãããã¡ãœããããããŒã¿ãåéããå¿
èŠããããŸããããã¯ãèŠããŠãããšãããLogstashã«ã¢ã¯ã»ã¹ãã°ãéä¿¡ããåŸã«æ±ºå®ããŸããã ãã®ãããèŠæ±ããã°ã«èšé²ããå¿
èŠããããã©ããã確èªããããžãã¹ããžãã¯ãè¿œå ããå¿
èŠããããŸããã
ãã®çµæãããã¡ããŠã¹ã®ææãšLuaèšèªã®åºç€ã®ç 究ã«å ããŠãçµ±åã«1é±éããããŸããã ç§ãã¡ã®æèŠã§ã¯ãããã¯çŽ æŽãããçµæã§ãã ãŸãããã¹ãã°ã©ã ã®åœ¢æãšããžãã¹ããžãã¯ã®æ€èšŒã®ããã«ãå¿çæéäžã«ããããªïŒçŽ5ã10ããªç§ïŒãªãŒããŒããããè¿œå ãããããšãéåžžã«ã¯ãŒã«ã§ãã
ãã ãããã®ãœãªã¥ãŒã·ã§ã³ã«ã¯æ¬ ç¹ããããŸããã¹ããŒã¿ã¹ã200ã§ãªããªã¯ãšã¹ãã®æéãèæ
®ããŠããŸãããçç±ã¯ãlog_by_luaãã£ã¬ã¯ãã£ãã§ããããã®ã³ã°ãè¿œå ããŸããããã®å Žåã¯åŒã³åºãããŸããã ãã¡ãã確èªã§ãã äžæ¹ãããã¯ééãã§ããããããã®ãããªãªã¯ãšã¹ãã®å¿çæéã«ã¯é¢å¿ããããŸããã ãã1ã€ã®ãã€ãã¹ç¹ã¯ããã¹ãã°ã©ã ãNginxå
±æã¡ã¢ãªã«ä¿åãããããšã§ãã Nginxãåèµ·åãããšãã¡ã¢ãªãã¯ãªã¢ãããåéãããã¡ããªãã¯ã倱ãããŸãã ãŸãããããšäžç·ã«çããããšãã§ããŸã-reloadã³ãã³ãã§Nginxãåèµ·åããããé »ç¹ã«ã¡ããªãã¯ãååŸããããã«Prometheusãæ§æããŸãã
ãã¹ãã°ã©ã ãäœæããããã®Nginxèšå®ã¯æ¬¡ã®ãšããã§ãã
lua_shared_dict prometheus_metrics 10M; init_by_lua ' prometheus = require("prometheus").init("prometheus_metrics") prometheusHelper = require("prometheus_helper") metric_request_time = prometheus:histogram("nginx_http_request_time", {"api_method_end_point", "request_method"}) '
ããã§ãå
±æã¡ã¢ãªãéžæããã©ã€ãã©ãªãšãã«ããŒãããžãã¹ããžãã¯ã«æ¥ç¶ãããã¹ãã°ã©ã ãåæåããŸã-ååãšã©ãã«ãå²ãåœãŠãŸãã
ãã®æ§æã¯ãèŠæ±ããã°ã«èšé²ããŸãã
location / { log_by_lua ' api_method_end_point = prometheusHelper.convert_request_uri_to_api_method_end_point(ngx.var.request_uri, ngx.var.request_method) if (api_method_end_point ~= nil) then metric_request_time:observe(tonumber(ngx.var.request_time),{api_method_end_point, ngx.var.request_method}) ' }
ããã§ãlog_by_luaãã£ã¬ã¯ãã£ãã§ãªã¯ãšã¹ããèšé²ãããã©ããããã§ãã¯ããèšé²ããå Žåã¯ããã¹ãã°ã©ã ã«å¿çæéãè¿œå ããŸãã
ã¡ããªãã¯ã¯ããšã³ããã€ã³ãããšã«Nginxãä»ããŠæäŸãããŸãã
server { listen 9099; server_name api1.2gis.com; location /metrics { content_by_lua 'prometheus:collect()'; } }
次ã«ãPrometheusæ§æã§ã¡ããªãã¯ãåéããããã®ã¢ããªã±ãŒã·ã§ã³ã®ããŒããæå®ããå¿
èŠããããŸãã
- targets: - api1.2gis.com:9099 - api2.2gis.com:9199 labels: job: bizaccount type: nginx role: monitoring-api-methods team: lk project: backend
ã¿ãŒã²ããã»ã¯ã·ã§ã³ã«ã¯ããŒãã®ãšã³ããã€ã³ãã衚瀺ãããã©ãã«ã»ã¯ã·ã§ã³ã«ã¯åéãããã¡ããªãã¯ã«è¿œå ãããã©ãã«ã衚瀺ãããŸãã ããããããã¡ããªãã¯ãšéä¿¡è
ã®ç®çã決å®ããŸãã
15ç§ããšã«ã¡ããªãã¯ã³ã¬ã¯ã·ã§ã³ãæ§æãããŠããŸã-Prometheusã¯æå®ãããããŒãã«ç§»åããã¡ããªãã¯ãä¿åããŸãã
ã¡ããªãã¯ãææ¡ããããããåéããPrometheusã«æž¡ãæ¹æ³ãåŠç¿ããåŸãçµ±åã®ç®çãã€ãŸãã¢ããªã±ãŒã·ã§ã³ã®é床ãäœäžããå Žåã®ã³ãã³ãã¡ãŒã«ã®ã¢ã©ãŒãã«é²ã¿ãŸããã 次ã«ã¢ã©ãŒãã®äŸã瀺ããŸãã
ALERT BizaccountAPI95PercentileUnreachebleGetUsers IF (sum(rate(nginx_http_request_time_bucket{le="0.4",api_method_end_point="/users",request_method="GET"}[5m])) by (api_method_end_point, request_method) / sum(rate(nginx_http_request_time_count{api_method_end_point="/users",request_method="GET"}[5m])) by (api_method_end_point, request_method)) * 100 < 95 FOR 5m LABELS { severity = "critical", team = "lk"} ANNOTATIONS { summary = "API-method {{ $labels.request_method}} {{ $labels.api_method_end_point}} is not in SLA", description = "For API-method {{ $labels.request_method}} {{ $labels.api_method_end_point }} 95 percentile is unreacheble in last 5 minutes. Current percentile is {{ $value }}.", }
Prometheusã«ã¯ç°¡æœãªã¯ãšãªçæèšèªããããããã䜿çšããŠæéã®ã¡ããªãã¯å€ãéžæããã©ãã«ã§ãã£ã«ã¿ãªã³ã°ã§ããŸãã IFãã£ã¬ã¯ãã£ãã§ã¯ãèšèªæ§é ã䜿çšããŠãããªã¬ãŒæ¡ä»¶ãæå®ããŸã-çŽåã®5åéã®ãªã¯ãšã¹ãã®95ããŒã»ã³ãæªæºã0.4ç§ã§å¿çããå Žåã ããã¯æ
床ãšèŠãªãããŸãã ååã§ã¯ãæåŸã®5åéã«0.4ç§ã§ã¹ã¿ãã¯ããããªã¯ãšã¹ãã®æ°ãèšç®ããŸãã
sum(rate(nginx_http_request_time_bucket{le="0.4",api_method_end_point="/users",request_method="GET"}[5m])) by (api_method_end_point, request_method)
åæ¯ã§ã¯ãæåŸã®5åéã®ãªã¯ãšã¹ãã®ç·æ°ãèæ
®ããŸãã
sum(rate(nginx_http_request_time_count{api_method_end_point="/users",request_method="GET"}[5m])) by (api_method_end_point, request_method)
çµæã®å°æ°ã«100ãæããŠã0.4ç§ã§å¿çããã¯ãšãªã®å²åãååŸããŸãã ããã®ã¬ãŒãé¢æ°ã¯ãæå®ãããééã®åç¬éã®å¿çæéãè¿ããŸãã sumé¢æ°ã¯ãçµæã®ã·ãªãŒãºãåèšããŸãã byæŒç®åã¯ãæå®ãããã©ãã«ã§ã°ã«ãŒãåãå®è¡ããGROUP BYæŒç®åã«é¡äŒŒããŠããŸãã
FORã»ã¯ã·ã§ã³ã§ã¯ãæåã®ããªã¬ãŒãšã¢ã©ãŒããéä¿¡ããå¿
èŠãããç¬éã®ééãããªã¬ãŒãããŸãã ééã¯5åã§ãã5å以å
ã«ç¶æ³ãå€ãããªãå Žåã¯ãã¢ã©ãŒããéä¿¡ããå¿
èŠããããŸãã LABELSã»ã¯ã·ã§ã³ã«ã¯ãããŒã ãšåé¡ã®é倧床ã瀺ãã©ãã«ã衚瀺ãããŸãã ANNOTATIONSã»ã¯ã·ã§ã³ã¯ãåé¡ã®ããã¡ãœãããšã0.4ç§ã§å¿çãããªã¯ãšã¹ãã®å²åã瀺ããŸãã
ç¹°ãè¿ãã¢ã©ãŒããçºçããå ŽåãPrometheusã¯éè€æé€ãè¡ãã1ã€ã®ã¢ã©ãŒããã³ãã³ãã¡ãŒã«ã«éä¿¡ã§ããŸãã ãããŠãããã¯ãã¹ãŠãã®ãŸãŸã§ãã«ãŒã«ãšããªã¬ãŒééãæå®ããã ãã§ãã
Prometheusã®ã¢ã©ãŒãã¯ãæ£ç¢ºãªæ§æã§ãããã¢ã©ãŒãã®éè€æé€æ©èœãåããèªè»¢è»ããã©ã®èšèªã§ãã¢ã©ãŒããããªã¬ãŒããããžãã¯ãå®è£
ããããšãªããæ確ã«æ§æãããŠããŸãã
ã¡ãã»ãŒãžã¯æ¬¡ã®ããã«ãªããŸãã

ãããã«
ãã®ã³ã°ã·ã¹ãã ãæ¹åããæ
å ±äžè¶³ã®åé¡ã¯ãªããªããŸããã
- ãšã©ãŒãçºçããå Žåãåé¡ã«é¢ããååãªæ
å ±ããããŸãã çŸåšããã¯ãã«ã«ãµããŒããªã¯ãšã¹ãã®99ïŒ
ã«ã€ããŠããŠãŒã¶ãŒã«äœãèµ·ãã£ãããææ¡ããåé¡ãšä¿®æ£ã®å¯èœæ§ã®ããæ¡ä»¶ã«ã€ããŠãã¯ãã«ã«ãµããŒããæ£ç¢ºã«æ¹åä»ããŠããŸãã
- ã¢ã©ãŒãã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ã®åé¡é åãç¹å®ããããããæé©åããŠãã¢ããªã±ãŒã·ã§ã³ãããé«éã§ä¿¡é Œæ§ã®é«ããã®ã«ããŸãã
- Prometheusã䜿çšããŠãé床ã®äœäžããã°ããèŠã€ãããã®åŸELKã調ã¹ãŠãäœãèµ·ãã£ãã®ãã詳现ã«èª¿æ»ãå§ããŸãã ELK + Prometheusã«ã¯å€§ããªå¯èœæ§ããããŸãããšã©ãŒãå¢å ããå Žåã«ã¢ã©ãŒããè¿œå ããå€éšãµãŒãã¹ãç£èŠããäºå®ã§ãã