Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

เป‚เบ”เบเบ›เบปเบเบเบฐเบ•เบด, เบœเบฐเบฅเบดเบ”เบ•เบฐเบžเบฑเบ™เบเบฒเบ™เบ„เป‰เบฒเบซเบผเบทเบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเบžเป‰เบญเบกเบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เปเบฅเป‰เบง, เป€เบŠเบฑเปˆเบ™: Prometheus + Grafana, เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เป€เบžเบทเปˆเบญเบ•เบดเบ”เบ•เบฒเบกเปเบฅเบฐเบงเบดเป€เบ„เบฒเบฐเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™เบ‚เบญเบ‡ Nginx. เบ™เบตเป‰เปเบกเปˆเบ™เบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ—เบตเปˆเบ”เบตเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ•เบดเบ”เบ•เบฒเบกเบซเบผเบทเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเปเบ—เป‰เบˆเบดเบ‡, เปเบ•เปˆเบšเปเปˆเบชเบฐเบ”เบงเบเบซเบผเบฒเบเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ›เบฐเบซเบงเบฑเบ”เบชเบฒเบ”. เปƒเบ™เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบ—เบตเปˆเบ™เบดเบเบปเบกเปƒเบ”เบเปเปˆเบ•เบฒเบก, เบ›เบฐเบฅเบดเบกเบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบˆเบฒเบเบšเบฑเบ™เบ—เบถเบ nginx เปเบกเปˆเบ™เบเบฒเบ™เบ‚เบฐเบซเบเบฒเบเบ•เบปเบงเบขเปˆเบฒเบ‡เป„เบงเบงเบฒ, เปเบฅเบฐเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ‚เปเป‰เบกเบนเบ™เบˆเปเบฒเบ™เบงเบ™เบซเบฅเบฒเบ, เบกเบฑเบ™เบกเบตเป€เบซเบ”เบœเบปเบ™เบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰เบชเบดเปˆเบ‡เบ—เบตเปˆเบžเบดเป€เบชเบ”เบเบงเปˆเบฒ.

เปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเบšเบญเบเบ—เปˆเบฒเบ™เบงเบดเบ—เบตเบ—เบตเปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰ Athena เป€เบžเบทเปˆเบญเบงเบดเป€เบ„เบฒเบฐเบšเบฑเบ™เบ—เบถเบ, เป€เบญเบปเบฒ Nginx เป€เบ›เบฑเบ™เบ•เบปเบงเบขเปˆเบฒเบ‡, เปเบฅเบฐเบ‚เป‰เบญเบเบˆเบฐเบชเบฐเปเบ”เบ‡เบงเบดเบ—เบตเบเบฒเบ™เบฅเบงเบšเบฅเบงเบก dashboard เบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบˆเบฒเบเบ‚เปเป‰เบกเบนเบ™เบ™เบตเป‰เป‚เบ”เบเปƒเบŠเป‰เบเบญเบš cube.js open-source. เบ™เบตเป‰เปเบกเปˆเบ™เบชเบฐเบ–เบฒเบ›เบฑเบ”เบ•เบฐเบเบฐเบเปเบฒเบเบฒเบ™เปเบเป‰เป„เบ‚เบ—เบตเปˆเบชเบปเบกเบšเบนเบ™:

Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

TL:DR;
เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบเบฑเบš dashboard เบชเปเบฒเป€เบฅเบฑเบ”เบฎเบนเบš.

เป€เบžเบทเปˆเบญเป€เบเบฑเบšเบเปเบฒเบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ เบ„เปˆเบญเบ‡เปเบ„เป‰เบง, เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบ›เบธเบ‡โ€‹เปเบ•เปˆเบ‡ - AWS Kinesis Data Firehose ะธ เบเบฒเบง AWS, เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เป€เบเบฑเบšโ€‹เบฎเบฑเบโ€‹เบชเบฒ - AWS S3. เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบกเบฑเบ”เบ™เบตเป‰, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเบšเปเปˆเบžเบฝเบ‡เปเบ•เปˆเบšเบฑเบ™เบ—เบถเบ nginx, เปเบ•เปˆเบเบฑเบ‡เป€เบซเบ”เบเบฒเบ™เบญเบทเปˆเบ™เป†, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบšเบฑเบ™เบ—เบถเบเบ‚เบญเบ‡เบเบฒเบ™เบšเปเบฅเบดเบเบฒเบ™เบญเบทเปˆเบ™เป†. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ—เบปเบ”เปเบ—เบ™เบšเบฒเบ‡เบชเปˆเบงเบ™เบ—เบตเปˆเบกเบตเบชเปˆเบงเบ™เบ—เบตเปˆเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™เบชเปเบฒเบฅเบฑเบš stack เบ‚เบญเบ‡เบ—เปˆเบฒเบ™, เบ•เบปเบงเบขเปˆเบฒเบ‡, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ‚เบฝเบ™เบšเบฑเบ™เบ—เบถเบเป€เบžเบทเปˆเบญ kinesis เป‚เบ”เบเบเบปเบ‡เบˆเบฒเบ nginx, bypassing fluentd, เบซเบผเบทเปƒเบŠเป‰ logstash เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰.

เป€เบเบฑเบšเบเปเบฒเบ‚เปเป‰เบกเบนเบ™เบšเบฑเบ™เบ—เบถเบ Nginx

เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™, เบšเบฑเบ™เบ—เบถเบ Nginx เบกเบตเบฅเบฑเบเบชเบฐเบ™เบฐเบ„เป‰เบฒเบเบ„เบทเบ™เบตเป‰:

4/9/2019 12:58:17 PM1.1.1.1 - - [09/Apr/2019:09:58:17 +0000] "GET /sign-up HTTP/2.0" 200 9168 "https://example.com/sign-in" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-"
4/9/2019 12:58:17 PM1.1.1.1 - - [09/Apr/2019:09:58:17 +0000] "GET /sign-in HTTP/2.0" 200 9168 "https://example.com/sign-up" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-"

เบžเบงเบเป€เบ‚เบปเบฒเบชเบฒเบกเบฒเบ”เบ–เบทเบเบงเบดเป€เบ„เบฒเบฐ, เปเบ•เปˆเบกเบฑเบ™เบ‡เปˆเบฒเบเบ‚เบถเป‰เบ™เบซเบผเบฒเบเบ—เบตเปˆเบˆเบฐเปเบเป‰เป„เบ‚เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒ Nginx เป€เบžเบทเปˆเบญเปƒเบซเป‰เบกเบฑเบ™เบœเบฐเบฅเบดเบ”เบšเบฑเบ™เบ—เบถเบเปƒเบ™ JSON:

log_format json_combined escape=json '{ "created_at": "$msec", '
            '"remote_addr": "$remote_addr", '
            '"remote_user": "$remote_user", '
            '"request": "$request", '
            '"status": $status, '
            '"bytes_sent": $bytes_sent, '
            '"request_length": $request_length, '
            '"request_time": $request_time, '
            '"http_referrer": "$http_referer", '
            '"http_x_forwarded_for": "$http_x_forwarded_for", '
            '"http_user_agent": "$http_user_agent" }';

access_log  /var/log/nginx/access.log  json_combined;

S3 เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒ

เป€เบžเบทเปˆเบญเป€เบเบฑเบšเบฎเบฑเบเบชเบฒเบšเบฑเบ™เบ—เบถเบ, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเปƒเบŠเป‰ S3. เบ™เบตเป‰เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเปเบฅเบฐเบงเบดเป€เบ„เบฒเบฐเบšเบฑเบ™เบ—เบถเบเบขเบนเปˆเปƒเบ™เบชเบฐเบ–เบฒเบ™เบ—เบตเปˆเบซเบ™เบถเปˆเบ‡, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒ Athena เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบ‚เปเป‰เบกเบนเบ™เปƒเบ™ S3 เป‚เบ”เบเบเบปเบ‡. เบ•เปเปˆเบกเบฒเปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเบšเบญเบเบ—เปˆเบฒเบ™เบงเบดเบ—เบตเบเบฒเบ™เป€เบžเบตเปˆเบกเปเบฅเบฐเบšเบฑเบ™เบ—เบถเบเบเบฒเบ™เบ›เบธเบ‡เปเบ•เปˆเบ‡เบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡, เปเบ•เปˆเบ—เปเบฒเบญเบดเบ”เบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™เบ–เบฑเบ‡เบ—เบตเปˆเบชเบฐเบญเบฒเบ”เบขเบนเปˆเปƒเบ™ S3, เป€เบŠเบดเปˆเบ‡เบšเปเปˆเบกเบตเบซเบเบฑเบ‡เบญเบตเบเบ—เบตเปˆเบˆเบฐเป€เบเบฑเบšเป„เบงเป‰. เบกเบฑเบ™เบ„เบธเป‰เบกเบ„เปˆเบฒเบ—เบตเปˆเบˆเบฐเบžเบดเบˆเบฒเบฅเบฐเบ™เบฒเบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒเบงเปˆเบฒเบ—เปˆเบฒเบ™เบˆเบฐเบชเป‰เบฒเบ‡เบ–เบฑเบ‡เบ‚เบญเบ‡เป€เบˆเบปเป‰เบฒเบขเบนเปˆเปƒเบ™เบžเบฒเบเบžเบทเป‰เบ™เปƒเบ”, เป€เบžเบฒเบฐเบงเปˆเบฒ Athena เบšเปเปˆเบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เป„เบ”เป‰เปƒเบ™เบ—เบธเบเบ‚เบปเบ‡เป€เบ‚เบ”.

เบเบฒเบ™เบชเป‰เบฒเบ‡เบงเบปเบ‡เบˆเบญเบ™เปƒเบ™ Athena console

เปƒเบซเป‰เบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปƒเบ™ Athena เบชเปเบฒเบฅเบฑเบšเบšเบฑเบ™เบ—เบถเบ. เบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™เบชเปเบฒเบฅเบฑเบšเบ—เบฑเบ‡เบเบฒเบ™เบ‚เบฝเบ™เปเบฅเบฐเบเบฒเบ™เบญเปˆเบฒเบ™เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบงเบฒเบ‡เปเบœเบ™เบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰ Kinesis Firehose. เป€เบ›เบตเบ” Athena console เปเบฅเบฐเบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡:

เบเบฒเบ™เบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ SQL

CREATE EXTERNAL TABLE `kinesis_logs_nginx`(
  `created_at` double, 
  `remote_addr` string, 
  `remote_user` string, 
  `request` string, 
  `status` int, 
  `bytes_sent` int, 
  `request_length` int, 
  `request_time` double, 
  `http_referrer` string, 
  `http_x_forwarded_for` string, 
  `http_user_agent` string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.orc.OrcSerde' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'
LOCATION
  's3://<YOUR-S3-BUCKET>'
TBLPROPERTIES ('has_encrypted_data'='false');

เบเบฒเบ™เบชเป‰เบฒเบ‡ Kinesis Firehose Stream

Kinesis Firehose เบˆเบฐเบ‚เบฝเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเป„เบ”เป‰เบฎเบฑเบšเบˆเบฒเบ Nginx เบซเบฒ S3 เปƒเบ™เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเป€เบฅเบทเบญเบ, เปเบšเปˆเบ‡เบญเบญเบเป€เบ›เบฑเบ™เป„เบ”เป€เบฅเบเบฐเบ—เปเบฅเบตเปƒเบ™เบฎเบนเบšเปเบšเบš YYYY/MM/DD/HH. เบ™เบตเป‰เบˆเบฐเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เปƒเบ™เป€เบงเบฅเบฒเบญเปˆเบฒเบ™เบ‚เปเป‰เบกเบนเบ™. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”, เปเบ™เปˆเบ™เบญเบ™, เบ‚เบฝเบ™เป‚เบ”เบเบเบปเบ‡เบเบฑเบš S3 เบˆเบฒเบ fluentd, เปเบ•เปˆเปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰เบ—เปˆเบฒเบ™เบˆเบฐเบ•เป‰เบญเบ‡เบ‚เบฝเบ™ JSON, เปเบฅเบฐเบ™เบตเป‰เบšเปเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆเบ‚เบญเบ‡เป„เบŸเบฅเปŒ. เบ™เบญเบเบˆเบฒเบเบ™เบฑเป‰เบ™, เป€เบกเบทเปˆเบญเปƒเบŠเป‰ PrestoDB เบซเบผเบท Athena, JSON เปเบกเปˆเบ™เบฎเบนเบšเปเบšเบšเบ‚เปเป‰เบกเบนเบ™เบŠเป‰เบฒเบ—เบตเปˆเบชเบธเบ”. เบชเบฐเบ™เบฑเป‰เบ™เป€เบ›เบตเบ” Kinesis Firehose console, เบ„เบฅเบดเบ "เบชเป‰เบฒเบ‡เบเบฒเบ™เบˆเบฑเบ”เบชเบปเปˆเบ‡เบเบฐเปเบช", เป€เบฅเบทเบญเบ "เป€เบญเบปเบฒเป‚เบ”เบเบเบปเบ‡" เปƒเบ™เบŠเปˆเบญเบ‡ "เบเบฒเบ™เบˆเบฑเบ”เบชเบปเปˆเบ‡":

Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

เปƒเบ™เปเบ–เบšเบ•เปเปˆเป„เบ›, เป€เบฅเบทเบญเบ "เบเบฒเบ™เปเบ›เบ‡เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบšเบฑเบ™เบ—เบถเบ" - "เป€เบ›เบตเบ”เปƒเบŠเป‰เบ‡เบฒเบ™" เปเบฅเบฐเป€เบฅเบทเบญเบ "Apache ORC" เป€เบ›เบฑเบ™เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบšเบฑเบ™เบ—เบถเบ. เบญเบตเบ‡เบ•เบฒเบกเบเบฒเบ™เบ„เบปเป‰เบ™เบ„เบงเป‰เบฒเบšเบฒเบ‡เบขเปˆเบฒเบ‡ Owen O'Malley, เบ™เบตเป‰เปเบกเปˆเบ™เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเบ”เบตเบ—เบตเปˆเบชเบธเบ”เบชเปเบฒเบฅเบฑเบš PrestoDB เปเบฅเบฐ Athena. เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบชเป‰เบฒเบ‡เบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡เป€เบ›เบฑเบ™ schema. เบเบฐโ€‹เบฅเบธโ€‹เบ™เบฒโ€‹เบชเบฑเบ‡โ€‹เป€เบเบ”โ€‹เบงเปˆเบฒโ€‹เบ—เปˆเบฒเบ™โ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เบเปเบฒโ€‹เบ™เบปเบ”โ€‹เบชเบฐโ€‹เบ–เบฒเบ™โ€‹เบ—เบตเปˆ S3 เปƒเบ”โ€‹เบซเบ™เบถเปˆเบ‡โ€‹เปƒเบ™ kinesisโ€‹; เบžเบฝเบ‡โ€‹เปเบ•เปˆ schema เป„เบ”เป‰โ€‹เบ–เบทเบโ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เบˆเบฒเบโ€‹เบ•เบฒโ€‹เบ•เบฐโ€‹เบฅเบฒเบ‡โ€‹. เปเบ•เปˆเบ–เป‰เบฒเบ—เปˆเบฒเบ™เบฅเบฐเบšเบธเบชเบฐเบ–เบฒเบ™เบ—เบตเปˆ S3 เบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบˆเบฐเบšเปเปˆเบชเบฒเบกเบฒเบ”เบญเปˆเบฒเบ™เบšเบฑเบ™เบ—เบถเบเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบˆเบฒเบเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ™เบตเป‰.

Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

เบžเบงเบเป€เบฎเบปเบฒเป€เบฅเบทเบญเบ S3 เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเปเบฅเบฐเบ–เบฑเบ‡เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบชเป‰เบฒเบ‡เบเปˆเบญเบ™เบซเบ™เป‰เบฒเบ™เบตเป‰. Aws Glue Crawler, เบ—เบตเปˆเบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเป€เบงเบปเป‰เบฒเบเปˆเบฝเบงเบเบฑเบšเป€เบฅเบฑเบเบ™เป‰เบญเบเบ•เปเปˆเบกเบฒ, เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเบ„เปเบฒเบ™เปเบฒเบซเบ™เป‰เบฒเปƒเบ™เบ–เบฑเบ‡ S3, เบชเบฐเบ™เบฑเป‰เบ™เบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบชเปเบฒเบ„เบฑเบ™เบ—เบตเปˆเบˆเบฐเบ›เปˆเบญเบเปƒเบซเป‰เบกเบฑเบ™เบซเบงเปˆเบฒเบ‡เป€เบ›เบปเปˆเบฒ.

Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

เบ—เบฒเบ‡โ€‹เป€เบฅเบทเบญเบโ€‹เบ—เบตเปˆโ€‹เบเบฑเบ‡โ€‹เป€เบซเบผเบทเบญโ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เป„เบ”เป‰โ€‹เบฎเบฑเบšโ€‹เบเบฒเบ™โ€‹เบ›เปˆเบฝเบ™โ€‹เปเบ›เบ‡โ€‹เป‚เบ”เบโ€‹เบญเบตเบ‡โ€‹เปƒเบชเปˆโ€‹เบเบฒเบ™โ€‹เป‚เบซเบผเบ”โ€‹เบ‚เบญเบ‡โ€‹เบ—เปˆเบฒเบ™โ€‹; เป‚เบ”เบโ€‹เบ›เบปเบโ€‹เบเบฐโ€‹เบ•เบดโ€‹เบ‚เป‰เบฒโ€‹เบžเบฐโ€‹เป€เบˆเบปเป‰เบฒโ€‹เปƒเบŠเป‰โ€‹เปƒเบ™โ€‹เบ•เบญเบ™โ€‹เบ•เบปเป‰เบ™โ€‹. เปƒเบซเป‰เบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเบเบฒเบ™เบšเบตเบšเบญเบฑเบ” S3 เบšเปเปˆเบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เป„เบ”เป‰, เปเบ•เปˆ ORC เปƒเบŠเป‰เบเบฒเบ™เบšเบตเบšเบญเบฑเบ”เปเบšเบšเป€เบ”เบตเบกเป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™.

เบ„เปˆเบญเบ‡เปเบ„เป‰เบง

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบšเบฑเบ™เบ—เบถเบเบเบฒเบ™เป€เบเบฑเบšเบฎเบฑเบเบชเบฒเปเบฅเบฐเบเบฒเบ™เบฎเบฑเบš, เบžเบงเบเป€เบฎเบปเบฒเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบชเบปเปˆเบ‡. เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ™เปเบฒเปƒเบŠเป‰ เบ„เปˆเบญเบ‡เปเบ„เป‰เบง, เป€เบžเบฒเบฐเบงเปˆเบฒเบ‚เป‰เบญเบเบฎเบฑเบ Ruby, เปเบ•เปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰ Logstash เบซเบผเบทเบชเบปเปˆเบ‡เบšเบฑเบ™เบ—เบถเบเป„เบ›เบซเบฒ kinesis เป‚เบ”เบเบเบปเบ‡. เป€เบŠเบตเบšเป€เบงเบต Fluentd เบชเบฒเบกเบฒเบ”เบ–เบทเบเป€เบ›เบตเบ”เบ•เบปเบงเปƒเบ™เบซเบผเบฒเบเบงเบดเบ—เบต, เบ‚เป‰เบญเบเบˆเบฐเบšเบญเบเบ—เปˆเบฒเบ™เบเปˆเบฝเบงเบเบฑเบš docker เป€เบžเบฒเบฐเบงเปˆเบฒเบกเบฑเบ™เบ‡เปˆเบฒเบเบ”เบฒเบเปเบฅเบฐเบชเบฐเบ”เบงเบ.

เบเปˆเบญเบ™เบญเบทเปˆเบ™, เบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™เป„เบŸเบฅเปŒเบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒ fluent.conf. เบชเป‰เบฒเบ‡เบกเบฑเบ™เปเบฅเบฐเป€เบžเบตเปˆเบกเปเบซเบผเปˆเบ‡:

เบ›เบฐเป€เบžเบ” เป„เบ›เบ‚เป‰เบฒเบ‡เบซเบ™เป‰เบฒ
port 24224
เบœเบนเบเบกเบฑเบ” 0.0.0.0

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบ Fluentd. เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ‚เบฑเป‰เบ™เบชเบนเบ‡, เปƒเบซเป‰เป„เบ›เบ—เบตเปˆ เบชเบนเบ™เบเบฒเบ‡ docker เบกเบตเบ„เบนเปˆเบกเบทเบฅเบฒเบเบฅเบฐเบญเบฝเบ”, เบฅเบงเบกเบ—เบฑเบ‡เบงเบดเบ—เบตเบเบฒเบ™เบ›เบฐเบเบญเบšเบฎเบนเบšเบžเบฒเบšเบ‚เบญเบ‡เบ—เปˆเบฒเบ™.

$ docker run 
  -d 
  -p 24224:24224 
  -p 24224:24224/udp 
  -v /data:/fluentd/log 
  -v <PATH-TO-FLUENT-CONF>:/fluentd/etc fluentd 
  -c /fluentd/etc/fluent.conf
  fluent/fluentd:stable

เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ™เบตเป‰เปƒเบŠเป‰เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡ /fluentd/log เป€เบžเบทเปˆเบญ cache เบšเบฑเบ™เบ—เบถเบเบเปˆเบญเบ™เบ—เบตเปˆเบˆเบฐเบชเบปเปˆเบ‡. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เป„เบ”เป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบ™เบตเป‰, เปเบ•เปˆเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เป€เบกเบทเปˆเบญเบ—เปˆเบฒเบ™ restart, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบชเบนเบ™เป€เบชเบเบ—เบธเบเบชเบดเปˆเบ‡เบ—เบธเบเบขเปˆเบฒเบ‡เบ—เบตเปˆเป€เบเบฑเบšเป„เบงเป‰เปƒเบ™เบ–เบฒเบ™เบ„เบงเบฒเบกเบˆเปเบฒเบ”เป‰เบงเบเปเบฎเบ‡เบ‡เบฒเบ™ back-breaking. เบ—เปˆเบฒเบ™เบเบฑเบ‡เบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เบžเบญเบ”เปƒเบ”เบเปเป„เบ”เป‰; 24224 เปเบกเปˆเบ™เบžเบญเบ” Fluentd เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™.

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบกเบต Fluentd เปเบฅเปˆเบ™, เบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เบชเบปเปˆเบ‡เบšเบฑเบ™เบ—เบถเบ Nginx เบขเบนเปˆเบ—เบตเปˆเบ™เบฑเป‰เบ™. เบžเบงเบเป€เบฎเบปเบฒเบ›เบปเบเบเบฐเบ•เบดเปเบฅเป‰เบงเปเบฅเปˆเบ™ Nginx เปƒเบ™ Docker container, เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰ Docker เบกเบตเป„เบ”เป€เบงเบตเบเบฒเบ™เป€เบ‚เบปเป‰เบฒเบชเบนเปˆเบฅเบฐเบšเบปเบšเบžเบทเป‰เบ™เป€เบกเบทเบญเบ‡เบชเปเบฒเบฅเบฑเบš Fluentd:

$ docker run 
--log-driver=fluentd 
--log-opt fluentd-address=<FLUENTD-SERVER-ADDRESS>
--log-opt tag="{{.Name}}" 
-v /some/content:/usr/share/nginx/html:ro 
-d 
nginx

เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™ Nginx เปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰เป„เบŸเบฅเปŒเบšเบฑเบ™เบ—เบถเบ, Fluentd เบกเบต plugin เบซเบฒเบ‡เป„เบŸเบฅเปŒ.

เบกเบฒเป€เบžเบตเปˆเบกเบเบฒเบ™เปเบเบเบงเบดเป€เบ„เบฒเบฐเบšเบฑเบ™เบ—เบถเบเบ—เบตเปˆเบเบณเบ™เบปเบ”เป„เบงเป‰เบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡เปƒเบชเปˆเบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ—เบตเปˆเบ„เปˆเบญเบ‡เปเบ„เป‰เบง:

<filter YOUR-NGINX-TAG.*>
  @type parser
  key_name log
  emit_invalid_record_to_error false
  <parse>
    @type json
  </parse>
</filter>

เปเบฅเบฐเบเบฒเบ™เบชเบปเปˆเบ‡เบšเบฑเบ™เบ—เบถเบเป„เบ›เบซเบฒ Kinesis เป‚เบ”เบเปƒเบŠเป‰ plugin kinesis firehose:

<match YOUR-NGINX-TAG.*>
    @type kinesis_firehose
    region region
    delivery_stream_name <YOUR-KINESIS-STREAM-NAME>
    aws_key_id <YOUR-AWS-KEY-ID>
    aws_sec_key <YOUR_AWS-SEC_KEY>
</match>

Athena

เบ–เป‰เบฒเบ—เปˆเบฒเบ™เป„เบ”เป‰เบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบ—เบธเบเบขเปˆเบฒเบ‡เบขเปˆเบฒเบ‡เบ–เบทเบเบ•เป‰เบญเบ‡, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เป„เบฅเบเบฐเบซเบ™เบถเปˆเบ‡ (เป‚เบ”เบเบ„เปˆเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™, Kinesis เบšเบฑเบ™เบ—เบถเบเบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเป„เบ”เป‰เบฎเบฑเบšเบ—เบธเบเป† 10 เบ™เบฒเบ—เบต) เบ—เปˆเบฒเบ™เบ„เบงเบ™เป€เบซเบฑเบ™เป„เบŸเบฅเปŒเบšเบฑเบ™เบ—เบถเบเปƒเบ™ S3. เปƒเบ™เป€เบกเบ™เบน "เบเบฒเบ™เบ•เบดเบ”เบ•เบฒเบก" เบ‚เบญเบ‡ Kinesis Firehose เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบšเบดเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™เบซเบผเบฒเบเบ›เบฒเบ™เปƒเบ”เบ—เบตเปˆเบ–เบทเบเบšเบฑเบ™เบ—เบถเบเป„เบงเป‰เปƒเบ™ S3, เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”. เบขเปˆเบฒเบฅเบทเบกเปƒเบซเป‰เบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบเบฒเบ™เบ‚เบฝเบ™เปƒเบชเปˆเบ–เบฑเบ‡ S3 เบเบฑเบšเบšเบปเบ”เบšเบฒเบ” Kinesis. เบ–เป‰เบฒ Kinesis เบšเปเปˆเบชเบฒเบกเบฒเบ”เบงเบดเป€เบ„เบฒเบฐเบšเบฒเบ‡เบญเบฑเบ™เป„เบ”เป‰, เบกเบฑเบ™เบˆเบฐเป€เบžเบตเปˆเบกเบ‚เปเป‰เบœเบดเบ”เบžเบฒเบ”เปƒเบชเปˆเปƒเบ™เบ–เบฑเบ‡เบ”เบฝเบงเบเบฑเบ™.

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบšเบดเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™เปƒเบ™ Athena. เปƒเบซเป‰เบŠเบญเบเบซเบฒเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเบซเบผเป‰เบฒเบชเบธเบ”เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบชเบปเปˆเบ‡เบ„เบทเบ™เบ‚เปเป‰เบœเบดเบ”เบžเบฒเบ”:

SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;

เบเบณเบฅเบฑเบ‡เบชเบฐเปเบเบ™เบšเบฑเบ™เบ—เบถเบเบ—เบฑเบ‡เปเบปเบ”เบชเบณเบฅเบฑเบšเปเบ•เปˆเบฅเบฐเบ„เบณเบฎเป‰เบญเบ‡เบ‚เป

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบšเบฑเบ™เบ—เบถเบเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบ–เบทเบเบ›เบธเบ‡เปเบ•เปˆเบ‡เปเบฅเบฐเป€เบเบฑเบšเบฎเบฑเบเบชเบฒเป„เบงเป‰เปƒเบ™ S3 เปƒเบ™ ORC, เบšเบตเบšเบญเบฑเบ”เปเบฅเบฐเบเบฝเบกเบžเป‰เบญเบกเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐ. Kinesis Firehose เปเบกเป‰เปเบ•เปˆเบˆเบฑเบ”เบฅเบฐเบšเบฝเบšเปƒเบซเป‰เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบฅเบฒเบเบเบฒเบ™เบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐเบŠเบปเปˆเบงเป‚เบกเบ‡. เบขเปˆเบฒเบ‡เปƒเบ”เบเปเบ•เบฒเบก, เบ•เบฒเบšเปƒเบ”เบ—เบตเปˆเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบšเปเปˆเป„เบ”เป‰เบ–เบทเบเปเบšเปˆเบ‡เบญเบญเบ, Athena เบˆเบฐเป‚เบซเบฅเบ”เบ‚เปเป‰เบกเบนเบ™เบ•เบฐเบซเบผเบญเบ”เป€เบงเบฅเบฒเปƒเบ™เบ—เบธเบเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป, เบกเบตเบ‚เปเป‰เบเบปเบเป€เบงเบฑเป‰เบ™เบ—เบตเปˆเบซเบฒเบเบฒเบ. เบ™เบตเป‰เปเบกเปˆเบ™เบšเบฑเบ™เบซเบฒเปƒเบซเบเปˆเบชเปเบฒเบฅเบฑเบšเบชเบญเบ‡เป€เบซเบ”เบœเบปเบ™:

  • เบ›เบฐเบฅเบดเบกเบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปเบกเปˆเบ™เบเบฒเบ™เบ‚เบฐเบซเบเบฒเบเบ•เบปเบงเบขเปˆเบฒเบ‡เบ•เปเปˆเป€เบ™เบทเปˆเบญเบ‡, เบŠเป‰เบฒเบฅเบปเบ‡เบเบฒเบ™เบชเบญเบšเบ–เบฒเบก;
  • Athena เบ–เบทเบเป€เบญเบตเป‰เบ™เป€เบเบฑเบšเป€เบ‡เบดเบ™เป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆเบ›เบฐเบฅเบดเบกเบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบ–เบทเบเบชเบฐเปเบเบ™, เบขเปˆเบฒเบ‡เบซเบ™เป‰เบญเบ 10 MB เบ•เปเปˆเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป.

เป€เบžเบทเปˆเบญเปเบเป‰เป„เบ‚เบ™เบตเป‰, เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ AWS Glue Crawler, เป€เบŠเบดเปˆเบ‡เบˆเบฐเบฅเบงเบšเบฅเบงเบกเบ‚เปเป‰เบกเบนเบ™เปƒเบ™ S3 เปเบฅเบฐเบ‚เบฝเบ™เบ‚เปเป‰เบกเบนเบ™เบเบฒเบ™เปเบšเปˆเบ‡เบ›เบฑเบ™เป„เบ›เบซเบฒ Glue Metastore. เบ™เบตเป‰เบˆเบฐเบŠเปˆเบงเบเปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒเบ™เปเบฒเปƒเบŠเป‰เบžเบฒเบ—เบดเบŠเบฑเบ™เป€เบ›เบฑเบ™เบ•เบปเบงเบเบญเบ‡เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบชเบญเบšเบ–เบฒเบก Athena, เปเบฅเบฐเบกเบฑเบ™เบˆเบฐเบžเบฝเบ‡เปเบ•เปˆเบชเบฐเปเบเบ™เป„เบ”เป€เบฅเบเบฐเบ—เปเบฅเบตเบ—เบตเปˆเบฅเบฐเบšเบธเป„เบงเป‰เปƒเบ™เปเบšเบšเบชเบญเบšเบ–เบฒเบกเป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™.

เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒ Amazon Glue Crawler

Amazon Glue Crawler เบชเบฐเปเบเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบฑเบ‡เปเบปเบ”เบขเบนเปˆเปƒเบ™เบ–เบฑเบ‡ S3 เปเบฅเบฐเบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ—เบตเปˆเบกเบตเบžเบฒเบ—เบดเบŠเบฑเบ™. เบชเป‰เบฒเบ‡ Glue Crawler เบˆเบฒเบ console AWS Glue เปเบฅเบฐเป€เบžเบตเปˆเบก bucket เบšเปˆเบญเบ™เบ—เบตเปˆเบ—เปˆเบฒเบ™เป€เบเบฑเบšเบ‚เปเป‰เบกเบนเบ™. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰เบ•เบปเบงเบเบงเบฒเบ”เป€เบงเบฑเบšเบซเบ™เบถเปˆเบ‡เบชเปเบฒเบฅเบฑเบšเบซเบผเบฒเบเป† buckets, เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰เบกเบฑเบ™เบˆเบฐเบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบฅเบฐเบšเบธเป„เบงเป‰เบ”เป‰เบงเบเบŠเบทเปˆเบ—เบตเปˆเบเบปเบ‡เบเบฑเบšเบŠเบทเปˆเบ‚เบญเบ‡ buckets. เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบงเบฒเบ‡เปเบœเบ™เบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰เบ‚เปเป‰เบกเบนเบ™เบ™เบตเป‰เป€เบ›เบฑเบ™เบ›เบปเบเบเบฐเบ•เบด, เปƒเบซเป‰เปเบ™เปˆเปƒเบˆเบงเปˆเบฒเบเปเบฒเบ™เบปเบ”เป€เบงเบฅเบฒเบเบฒเบ™เป€เบ›เบตเบ”เบ•เบปเบงเบ‚เบญเบ‡ Crawler เปƒเบซเป‰เป€เบซเบกเบฒเบฐเบชเบปเบกเบเบฑเบšเบ„เบงเบฒเบกเบ•เป‰เบญเบ‡เบเบฒเบ™เบ‚เบญเบ‡เบ—เปˆเบฒเบ™. เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบ•เบปเบงเบเบงเบฒเบ”เป€เบงเบฑเบšเบญเบฑเบ™เบ”เบฝเบงเบชเปเบฒเบฅเบฑเบšเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ—เบฑเบ‡เบซเบกเบปเบ”, เป€เบŠเบดเปˆเบ‡เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ—เบธเบเป†เบŠเบปเปˆเบงเป‚เบกเบ‡.

เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปเบšเปˆเบ‡เบชเปˆเบงเบ™

เบซเบผเบฑเบ‡เบˆเบฒเบเบเบฒเบ™เป€เบ›เบตเบ”เบ•เบปเบงเบ„เบฑเป‰เบ‡เบ—เปเบฒเบญเบดเบ”เบ‚เบญเบ‡เบ•เบปเบงเบเบงเบฒเบ”เป€เบงเบฑเบš, เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐเบ–เบฑเบ‡เบ—เบตเปˆเบชเบฐเปเบเบ™เบ„เบงเบ™เบˆเบฐเบ›เบฒเบเบปเบ”เบขเบนเปˆเปƒเบ™เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบฅเบฐเบšเบธเป„เบงเป‰เปƒเบ™เบเบฒเบ™เบ•เบฑเป‰เบ‡เบ„เปˆเบฒ. เป€เบ›เบตเบ” Athena console เปเบฅเบฐเบŠเบญเบเบซเบฒเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ—เบตเปˆเบกเบตเบšเบฑเบ™เบ—เบถเบ Nginx. เบฅเบญเบ‡เบญเปˆเบฒเบ™เบšเบฒเบ‡เบญเบฑเบ™:

SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
  partition_0 = '2019' AND
  partition_1 = '04' AND
  partition_2 = '08' AND
  partition_3 = '06'
  );

เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ™เบตเป‰เบˆเบฐเป€เบฅเบทเบญเบเบšเบฑเบ™เบ—เบถเบเบ—เบฑเบ‡เปเบปเบ”เบ—เบตเปˆเป„เบ”เป‰เบฎเบฑเบšเปƒเบ™เบฅเบฐเบซเบงเปˆเบฒเบ‡ 6 เป‚เบกเบ‡เป€เบŠเบปเป‰เบฒเบซเบฒ 7 เป‚เบกเบ‡เปเบฅเบ‡เบ‚เบญเบ‡เบงเบฑเบ™เบ—เบต 8 เป€เบกเบชเบฒ 2019. เปเบ•เปˆเบงเบดเบ—เบตเบเบฒเบ™เบ™เบตเป‰เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบซเบผเบฒเบเบเปˆเบงเบฒเบžเบฝเบ‡เปเบ•เปˆเบญเปˆเบฒเบ™เบˆเบฒเบเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ—เบตเปˆเบšเปเปˆเบกเบตเบเบฒเบ™เปเบšเปˆเบ‡เบ›เบฑเบ™? เปƒเบซเป‰เบŠเบญเบเบซเบฒเปเบฅเบฐเป€เบฅเบทเบญเบเป€เบญเบปเบฒเบšเบฑเบ™เบ—เบถเบเบ”เบฝเบงเบเบฑเบ™, เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เปƒเบซเป‰เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเป‚เบ”เบเป€เบงเบฅเบฒ:

Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

3.59 เบงเบดเบ™เบฒเบ—เบต เปเบฅเบฐ 244.34 megabytes เบ‚เบญเบ‡เบ‚เปเป‰เบกเบนเบ™เปƒเบ™เบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบกเบตเบšเบฑเบ™เบ—เบถเบเบžเบฝเบ‡เปเบ•เปˆเบซเบ™เบถเปˆเบ‡เบญเบฒเบ—เบดเบ”. เบกเบฒเบฅเบญเบ‡เปƒเบŠเป‰เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เบ•เบฒเบกเบเบฒเบ™เปเบšเปˆเบ‡เบชเปˆเบงเบ™:

Nginx Log Analytics เบเบฑเบš Amazon Athena เปเบฅเบฐ Cube.js

เป„เบงเบ‚เบถเป‰เบ™เป€เบฅเบฑเบเบ™เป‰เบญเบ, เปเบ•เปˆเบชเปเบฒเบ„เบฑเบ™เบ—เบตเปˆเบชเบธเบ” - เบžเบฝเบ‡เปเบ•เปˆ 1.23 megabytes เบ‚เบญเบ‡เบ‚เปเป‰เบกเบนเบ™! เบกเบฑเบ™เบˆเบฐเบกเบตเบฅเบฒเบ„เบฒเบ–เบทเบเบเบงเปˆเบฒเบซเบผเบฒเบเบ–เป‰เบฒเบšเปเปˆเปเบกเปˆเบ™เบชเปเบฒเบฅเบฑเบšเบ•เปเบฒเปˆเบชเบธเบ”เบ—เบตเปˆ 10 megabytes เบ•เปเปˆเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเบขเบนเปˆเปƒเบ™เบฅเบฒเบ„เบฒ. เปเบ•เปˆเบกเบฑเบ™เบเบฑเบ‡เบ”เบตเบเบงเปˆเบฒเบซเบผเบฒเบ, เปเบฅเบฐเปƒเบ™เบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆ, เบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡เบˆเบฐเบ›เบฐเบ—เบฑเบšเปƒเบˆเบซเบผเบฒเบ.

เบเบฒเบ™เบชเป‰เบฒเบ‡ dashboard เป‚เบ”เบเปƒเบŠเป‰ Cube.js

เป€เบžเบทเปˆเบญเบ›เบฐเบเบญเบš dashboard, เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบเบญเบšเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐ Cube.js. เบกเบฑเบ™เบกเบตเบซเบ™เป‰เบฒเบ—เบตเปˆเบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เบซเบผเบฒเบ, เปเบ•เปˆเบžเบงเบเป€เบฎเบปเบฒเบชเบปเบ™เปƒเบˆเบชเบญเบ‡เบขเปˆเบฒเบ‡: เบ„เบงเบฒเบกเบชเบฒเบกเบฒเบ”เปƒเบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบ•เบปเบงเบเบญเบ‡เบเบฒเบ™เปเบšเปˆเบ‡เบ›เบฑเบ™เบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เปเบฅเบฐเบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบ‚เปเป‰เบกเบนเบ™เบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒ. เบกเบฑเบ™เปƒเบŠเป‰ schema เบ‚เปเป‰เบกเบนเบ™ เป‚เบ„เบ‡โ€‹เบเบฒเบ™โ€‹เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹, เบ‚เบฝเบ™เปƒเบ™ Javascript เป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡ SQL เปเบฅเบฐเบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™. เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เบžเบฝเบ‡โ€‹เปเบ•เปˆโ€‹เบ•เป‰เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบ—เบตเปˆโ€‹เบˆเบฐโ€‹เบŠเบตเป‰โ€‹เบšเบญเบโ€‹เบงเบดโ€‹เบ—เบตโ€‹เบเบฒเบ™โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เบ•เบปเบงโ€‹เบเบญเบ‡โ€‹เบเบฒเบ™โ€‹เปเบšเปˆเบ‡โ€‹เบ›เบฑเบ™โ€‹เปƒเบ™โ€‹เป‚เบ„เบ‡โ€‹เบเบฒเบ™โ€‹เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹.

เบกเบฒเบชเป‰เบฒเบ‡เปเบญเบฑเบšเบžเบฅเบดเป€เบ„เบŠเบฑเบ™ Cube.js เปƒเปเปˆ. เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ AWS stack เบขเบนเปˆเปเบฅเป‰เบง, เบกเบฑเบ™เบชเบปเบกเป€เบซเบ”เบชเบปเบกเบœเบปเบ™เบ—เบตเปˆเบˆเบฐเปƒเบŠเป‰ Lambda เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ•เบดเบ”เบ•เบฑเป‰เบ‡. เบ—เปˆเบฒเบ™โ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เบ™เปเบฒโ€‹เปƒเบŠเป‰โ€‹เปเบกเปˆโ€‹เปเบšเบšโ€‹เบชเบฐโ€‹เปเบ”เบ‡โ€‹เบญเบญเบโ€‹เบชเปเบฒโ€‹เบฅเบฑเบšโ€‹เบเบฒเบ™โ€‹เบœเบฐโ€‹เบฅเบดเบ”โ€‹เป„เบ”เป‰โ€‹เบ–เป‰เบฒโ€‹เบซเบฒเบโ€‹เบงเปˆเบฒโ€‹เบ—เปˆเบฒเบ™โ€‹เบงเบฒเบ‡โ€‹เปเบœเบ™โ€‹เบ—เบตเปˆโ€‹เบˆเบฐโ€‹เป€เบ›เบฑเบ™โ€‹เป€เบˆเบปเป‰เบฒโ€‹เบžเบฒเบš backend Cube.js เปƒเบ™ Heroku เบซเบผเบท Dockerโ€‹. เป€เบญเบเบฐเบชเบฒเบ™เบญเบฐเบ—เบดเบšเบฒเบเบ„เบปเบ™เบญเบทเปˆเบ™ เบงเบดเบ—เบตเบเบฒเบ™เป‚เบฎเบ”เบ•เบดเป‰เบ‡.

$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena

เบ•เบปเบงเปเบ›เบชเบฐเบžเบฒเบšเปเบงเบ”เบฅเป‰เบญเบกเปเบกเปˆเบ™เปƒเบŠเป‰เป€เบžเบทเปˆเบญเบ•เบฑเป‰เบ‡เบ„เปˆเบฒเบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เปƒเบ™ cube.js. เป€เบ„เบทเปˆเบญเบ‡เบเปเบฒเป€เบ™เบตเบ”เบˆเบฐเบชเป‰เบฒเบ‡เป„เบŸเบฅเปŒ .env เบ—เบตเปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบฅเบฐเบšเบธเบฅเบฐเบซเบฑเบ”เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เบชเปเบฒเบฅเบฑเบš Athena.

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™ เป‚เบ„เบ‡โ€‹เบเบฒเบ™โ€‹เบ‚เปเป‰โ€‹เบกเบนเบ™โ€‹, เปƒเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบŠเบตเป‰เบšเบญเบเบงเบดเบ—เบตเบเบฒเบ™เบšเบฑเบ™เบ—เบถเบเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเบ–เบทเบเป€เบเบฑเบšเป„เบงเป‰. เบขเบนเปˆเบ—เบตเปˆเบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบเบฑเบ‡เบชเบฒเบกเบฒเบ”เบเปเบฒเบ™เบปเบ”เบงเบดเบ—เบตเบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆ metrics เบชเปเบฒเบฅเบฑเบš dashboards.

เปƒเบ™โ€‹เบฅเบฐโ€‹เบšเบปเบšโ€‹ schema, เบชเป‰เบฒเบ‡เป„เบŸเบฅเปŒ Logs.js. เบ™เบตเป‰เปเบกเปˆเบ™เบ•เบปเบงเปเบšเบšเบ‚เปเป‰เบกเบนเบ™เบ•เบปเบงเบขเปˆเบฒเบ‡เบชเปเบฒเบฅเบฑเบš nginx:

เบฅเบฐเบซเบฑเบ”เบ•เบปเบงเปเบšเบš

const partitionFilter = (from, to) => `
    date(from_iso8601_timestamp(${from})) <= date_parse(partition_0 || partition_1 || partition_2, '%Y%m%d') AND
    date(from_iso8601_timestamp(${to})) >= date_parse(partition_0 || partition_1 || partition_2, '%Y%m%d')
    `

cube(`Logs`, {
  sql: `
  select * from part_demo_kinesis_bucket
  WHERE ${FILTER_PARAMS.Logs.createdAt.filter(partitionFilter)}
  `,

  measures: {
    count: {
      type: `count`,
    },

    errorCount: {
      type: `count`,
      filters: [
        { sql: `${CUBE.isError} = 'Yes'` }
      ]
    },

    errorRate: {
      type: `number`,
      sql: `100.0 * ${errorCount} / ${count}`,
      format: `percent`
    }
  },

  dimensions: {
    status: {
      sql: `status`,
      type: `number`
    },

    isError: {
      type: `string`,
      case: {
        when: [{
          sql: `${CUBE}.status >= 400`, label: `Yes`
        }],
        else: { label: `No` }
      }
    },

    createdAt: {
      sql: `from_unixtime(created_at)`,
      type: `time`
    }
  }
});

เปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบเปเบฒเบฅเบฑเบ‡เปƒเบŠเป‰เบ•เบปเบงเปเบ› FILTER_PARAMSเป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡เบ„เปเบฒเบ–เบฒเบก SQL เบ—เบตเปˆเบกเบตเบ•เบปเบงเบเบญเบ‡เบžเบฒเบ—เบดเบŠเบฑเบ™.

เบžเบงเบเป€เบฎเบปเบฒเบเบฑเบ‡เบเปเบฒเบ™เบปเบ” metrics เปเบฅเบฐเบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเบชเบฐเปเบ”เบ‡เบขเบนเปˆเปƒเบ™ dashboard เปเบฅเบฐเบเปเบฒเบ™เบปเบ”เบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒ. Cube.js เบˆเบฐเบชเป‰เบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เป€เบžเบตเปˆเบกเป€เบ•เบตเบกเบ—เบตเปˆเบกเบตเบ‚เปเป‰เบกเบนเบ™เบฅเบงเบกเบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒเปเบฅเบฐเบˆเบฐเบ›เบฑเบšเบ›เบธเบ‡เบ‚เปเป‰เบกเบนเบ™เบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เป€เบกเบทเปˆเบญเบกเบฑเบ™เบกเบฒเบฎเบญเบ”. เบ™เบตเป‰เบšเปเปˆเบžเบฝเบ‡เปเบ•เปˆเป€เบฅเบฑเปˆเบ‡เบเบฒเบ™เบชเบญเบšเบ–เบฒเบก, เปเบ•เปˆเบเบฑเบ‡เบซเบผเบธเบ”เบœเปˆเบญเบ™เบ„เปˆเบฒเปƒเบŠเป‰เบˆเปˆเบฒเบเบ‚เบญเบ‡เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰ Athena.

เปƒเบซเป‰เป€เบžเบตเปˆเบกเบ‚เปเป‰เบกเบนเบ™เบ™เบตเป‰เปƒเบชเปˆเป„เบŸเบฅเปŒ schema เบ‚เปเป‰เบกเบนเบ™:

preAggregations: {
  main: {
    type: `rollup`,
    measureReferences: [count, errorCount],
    dimensionReferences: [isError, status],
    timeDimensionReference: createdAt,
    granularity: `day`,
    partitionGranularity: `month`,
    refreshKey: {
      sql: FILTER_PARAMS.Logs.createdAt.filter((from, to) => 
        `select
           CASE WHEN from_iso8601_timestamp(${to}) + interval '3' day > now()
           THEN date_trunc('hour', now()) END`
      )
    }
  }
}

เบžเบงเบเป€เบฎเบปเบฒเบฅเบฐเบšเบธเปƒเบ™เบฎเบนเบšเปเบšเบšเบ™เบตเป‰เบงเปˆเบฒเบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™เบ—เบตเปˆเบˆเบฐเบฅเบงเบšเบฅเบงเบกเบ‚เปเป‰เบกเบนเบ™เบฅเปˆเบงเบ‡เบซเบ™เป‰เบฒเบชเปเบฒเบฅเบฑเบšเบ—เบธเบ metrics เบ—เบตเปˆเปƒเบŠเป‰, เปเบฅเบฐเปƒเบŠเป‰เบเบฒเบ™เปเบšเปˆเบ‡เบ›เบฑเบ™เป‚เบ”เบเป€เบ”เบทเบญเบ™. เบเบฒเบ™เปเบšเปˆเบ‡เบชเปˆเบงเบ™เบ—เบฒเบ‡เบชเปˆเบงเบ™เบซเบ™เป‰เบฒเบ‚เบญเบ‡เบเบฒเบ™เบฅเบงเบšเบฅเบงเบก เบชเบฒเบกเบฒเบ”เป€เบฅเบฑเปˆเบ‡เบเบฒเบ™เป€เบเบฑเบšเบเบณเบ‚เปเป‰เบกเบนเบ™ เปเบฅเบฐเบญเบฑเบšเป€เบ”เบ”เป„เบ”เป‰เบขเปˆเบฒเบ‡เบกเบตเป„เบ™เบชเปเบฒเบ„เบฑเบ™.

เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เบ›เบฐเบเบญเบš dashboard เป„เบ”เป‰!

Cube.js backend เปƒเบซเป‰ REST API เปเบฅเบฐเบŠเบธเบ”เบ‚เบญเบ‡เบซเป‰เบญเบ‡เบชเบฐเบซเบกเบธเบ”เบฅเบนเบเบ„เป‰เบฒเบชเปเบฒเบฅเบฑเบšเบเบญเบšเบซเบ™เป‰เบฒเบ—เบตเปˆเบ™เบดเบเบปเบก. เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเปƒเบŠเป‰ React เป€เบงเบตเบŠเบฑเบ™เบ‚เบญเบ‡เบฅเบนเบเบ„เป‰เบฒเป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡ dashboard. Cube.js เปƒเบซเป‰เบ‚เปเป‰เบกเบนเบ™เป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ•เป‰เบญเบ‡เบเบฒเบ™เบซเป‰เบญเบ‡เบชเบฐเปเบธเบ”เบžเบฒเบš - เบ‚เป‰เบญเบเบกเบฑเบเบกเบฑเบ™ เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปƒเบซเบกเปˆ, เปเบ•เปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ™เปเบฒเปƒเบŠเป‰เบญเบฑเบ™เปƒเบ”เบเปเปˆเป„เบ”เป‰.

เป€เบŠเบตเบšเป€เบงเบต Cube.js เบเบญเบกเบฎเบฑเบšเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเปƒเบ™ เบฎเบนเบšเปเบšเบš JSON, เป€เบŠเบดเปˆเบ‡เบเปเบฒเบ™เบปเบ” metrics เบ—เบตเปˆเบ•เป‰เบญเบ‡เบเบฒเบ™. เบ•เบปเบงเบขเปˆเบฒเบ‡, เป€เบžเบทเปˆเบญเบ„เบดเบ”เป„เบฅเปˆเบˆเปเบฒเบ™เบงเบ™เบ‚เปเป‰เบœเบดเบ”เบžเบฒเบ”เบ—เบตเปˆ Nginx เปƒเบซเป‰เบ•เปเปˆเบกเบทเป‰, เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบชเบปเปˆเบ‡เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเบ•เปเปˆเป„เบ›เบ™เบตเป‰:

{
  "measures": ["Logs.errorCount"],
  "timeDimensions": [
    {
      "dimension": "Logs.createdAt",
      "dateRange": ["2019-01-01", "2019-01-07"],
      "granularity": "day"
    }
  ]
}

เปƒเบซเป‰เบ•เบดเบ”เบ•เบฑเป‰เบ‡เบฅเบนเบเบ‚เปˆเบฒเบ Cube.js เปเบฅเบฐเบซเป‰เบญเบ‡เบชเบฐเปเบธเบ”เบญเบปเบ‡เบ›เบฐเบเบญเบš React เบœเปˆเบฒเบ™ NPM:

$ npm i --save @cubejs-client/core @cubejs-client/react

เบžเบงเบเป€เบฎเบปเบฒเบ™เปเบฒเป€เบ‚เบปเป‰เบฒเบชเปˆเบงเบ™เบ›เบฐเบเบญเบš cubejs ะธ QueryRendererเป€เบžเบทเปˆเบญเบ”เบฒเบงเป‚เบซเบฅเบ”เบ‚เปเป‰เบกเบนเบ™, เปเบฅเบฐเป€เบเบฑเบšเบเปเบฒ dashboard:

เบฅเบฐเบซเบฑเบ” dashboard

import React from 'react';
import { LineChart, Line, XAxis, YAxis } from 'recharts';
import cubejs from '@cubejs-client/core';
import { QueryRenderer } from '@cubejs-client/react';

const cubejsApi = cubejs(
  'YOUR-CUBEJS-API-TOKEN',
  { apiUrl: 'http://localhost:4000/cubejs-api/v1' },
);

export default () => {
  return (
    <QueryRenderer
      query={{
        measures: ['Logs.errorCount'],
        timeDimensions: [{
            dimension: 'Logs.createdAt',
            dateRange: ['2019-01-01', '2019-01-07'],
            granularity: 'day'
        }]
      }}
      cubejsApi={cubejsApi}
      render={({ resultSet }) => {
        if (!resultSet) {
          return 'Loading...';
        }

        return (
          <LineChart data={resultSet.rawData()}>
            <XAxis dataKey="Logs.createdAt"/>
            <YAxis/>
            <Line type="monotone" dataKey="Logs.errorCount" stroke="#8884d8"/>
          </LineChart>
        );
      }}
    />
  )
}

เปเบซเบผเปˆเบ‡ dashboard เบกเบตเบขเบนเปˆ sandbox เบฅเบฐเบซเบฑเบ”.

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™