Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

ื˜ื™ืคึผื™ืงืึทืœืœื™, ื’ืขืฉืขืคื˜ ืคึผืจืึธื“ื•ืงื˜ืŸ ืึธื“ืขืจ ืคืึทืจื˜ื™ืง ืขืคึฟืขื ืขืŸ-ืžืงื•ืจ ืึทืœื˜ืขืจื ืึทื˜ื™ื•ื•ืขืก, ืึทื–ืึท ื•ื•ื™ Prometheus + Grafana, ื–ืขื ืขืŸ ื’ืขื ื™ืฆื˜ ืฆื• ืžืึธื ื™ื˜ืึธืจ ืื•ืŸ ืึทื ืึทืœื™ื™ื– ื“ื™ ืึธืคึผืขืจืึทืฆื™ืข ืคื•ืŸ โ€‹โ€‹Nginx. ื“ืึธืก ืื™ื– ืึท ื’ื•ื˜ ืึธืคึผืฆื™ืข ืคึฟืึทืจ ืžืึธื ื™ื˜ืึธืจื™ื ื’ ืึธื“ืขืจ ืคืึทืงื˜ื™ืฉ-ืฆื™ื™ื˜ ืึทื ืึทืœื™ื˜ื™ืงืก, ืึธื‘ืขืจ ื ื™ืฉื˜ ื–ื™ื™ืขืจ ื‘ืึทืงื•ื•ืขื ืคึฟืึทืจ ื”ื™ืกื˜ืืจื™ืฉืข ืึทื ืึทืœื™ืกื™ืก. ืื•ื™ืฃ ืงื™ื™ืŸ ืคืึธืœืงืก ืžื™ื˜ืœ, ื“ื™ ื‘ืึทื ื“ ืคื•ืŸ ื“ืึทื˜ืŸ ืคื•ืŸ nginx ืœืึธื’ืก ืื™ื– ื’ืจืึธื•ื™ื ื’ ืจืึทืคึผืึทื“ืœื™, ืื•ืŸ ืฆื• ืึทื ืึทืœื™ื™ื– ืึท ื’ืจื•ื™ืก ืกื•ืžืข ืคื•ืŸ โ€‹โ€‹ื“ืึทื˜ืŸ, ืขืก ืื™ื– ืœืึทื“ื–ืฉื™ืงืึทืœ ืฆื• ื ื•ืฆืŸ ืขืคึผืขืก ืžืขืจ ืกืคึผืขืฉืึทืœื™ื™ื–ื“.

ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื™ืš ื•ื•ืขื˜ ื–ืึธื’ืŸ ืื™ืจ ื•ื•ื™ ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ืึทื˜ื”ืขื ืึท ืฆื• ืคื•ื ืึทื ื“ืขืจืงืœื™ื™ึทื‘ืŸ ืœืึธื’ืก, ื ืขืžืขืŸ Nginx ื•ื•ื™ ืึท ื‘ื™ื™ืฉืคึผื™ืœ, ืื•ืŸ ืื™ืš ื•ื•ืขืœ ื•ื•ื™ื™ึทื–ืŸ ื•ื•ื™ ืฆื• ืึทืกืขืžื‘ืึทืœ ืึทืŸ ืึทื ืึทืœื™ืกื™ืก ื“ืึทืฉื‘ืึธืจื“ ืคึฟื•ืŸ ื“ื™ ื“ืึทื˜ืŸ ื ื™ืฆืŸ ื“ื™ ืึธืคึฟืŸ ืžืงื•ืจ cube.js ืคืจื™ื™ืžื•ื•ืขืจืง. ื“ืึธ ืื™ื– ื“ื™ ืคื•ืœืฉื˜ืขื ื“ื™ืง ืœื™ื™ื–ื•ื ื’ ืึทืจืงืึทื˜ืขืงื˜ืฉืขืจ:

Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

TL:DR;
ืœื™ื ืง ืฆื• ื“ื™ ืคืึทืจื˜ื™ืง ื“ืึทืฉื‘ืึธืจื“.

ืฆื• ื–ืึทืžืœืขืŸ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ืžื™ืจ ื ื•ืฆืŸ ืคืœื•ืขื ื˜ื“, ืคึฟืึทืจ ืคึผืจืึทืกืขืกื™ื ื’ - AWS Kinesis Data Firehose ะธ AWS ืงืœื™ื™, ืคึฟืึทืจ ืกื˜ืึธืจื™ื“ื–ืฉ - ืึทื•ื•ืก ืก 3. ืžื™ื˜ ื“ืขื ืคึผืขืงืœ, ืื™ืจ ืงืขื ืขืŸ ืงืจืึธื ื ื™ื˜ ื‘ืœื•ื™ื– nginx ืœืึธื’ืก, ืึธื‘ืขืจ ืื•ื™ืš ืื ื“ืขืจืข ื’ืขืฉืขืขื ื™ืฉืŸ, ื•ื•ื™ ื’ืขื–ื•ื ื˜ ื•ื•ื™ ืœืึธื’ืก ืคื•ืŸ ืื ื“ืขืจืข ื‘ืึทื“ื™ื ื•ื ื’ืก. ืื™ืจ ืงืขื ืขืŸ ืคืึทืจื‘ื™ื™ึทื˜ืŸ ืขื˜ืœืขื›ืข ืคึผืึทืจืฅ ืžื™ื˜ ืขื ืœืขืš ืคึผืึทืจืฅ ืคึฟืึทืจ ื“ื™ื™ืŸ ืึธื ืœื™ื™ื’ืŸ, ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืื™ืจ ืงืขื ืขืŸ ืฉืจื™ื™ึทื‘ืŸ ืœืึธื’ืก ืฆื• ืงื™ื ืขืกื™ืก ื’ืœื™ื™ึทืš ืคึฟื•ืŸ nginx, ื‘ื™ื™ืคึผืึทืกื™ื ื’ ืคืœื•ืขื ื˜ื“ ืึธื“ืขืจ ื ื•ืฆืŸ ืœืึธื’ืกื˜ืึทืฉ ืคึฟืึทืจ ื“ืขื.

ืงืึทืœืขืงื˜ื™ื ื’ 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. ื“ืึธืก ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืงืจืึธื ืื•ืŸ ืึทื ืึทืœื™ื™ื– ืœืึธื’ืก ืื•ื™ืฃ ืื™ื™ืŸ ืึธืจื˜, ื•ื•ื™ื™ึทืœ ืึทื˜ื”ืขื ืึท ืงืขื ืขืŸ ืึทืจื‘ืขื˜ืŸ ืžื™ื˜ ื“ืึทื˜ืŸ ืื™ืŸ S3 ื’ืœื™ื™ึทืš. ืฉืคึผืขื˜ืขืจ ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื™ืš ื•ื•ืขื˜ ื–ืึธื’ืŸ ืื™ืจ ื•ื•ื™ ืฆื• ืœื™ื™ื’ืŸ ืื•ืŸ ืคึผืจืึธืฆืขืก ืœืึธื’ืก ืจื™ื›ื˜ื™ืง, ืึธื‘ืขืจ ืขืจืฉื˜ืขืจ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืึท ืจื™ื™ืŸ ืขืžืขืจ ืื™ืŸ S3, ืื™ืŸ ื•ื•ืึธืก ื’ืึธืจื ื™ืฉื˜ ืึทื ื“ืขืจืฉ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืกื˜ืึธืจื“. ืขืก ืื™ื– ื•ื•ืขืจื˜ ืฆื• ื‘ืึทื˜ืจืึทื›ื˜ืŸ ืื™ืŸ ืฉื˜ื™ื™ึทื’ืŸ ืื™ืŸ ื•ื•ืึธืก ื’ืขื’ื ื˜ ืื™ืจ ื•ื•ืขื˜ ืžืึทื›ืŸ ื“ื™ื™ืŸ ืขืžืขืจ, ื•ื•ื™ื™ึทืœ ืึทื˜ื”ืขื ืึท ืื™ื– ื ื™ืฉื˜ ื‘ื ื™ืžืฆื ืื™ืŸ ืึทืœืข ื’ืขื’ื ื˜ืŸ.

ืฉืึทืคึฟืŸ ืึท ืงืจื™ื™ึทื– ืื™ืŸ ื“ื™ ืึทื˜ื”ืขื ืึท ืงืึทื ืกืึธื•ืœ

ืœืึธืžื™ืจ ืžืึทื›ืŸ ืึท ื˜ื™ืฉ ืื™ืŸ ืึทื˜ื”ืขื ืึท ืคึฟืึทืจ ืœืึธื’ืก. ืขืก ืื™ื– ื“ืืจืฃ ืคึฟืึทืจ ื‘ื™ื™ื“ืข ืฉืจื™ื™ื‘ืŸ ืื•ืŸ ืœื™ื™ืขื ืขืŸ ืื•ื™ื‘ ืื™ืจ ืคึผืœืึทืŸ ืฆื• ื ื•ืฆืŸ Kinesis Firehose. ืขืคึฟืขื ืขืŸ ื“ื™ ืึทื˜ื”ืขื ืึท ืงืึทื ืกืึธื•ืœ ืื•ืŸ ืฉืึทืคึฟืŸ ืึท ื˜ื™ืฉ:

ืกืงืœ ื˜ื™ืฉ ืฉืึทืคื•ื ื’

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 ืคึฟื•ืŸ ืคืœื•ืขื ื˜ื“, ืึธื‘ืขืจ ืื™ืŸ ื“ืขื ืคืึทืœ ืื™ืจ ื•ื•ืขื˜ ื”ืึธื‘ืŸ ืฆื• ืฉืจื™ื™ึทื‘ืŸ JSON, ืื•ืŸ ื“ืึธืก ืื™ื– ื‘ืึทื˜ืœืึธื ื™ืฉ ื•ื•ื™ื™ึทืœ ืคื•ืŸ ื“ื™ ื’ืจื•ื™ืก ื’ืจื™ื™ืก ืคื•ืŸ ื“ื™ ื˜ืขืงืขืก. ืึทื“ื“ื™ื˜ื™ืึธื ืึทืœืœื™, ื•ื•ืขืŸ ื ื™ืฆืŸ PrestoDB ืึธื“ืขืจ Athena, JSON ืื™ื– ื“ื™ ืกืœืึธื•ืึทืกื˜ ื“ืึทื˜ืŸ ืคึฟืึธืจืžืึทื˜. ืึทื–ื•ื™ ืขืคึฟืขื ืขืŸ ื“ื™ Kinesis Firehose ืงืึทื ืกืึธื•ืœ, ื’ื™ื˜ "ืฉืึทืคึฟืŸ ืขืงืกืคึผืจืขืก ื˜ื™ื™ึทืš", ืกืขืœืขืงื˜ื™ืจืŸ "ื“ื™ืจืขืงื˜ PUT" ืื™ืŸ ื“ื™ "ืขืงืกืคึผืจืขืก" ืคืขืœื“:

Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

ืื™ืŸ ื“ืขืจ ื•ื•ื™ื™ึทื˜ืขืจ ืงื•ื•ื™ื˜ืœ, ืกืขืœืขืงื˜ื™ืจืŸ "ืจืขืงืึธืจื“ ืคึฟืึธืจืžืึทื˜ ืงืึทื ื•ื•ืขืจื–ืฉืึทืŸ" - "ืขื ืึทื‘ืœืขื“" ืื•ืŸ ืกืขืœืขืงื˜ื™ืจืŸ "ืึทืคึผืึทื˜ืฉื™ ORC" ื•ื•ื™ ื“ื™ ืจืขืงืึธืจื“ื™ื ื’ ืคึฟืึธืจืžืึทื˜. ืœื•ื™ื˜ ืฆื• ืขื˜ืœืขื›ืข ืคืึธืจืฉื•ื ื’ ืึธื•ื•ืขืŸ ืึธ'ืžืึทืœื™, ื“ืึธืก ืื™ื– ื“ื™ ืึธืคึผื˜ื™ืžืึทืœ ืคึฟืึธืจืžืึทื˜ ืคึฟืึทืจ PrestoDB ืื•ืŸ Athena. ืžื™ืจ ื ื•ืฆืŸ ื“ื™ ื˜ื™ืฉ ื•ื•ืึธืก ืžื™ืจ ื‘ืืฉืืคืŸ ืื•ื™ื‘ืŸ ื•ื•ื™ ืึท ืกื˜ืฉืขืžืึท. ื‘ื™ื˜ืข ื˜ืึธืŸ ืึทื– ืื™ืจ ืงืขื ืขืŸ ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ืงื™ื™ืŸ S3 ืึธืจื˜ ืื™ืŸ ืงื™ื ืขืกื™ืก; ื‘ืœื•ื™ื– ื“ื™ ืกื˜ืฉืขืžืึท ืื™ื– ื’ืขื ื™ืฆื˜ ืคึฟื•ืŸ ื“ื™ ื˜ื™ืฉ. ืึธื‘ืขืจ ืื•ื™ื‘ ืื™ืจ ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ืึท ืึทื ื“ืขืจืฉ S3 ืึธืจื˜, ืื™ืจ ื•ื•ืขื˜ ื ื™ืฉื˜ ืงืขื ืขืŸ ืฆื• ืœื™ื™ืขื ืขืŸ ื“ื™ ืจืขืงืึธืจื“ืก ืคึฟื•ืŸ ื“ืขื ื˜ื™ืฉ.

Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

ืžื™ืจ ืกืขืœืขืงื˜ื™ืจืŸ S3 ืคึฟืึทืจ ืกื˜ืึธืจื™ื“ื–ืฉ ืื•ืŸ ื“ื™ ืขืžืขืจ ื•ื•ืึธืก ืžื™ืจ ื‘ืืฉืืคืŸ ืคืจื™ืขืจ. Aws Glue Crawler, ื•ื•ืึธืก ืื™ืš ื•ื•ืขืœ ืจืขื“ืŸ ื•ื•ืขื’ืŸ ืึท ื‘ื™ืกืœ ืฉืคึผืขื˜ืขืจ, ืงืขืŸ ื ื™ืฉื˜ ืึทืจื‘ืขื˜ืŸ ืžื™ื˜ ืคึผืจืขืคื™ืงืก ืื™ืŸ ืึท S3 ืขืžืขืจ, ืึทื–ื•ื™ ืขืก ืื™ื– ื•ื•ื™ื›ื˜ื™ืง ืฆื• ืœืึธื–ืŸ ืขืก ืœื™ื™ื“ื™ืง.

Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

ื“ื™ ืจื•ืขืŸ ืึธืคึผืฆื™ืขืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ืคืืจืขื ื“ืขืจื˜ ื“ื™ืคึผืขื ื“ื™ื ื’ ืื•ื™ืฃ ื“ื™ื™ืŸ ืžืึทืกืข; ืื™ืš ื™ื•ื–ืฉืึทื•ื•ืึทืœื™ ื ื•ืฆืŸ ื“ื™ ืคืขืœื™ืงื™ื™ึทื˜ ืึธื ืขืก. ื‘ืึทืžืขืจืงื•ื ื’ ืึทื– S3 ืงืึทืžืคึผืจืขืฉืึทืŸ ืื™ื– ื ื™ื˜ ื‘ื ื™ืžืฆื, ืึธื‘ืขืจ ORC ื ื™ืฆื˜ ื’ืขื‘ื•ื™ืจืŸ ืงืึทืžืคึผืจืขืฉืึทืŸ ื“ื•ืจืš ืคืขืœื™ืงื™ื™ึทื˜.

ืคืœื•ืขื ื˜ื“

ืื™ืฆื˜ ืึทื– ืžื™ืจ ื”ืึธื‘ืŸ ืงืึทื ืคื™ื’ื™ืขืจื“ ืกื˜ืึธืจื™ื ื’ ืื•ืŸ ืจื™ืกื™ื•ื•ื™ื ื’ ืœืึธื’ืก, ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืงืึทื ืคื™ื’ื™ืขืจ ืฉื™ืงื˜. ืžื™ืจ ื•ื•ืขืœืŸ ื ื•ืฆืŸ ืคืœื•ืขื ื˜ื“, ื•ื•ื™ื™ึทืœ ืื™ืš ืœื™ื‘ืข ืจื•ื‘ื™, ืึธื‘ืขืจ ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ Logstash ืึธื“ืขืจ ืฉื™ืงืŸ ืœืึธื’ืก ืฆื• ืงื™ื ืขืกื™ืก ื’ืœื™ื™ึทืš. ื“ื™ ืคืœื•ืขื ื˜ื“ ืกืขืจื•ื•ืขืจ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืœืึธื ื˜ืฉื˜ ืื™ืŸ ืขื˜ืœืขื›ืข ื•ื•ืขื’ืŸ, ืื™ืš ื•ื•ืขื˜ ื–ืึธื’ืŸ ืื™ืจ ื•ื•ืขื’ืŸ ื“ืึธืงืขืจ ื•ื•ื™ื™ึทืœ ืขืก ืื™ื– ืคึผืฉื•ื˜ ืื•ืŸ ื‘ืึทืงื•ื•ืขื.

ืขืจืฉื˜ืขืจ, ืžื™ืจ ื“ืึทืจืคึฟืŸ ื“ื™ fluent.conf ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื˜ืขืงืข. ืฉืึทืคึฟืŸ ืขืก ืื•ืŸ ืœื™ื™ื’ืŸ ืžืงื•ืจ:

ื˜ื™ืคึผ ืคืึธืจื•ื™ืก
ืคึผืึธืจื˜ ืงืกื ื•ืžืงืก
ื‘ื™ื ื“ืŸ 0.0.0.0

ืื™ืฆื˜ ืื™ืจ ืงืขื ืขืŸ ืึธื ื”ื™ื™ื‘ืŸ ื“ื™ Fluentd ืกืขืจื•ื•ืขืจ. ืื•ื™ื‘ ืื™ืจ ื“ืึทืจืคึฟืŸ ืึท ืžืขืจ ืึทื•ื•ืึทื ืกื™ืจื˜ืข ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ, ื’ื™ื™ืŸ ืฆื• ื“ืึธืงืงืขืจ ื›ืึทื‘ ืขืก ืื™ื– ืึท ื“ื™ื˜ื™ื™ืœื“ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ, ืึทืจื™ื™ึทื ื’ืขืจืขื›ื ื˜ ื•ื•ื™ ืฆื• ืึทืกืขืžื‘ืึทืœ ื“ื™ื™ืŸ ื‘ื™ืœื“.

$ 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 ืฆื• ืงืึทืฉ ืœืึธื’ืก ืื™ื™ื“ืขืจ ืฉื™ืงืŸ. ืื™ืจ ืงืขื ืขืŸ ื˜ืึธืŸ ืึธืŸ ื“ืขื, ืึธื‘ืขืจ ื•ื•ืขืŸ ืื™ืจ ืจื™ืกื˜ืึทืจื˜, ืื™ืจ ืงืขื ืขืŸ ืคืึทืจืœื™ืจืŸ ืึทืœืฅ ืงืึทืฉื˜ ืžื™ื˜ ืฆื•ืจื™ืง-ื‘ืจื™ื™ืงื™ื ื’ ืึทืจื‘ืขื˜. ืื™ืจ ืงืขื ื˜ ืื•ื™ืš ื ื•ืฆืŸ ืงื™ื™ืŸ ืคึผืึธืจื˜; 24224 ืื™ื– ื“ื™ ืคืขืœื™ืงื™ื™ึทื˜ ืคืœื•ืขื ื˜ื“ ืคึผืึธืจื˜.

ืื™ืฆื˜ ืึทื– ืžื™ืจ ืœื•ื™ืคืŸ Fluent, ืžื™ืจ ืงืขื ืขืŸ ืฉื™ืงืŸ Nginx ืœืึธื’ืก ื“ืึธืจื˜. ืžื™ืจ ื™ื•ื–ืฉืึทื•ื•ืึทืœื™ ืœื•ื™ืคืŸ Nginx ืื™ืŸ ืึท ื“ืึธืงืงืขืจ ืงืึทื ื˜ื™ื™ื ืขืจ, ืื™ืŸ ื•ื•ืึธืก ืคืึทืœ ื“ืึธืงืขืจ ื”ืื˜ ืึท ื’ืขื‘ื•ื™ืจืŸ ืœืึธื’ื™ื ื’ ืฉืึธืคืขืจ ืคึฟืึทืจ ืคืœื•ืขื ื˜ื“:

$ 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 ื”ืื˜ ื˜ืขืงืข ืขืง ืคึผืœื•ื’ื™ืŸ.

ืœืึธืžื™ืจ ืœื™ื™ื’ืŸ ื“ืขื ืงืœืึธืฅ ืคึผืึทืจืกื™ื ื’ ืงืึทื ืคื™ื’ื™ืขืจื“ ืื•ื™ื‘ืŸ ืฆื• ื“ื™ ืคืœื•ืึทื ื˜ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ:

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

ืื•ืŸ ืฉื™ืงืŸ ืœืึธื’ืก ืฆื• ืงื™ื ืขืกื™ืก ื ื™ืฆืŸ 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>

ืึทื˜ื”ืขื ืึท

ืื•ื™ื‘ ืื™ืจ ื”ืึธื˜ ืงืึทื ืคื™ื’ื™ืขืจื“ ืึทืœืฅ ืจื™ื›ื˜ื™ืง, ื ืึธืš ืึท ื‘ืฉืขืช (ื“ื•ืจืš ืคืขืœื™ืงื™ื™ึทื˜, ืงื™ื ืขืกื™ืก ืจืขืงืึธืจื“ืก ื‘ืืงื•ืžืขืŸ ื“ืึทื˜ืŸ ืึทืžืึธืœ ื™ืขื“ืขืจ 10 ืžื™ื ื•ื˜) ืื™ืจ ื–ืึธืœ ื–ืขืŸ ืœืึธื’ ื˜ืขืงืขืก ืื™ืŸ S3. ืื™ืŸ ื“ื™ "ืžืึธื ื™ื˜ืึธืจื™ื ื’" ืžืขื ื™ื• ืคื•ืŸ Kinesis Firehose ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ ื•ื•ื™ ืคื™ืœ ื“ืึทื˜ืŸ ื–ืขื ืขืŸ ืจืขืงืึธืจื“ืขื“ ืื™ืŸ S3, ื•ื•ื™ ื’ืขื–ื•ื ื˜ ื•ื•ื™ ืขืจืจืึธืจืก. ื“ื• ื–ืืœืกื˜ ื ื™ืฉื˜ ืคืึทืจื’ืขืกืŸ ืฆื• ื’ืขื‘ืŸ ืฉืจื™ื™ื‘ืŸ ืึทืงืกืขืก ืฆื• ื“ื™ S3 ืขืžืขืจ ืฆื• ื“ื™ ืงื™ื ืขืกื™ืก ืจืึธืœืข. ืื•ื™ื‘ ืงื™ื ืขืกื™ืก ืงืขืŸ ื ื™ืฉื˜ ืคึผืึทืจืกื™ืจืŸ ืขืคึผืขืก, ืขืก ื•ื•ืขื˜ ืœื™ื™ื’ืŸ ื“ื™ ืขืจืจืึธืจืก ืฆื• ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืขืžืขืจ.

ืื™ืฆื˜ ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ ื“ื™ ื“ืึทื˜ืŸ ืื™ืŸ ืึทื˜ื”ืขื ืึท. ืœืึธืžื™ืจ ื’ืขืคึฟื™ื ืขืŸ ื“ื™ ืœืขืฆื˜ืข ืจื™ืงื•ื•ืขืก ืคึฟืึทืจ ื•ื•ืึธืก ืžื™ืจ ื”ืึธื‘ืŸ ืื•ืžื’ืขืงืขืจื˜ ืขืจืจืึธืจืก:

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

ืกืงืึทื ื™ื ื’ ืึทืœืข ืจืขืงืึธืจื“ืก ืคึฟืึทืจ ื™ืขื“ืขืจ ื‘ืงืฉื”

ืื™ืฆื˜ ืื•ื ื“ื–ืขืจ ืœืึธื’ืก ื–ืขื ืขืŸ ืคึผืจืึทืกืขืกื˜ ืื•ืŸ ืกื˜ืึธืจื“ ืื™ืŸ S3 ืื™ืŸ ORC, ืงืึทืžืคึผืจืขืกื˜ ืื•ืŸ ื’ืจื™ื™ื˜ ืคึฟืึทืจ ืึทื ืึทืœื™ืกื™ืก. Kinesis Firehose ืืคื™ืœื• ืึธืจื’ืึทื ื™ื–ื™ืจื˜ ื–ื™ื™ ืื™ืŸ ื“ื™ืจืขืงื˜ืขืจื™ื– ืคึฟืึทืจ ื™ืขื“ืขืจ ืฉืขื”. ืึธื‘ืขืจ, ื•ื•ื™ ืœืึทื ื’ ื•ื•ื™ ื“ื™ ื˜ื™ืฉ ืื™ื– ื ื™ืฉื˜ ืคึผืึทืจื˜ื™ืฉืึทื ื–, ืึทื˜ื”ืขื ืึท ื•ื•ืขื˜ ืœืึธื“ืŸ ืึทืœืข-ืฆื™ื™ื˜ ื“ืึทื˜ืŸ ืื•ื™ืฃ ื™ืขื“ืขืจ ื‘ืงืฉื”, ืžื™ื˜ ื–ืขืœื˜ืŸ ืื•ื™ืกื ืขืžืขืŸ. ื“ืึธืก ืื™ื– ืึท ื’ืจื•ื™ืก ืคึผืจืึธื‘ืœืขื ืคึฟืึทืจ ืฆื•ื•ื™ื™ ืกื™ื‘ื•ืช:

  • ื“ืขืจ ื‘ืึทื ื“ ืคื•ืŸ ื“ืึทื˜ืŸ ืื™ื– ืงืขืกื™ื™ื“ืขืจ ื’ืจืึธื•ื™ื ื’, ืกืœืึธื•ื™ื ื’ ืึทืจืึธืคึผ ืงื•ื•ื™ืจื™ื–;
  • ืึทื˜ื”ืขื ืึท ืื™ื– ื‘ื™ืœืขื“ ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ื“ื™ ื‘ืึทื ื“ ืคื•ืŸ ื“ืึทื˜ืŸ ืกืงืึทื ื“, ืžื™ื˜ ืึท ืžื™ื ื™ืžื•ื ืคื•ืŸ 10 ืžื‘ ืคึผืขืจ ื‘ืงืฉื”.

ืฆื• ืคืึทืจืจื™ื›ื˜ืŸ ื“ืขื, ืžื™ืจ ื ื•ืฆืŸ AWS Glue Crawler, ื•ื•ืึธืก ื•ื•ืขื˜ ืงืจื™ื›ืŸ ื“ื™ ื“ืึทื˜ืŸ ืื™ืŸ S3 ืื•ืŸ ืฉืจื™ื™ึทื‘ืŸ ื“ื™ ืฆืขื˜ื™ื™ืœื•ื ื’ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ืฆื• ื“ื™ Glue Metastore. ื“ืึธืก ื•ื•ืขื˜ ืœืึธื–ืŸ ืื•ื ื“ื– ืฆื• ื ื•ืฆืŸ ืคึผืึทืจื˜ื™ืฉืึทื ื– ื•ื•ื™ ืึท ืคื™ืœื˜ืขืจ ื•ื•ืขืŸ ืื™ืจ ืคืจืขื’ืŸ ืึทื˜ื”ืขื ืึท, ืื•ืŸ ืขืก ื•ื•ืขื˜ ื ืึธืจ ื™ื‘ืขืจืงื•ืงืŸ ื“ื™ ื“ื™ืจืขืงื˜ืขืจื™ื– ืกืคึผืขืกื™ืคื™ืขื“ ืื™ืŸ ื“ื™ ืึธื ืคึฟืจืขื’.

ื‘ืึทืฉื˜ืขื˜ื™ืงืŸ Amazon Glue Crawler

Amazon Glue Crawler ืกืงืึทื ื– ืึทืœืข ื“ื™ ื“ืึทื˜ืŸ ืื™ืŸ ื“ื™ S3 ืขืžืขืจ ืื•ืŸ ืงืจื™ื™ื™ืฅ ื˜ื™ืฉืŸ ืžื™ื˜ ืคึผืึทืจื˜ื™ืฉืึทื ื–. ืฉืึทืคึฟืŸ ืึท ืงืœื™ื™ ืงืจืึทื•ื•ืœืขืจ ืคึฟื•ืŸ ื“ื™ AWS ืงืœื™ื™ ืงืึทื ืกืึธื•ืœ ืื•ืŸ ืœื™ื™ื’ืŸ ืึท ืขืžืขืจ ื•ื•ื• ืื™ืจ ืงืจืึธื ื“ื™ ื“ืึทื˜ืŸ. ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ืื™ื™ืŸ ืงืจืึทื•ื•ืœืขืจ ืคึฟืึทืจ ืขื˜ืœืขื›ืข ื‘ืึทืงืึทืฅ, ืื™ืŸ ื•ื•ืึธืก ืคืึทืœ ืขืก ื•ื•ืขื˜ ืžืึทื›ืŸ ื˜ื™ืฉืŸ ืื™ืŸ ื“ื™ ืกืคึผืขืกื™ืคื™ืขื“ ื“ืึทื˜ืึทื‘ื™ื™ืก ืžื™ื˜ ื ืขืžืขืŸ ื•ื•ืึธืก ื’ืœื™ื™ึทื›ืŸ ื“ื™ ื ืขืžืขืŸ ืคื•ืŸ ื“ื™ ื‘ืึทืงืึทืฅ. ืื•ื™ื‘ ืื™ืจ ืคึผืœืึทืŸ ืฆื• ื ื•ืฆืŸ ื“ื™ ื“ืึทื˜ืŸ ืงืขืกื™ื™ื“ืขืจ, ื–ื™ื™ืŸ ื–ื™ื›ืขืจ ืฆื• ืงืึทื ืคื™ื’ื™ืขืจ Crawler ืก ืงืึทื˜ืขืจ ืคึผืœืึทืŸ ืฆื• ืคึผืึทืกืŸ ื“ื™ื™ืŸ ื“ืึทืจืฃ. ืžื™ืจ ื ื•ืฆืŸ ืื™ื™ืŸ ืงืจืึทื•ื•ืœืขืจ ืคึฟืึทืจ ืึทืœืข ื˜ื™ืฉืŸ, ื•ื•ืึธืก ืœื•ื™ืคื˜ ื™ืขื“ืขืจ ืฉืขื”.

ืฆืขื˜ื™ื™ืœื˜ ื˜ื™ืฉืŸ

ื ืึธืš ื“ืขืจ ืขืจืฉื˜ืขืจ ืงืึทื˜ืขืจ ืคื•ืŸ ื“ื™ ืงืจืึทื•ื•ืœืขืจ, ื“ื™ ื˜ื™ืฉืŸ ืคึฟืึทืจ ื™ืขื“ืขืจ ืกืงืึทื ื“ ืขืžืขืจ ื–ืึธืœ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื–ืŸ ืื™ืŸ ื“ื™ ื“ืึทื˜ืึทื‘ื™ื™ืก ืกืคึผืขืกื™ืคื™ืขื“ ืื™ืŸ ื“ื™ ืกืขื˜ื˜ื™ื ื’ืก. ืขืคึฟืขื ืขืŸ ื“ื™ ืึทื˜ื”ืขื ืึท ืงืึทื ืกืึธื•ืœ ืื•ืŸ ื’ืขืคึฟื™ื ืขืŸ ื“ื™ ื˜ื™ืฉ ืžื™ื˜ 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 ืื•ื™ืฃ ืืคืจื™ืœ XNUMX, XNUMX. ืื‘ืขืจ ื•ื•ื™ ืคื™ืœ ืžืขืจ ืขืคืขืงื˜ื™ื•ื• ืื™ื– ื“ืึธืก ื•ื•ื™ ื ืึธืจ ืœื™ื™ืขื ืขืŸ ืคื•ืŸ ืึท ื ื™ื˜-ืคึผืึทืจื˜ื™ื˜ืฉืึทื ื“ ื˜ื™ืฉ? ืœืึธืžื™ืจ ื’ืขืคึฟื™ื ืขืŸ ืื•ื™ืก ืื•ืŸ ืกืขืœืขืงื˜ื™ืจืŸ ื“ื™ ื–ืขืœื‘ืข ืจืขืงืึธืจื“ืก, ืคื™ืœื˜ืขืจื™ื ื’ ื–ื™ื™ ื“ื•ืจืš ื˜ื™ืžืขืกื˜ืึทืžืคึผ:

Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

3.59 ืกืขืงื•ื ื“ืขืก ืื•ืŸ 244.34 ืžืขื’ืื‘ื™ื™ื˜ ืคื•ืŸ ื“ืึทื˜ืŸ ืื•ื™ืฃ ืึท ื“ืึทื˜ืึทืกืขื˜ ืžื™ื˜ ื‘ืœื•ื™ื– ืึท ื•ื•ืึธืš ืคื•ืŸ ืœืึธื’ืก. ืœืึธืžื™ืจ ืคึผืจื•ื‘ื™ืจืŸ ืึท ืคื™ืœื˜ืขืจ ื“ื•ืจืš ืฆืขื˜ื™ื™ืœื•ื ื’:

Nginx ืœืึธื’ ืึทื ืึทืœื™ื˜ื™ืงืก ื ื™ืฆืŸ Amazon Athena ืื•ืŸ Cube.js

ื ื‘ื™ืกืœ ืคืึทืกื˜ืขืจ, ืึธื‘ืขืจ ืจื•ื‘ึฟ ื™ืžืคึผืึธืจื˜ืึทื ื˜ืœื™ - ื‘ืœื•ื™ื– 1.23 ืžืขื’ืื‘ื™ื™ื˜ ืคื•ืŸ ื“ืึทื˜ืŸ! ืขืก ื•ื•ืึธืœื˜ ื–ื™ื™ืŸ ืคื™ืœ ื˜ืฉื™ืคึผืขืจ ืื•ื™ื‘ ื ื™ืฉื˜ ืคึฟืึทืจ ื“ื™ ืžื™ื ื™ืžื•ื 10 ืžืขื’ืื‘ื™ื™ื˜ ืคึผืขืจ ื‘ืงืฉื” ืื™ืŸ ื“ื™ ืคึผืจื™ื™ืกื™ื ื’. ืึธื‘ืขืจ ืขืก ืื™ื– ื ืึธืš ืคื™ืœ ื‘ืขืกืขืจ, ืื•ืŸ ืื™ืŸ ื’ืจื•ื™ืก ื“ืึทื˜ืึทืกืขืฅ ื“ื™ ื—ื™ืœื•ืง ื•ื•ืขื˜ ื–ื™ื™ืŸ ืคื™ืœ ืžืขืจ ื™ืžืคึผืจืขืกื™ื•ื•.

ื‘ื•ื™ืขืŸ ืึท ื“ืึทืฉื‘ืึธืจื“ ื ื™ืฆืŸ Cube.js

ืฆื• ืึทืกืขืžื‘ืึทืœ ื“ื™ ื“ืึทืฉื‘ืึธืจื“, ืžื™ืจ ื ื•ืฆืŸ ื“ื™ Cube.js ืึทื ืึทืœื™ืกื™ืก ืคืจื™ื™ืžื•ื•ืขืจืง. ืขืก ื”ืื˜ ื’ืึทื ืฅ ืึท ืคึผืœืึทืฅ ืคื•ืŸ ืคืึทื ื’ืงืฉืึทื ื–, ืึธื‘ืขืจ ืžื™ืจ ื–ืขื ืขืŸ ืื™ื ื˜ืขืจืขืกื™ืจื˜ ืื™ืŸ ืฆื•ื•ื™ื™: ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ืื•ื™ื˜ืึธืžืึทื˜ื™ืฉ ื ื•ืฆืŸ ืฆืขื˜ื™ื™ืœื•ื ื’ ืคื™ืœื˜ืขืจืก ืื•ืŸ ื“ืึทื˜ืŸ ืคืึทืจ - ืึทื’ื’ืจืขื’ืึทื˜ื™ืึธืŸ. ืขืก ื ื™ืฆื˜ ื“ืึทื˜ืŸ ืกื˜ืฉืขืžืึท ื“ืึทื˜ืŸ ืกื˜ืฉืขืžืึท, ื’ืขืฉืจื™ื‘ืŸ ืื™ืŸ ื“ื–ืฉืึทื•ื•ืึทืกืงืจื™ืคึผื˜ ืฆื• ื“ื–ืฉืขื ืขืจื™ื™ื˜ ืกืงืœ ืื•ืŸ ื•ื™ืกืคื™ืจืŸ ืึท ื“ืึทื˜ืึทื‘ื™ื™ืก ืึธื ืคึฟืจืขื’. ืžื™ืจ ื ืึธืจ ื“ืึทืจืคึฟืŸ ืฆื• ืึธื ื•ื•ื™ื™ึทื–ืŸ ื•ื•ื™ ืฆื• ื ื•ืฆืŸ ื“ื™ ืฆืขื˜ื™ื™ืœื•ื ื’ ืคื™ืœื˜ืขืจ ืื™ืŸ ื“ื™ ื“ืึทื˜ืŸ ืกื˜ืฉืขืžืึท.

ืœืึธืžื™ืจ ืฉืึทืคึฟืŸ ืึท ื ื™ื™ึทืข Cube.js ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ื–ื™ื ื˜ ืžื™ืจ ืฉื•ื™ืŸ ื ื•ืฆืŸ ื“ื™ AWS ืึธื ืœื™ื™ื’ืŸ, ืขืก ืื™ื– ืœืึทื“ื–ืฉื™ืงืึทืœ ืฆื• ื ื•ืฆืŸ Lambda ืคึฟืึทืจ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜. ืื™ืจ ืงืขื ื˜ ื ื•ืฆืŸ ื“ื™ ืขืงืกืคึผืจืขืกืก ืžื•ืกื˜ืขืจ ืคึฟืึทืจ ื“ื•ืจ ืื•ื™ื‘ ืื™ืจ ืคึผืœืึทืŸ ืฆื• ื‘ืึทืœืขื‘ืึธืก ื“ื™ Cube.js ื‘ืึทืงืขื ื“ ืื™ืŸ Heroku ืึธื“ืขืจ Docker. ื“ื™ ื“ืึทืงื™ื•ืžืขื ื˜ื™ื™ืฉืึทืŸ ื‘ืืฉืจื™ื™ื‘ื˜ ืื ื“ืขืจืข ื”ืึธืกื˜ื™ื ื’ ืžืขื˜ื”ืึธื“ืก.

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

ืกื•ื•ื™ื•ื•ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื– ื–ืขื ืขืŸ ื’ืขื ื™ืฆื˜ ืฆื• ืงืึทื ืคื™ื’ื™ืขืจ ื“ื™ื™ื˜ืึทื‘ื™ื™ืก ืึทืงืกืขืก ืื™ืŸ cube.js. ื“ืขืจ ื’ืขื ืขืจืึทื˜ืึธืจ ื•ื•ืขื˜ ืฉืึทืคึฟืŸ ืึท .ืขื ื•ื• ื˜ืขืงืข ืื™ืŸ ื•ื•ืึธืก ืื™ืจ ืงืขื ืขืŸ ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ื“ื™ื™ืŸ ืฉืœื™ืกืœืขืŸ ืคึฟืึทืจ ืึทื˜ื”ืขื ืึท.

ืื™ืฆื˜ ืžื™ืจ ื“ืึทืจืคึฟืŸ ื“ืึทื˜ืŸ ืกื˜ืฉืขืžืึท, ืื™ืŸ ื•ื•ืึธืก ืžื™ืจ ื•ื•ืขืœืŸ ืึธื ื•ื•ื™ื™ึทื–ืŸ ืคึผื•ื ืงื˜ ื•ื•ื™ ืื•ื ื“ื–ืขืจ ืœืึธื’ืก ื–ืขื ืขืŸ ืกื˜ืึธืจื“. ืขืก ืื™ืจ ืงืขื ืขืŸ ืื•ื™ืš ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ื•ื•ื™ ืฆื• ืจืขื›ืขื ืขืŸ ืžืขื˜ืจื™ืงืก ืคึฟืึทืจ ื“ืึทืฉื‘ืึธืจื“ื–.

ืื™ืŸ ื“ืขืจ ื•ื•ืขื’ื•ื•ื™ื™ึทื–ืขืจ 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 ืึธื ืคึฟืจืขื’ ืžื™ื˜ ืึท ืฆืขื˜ื™ื™ืœื•ื ื’ ืคื™ืœื˜ืขืจ.

ืžื™ืจ ืื•ื™ืš ืฉื˜ืขืœืŸ ื“ื™ ืžืขื˜ืจื™ืงืก ืื•ืŸ ืคึผืึทืจืึทืžืขื˜ืขืจืก ื•ื•ืึธืก ืžื™ืจ ื•ื•ื™ืœืŸ ืฆื• ื•ื•ื™ื™ึทื–ืŸ ืื•ื™ืฃ ื“ื™ ื“ืึทืฉื‘ืึธืจื“ ืื•ืŸ ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ืคืึทืจ-ืึทื’ื’ื’ืจืขื’ืึทื˜ื™ืึธื ืก. Cube.js ื•ื•ืขื˜ ืฉืึทืคึฟืŸ ื ืึธืš ื˜ื™ืฉืŸ ืžื™ื˜ ืคืึทืจ-ืึทื’ื’ืึทื“ื–ืฉื™ื™ื˜ืึทื“ ื“ืึทื˜ืŸ ืื•ืŸ ื•ื•ืขื˜ ืื•ื™ื˜ืึธืžืึทื˜ื™ืฉ ื“ืขืจื”ื™ื™ึทื ื˜ื™ืงืŸ ื“ื™ ื“ืึทื˜ืŸ ื•ื•ืขืŸ ืขืก ืงื•ืžื˜. ื“ืึธืก ื ื™ื˜ ื‘ืœื•ื™ื– ืกืคึผื™ื“ื– ืึทืจื•ื™ืฃ ืคึฟืจืื’ืŸ, ืึธื‘ืขืจ ืื•ื™ืš ืจืึทื“ื•ืกืึทื– ื“ื™ ืงืึธืก ืคื•ืŸ ื ื™ืฆืŸ ืึทื˜ื”ืขื ืึท.

ืœืึธืžื™ืจ ืœื™ื™ื’ืŸ ื“ื™ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ืฆื• ื“ื™ ื“ืึทื˜ืŸ ืกื˜ืฉืขืžืึท ื˜ืขืงืข:

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`
      )
    }
  }
}

ืžื™ืจ ืกืคึผืขืฆื™ืคื™ืฆื™ืจืŸ ืื™ืŸ ื“ืขื ืžืึธื“ืขืœ ืึทื– ืขืก ืื™ื– ื ื™ื™ื˜ื™ืง ืฆื• ืคืึทืจ - ืึทื’ื’ืจืขื’ืึทื˜ืขื“ ื“ืึทื˜ืŸ ืคึฟืึทืจ ืึทืœืข ืžืขื˜ืจื™ืงืก ื’ืขื ื™ืฆื˜, ืื•ืŸ ื ื•ืฆืŸ ืคึผืึทืจื˜ื™ืฉืึทื ื™ื ื’ ื“ื•ืจืš ื—ื•ื“ืฉ. ืคืึทืจ - ืึทื’ื’ืจืขื’ืึทื˜ื™ืึธืŸ ืฆืขื˜ื™ื™ืœื•ื ื’ ืงืขื ืขืŸ ื‘ืื˜ื™ื™ื˜ื™ืง ืคืึทืจื’ื™ื›ืขืจืŸ ื“ืึทื˜ืŸ ื–ืึทืžืœื•ื ื’ ืื•ืŸ ืึทืคึผื“ื™ื™ื˜ื™ื ื’.

ืื™ืฆื˜ ืžื™ืจ ืงืขื ืขืŸ ืึทืกืขืžื‘ืึทืœ ื“ื™ ื“ืึทืฉื‘ืึธืจื“!

Cube.js ื‘ืึทืงืขื ื“ ื’ื™ื˜ REST API ืื•ืŸ ืึท ื’ืึทื ื’ ืคื•ืŸ ืงืœื™ืขื ื˜ ืœื™ื™ื‘ืจืขืจื™ื– ืคึฟืึทืจ ืคืึธืœืงืก ืคืจืึธื ื˜-ืกื•ืฃ ืคืจืึทืžืขื•ื•ืึธืจืงืก. ืžื™ืจ ื•ื•ืขืœืŸ ื ื•ืฆืŸ ื“ื™ ืจืขืึทืงื˜ ื•ื•ืขืจืกื™ืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ื“ืขื ืงืœื™ืขื ื˜ ืฆื• ื‘ื•ื™ืขืŸ ื“ื™ ื“ืึทืฉื‘ืึธืจื“. Cube.js ื’ื™ื˜ ื‘ืœื•ื™ื– ื“ืึทื˜ืŸ, ืึทื–ื•ื™ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืึท ื•ื•ื™ื–ืฉื•ื•ืึทืœืึทื–ื™ื™ืฉืึทืŸ ื‘ื™ื‘ืœื™ืึธื˜ืขืง - ืื™ืš ื•ื•ื™ ืขืก ืจื™ื˜ืฉืึทืฅ, ืึธื‘ืขืจ ืื™ืจ ืงืขื ืขืŸ ื ื•ืฆืŸ ืงื™ื™ืŸ.

ื“ื™ Cube.js ืกืขืจื•ื•ืขืจ ืึทืงืกืขืคึผืฅ ื“ื™ ื‘ืงืฉื” ืื™ืŸ JSON ืคึฟืึธืจืžืึทื˜, ื•ื•ืึธืก ืกืคึผืขืฆื™ืคื™ืฆื™ืจื˜ ื“ื™ ืคืืจืœืื ื’ื˜ ืžืขื˜ืจื™ืงืก. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืฆื• ืจืขื›ืขื ืขืŸ ื•ื•ื™ ืคื™ืœืข ืขืจืจืึธืจืก Nginx ื’ืขื’ืขื‘ืŸ ื“ื•ืจืš ื˜ืึธื’, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืฉื™ืงืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ื‘ืขื˜ืŸ:

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

ืœืึธืžื™ืจ ื™ื ืกื˜ืึทืœื™ืจืŸ ื“ื™ Cube.js ืงืœื™ืขื ื˜ ืื•ืŸ ื“ื™ ืจืขืึทืงื˜ ืงืึธืžืคึผืึธื ืขื ื˜ ื‘ื™ื‘ืœื™ืึธื˜ืขืง ื“ื•ืจืš NPM:

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

ืžื™ืจ ืึทืจื™ื™ึทื ืคื™ืจ ืงืึทืžืคึผืึธื•ื ืึทื ืฅ cubejs ะธ QueryRendererืฆื• ืึธืคึผืœืึธื“ื™ืจืŸ ื“ื™ ื“ืึทื˜ืŸ ืื•ืŸ ืงืœื™ื™ึทื‘ืŸ ื“ื™ ื“ืึทืฉื‘ืึธืจื“:

ื“ืึทืฉื‘ืึธืจื“ ืงืึธื“

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>
        );
      }}
    />
  )
}

ื“ืึทืฉื‘ืึธืจื“ ืงื•ื•ืืœืŸ ื–ืขื ืขืŸ ื‘ื ื™ืžืฆื ืื™ืŸ ืงืึธื“ืขืงืกืึทื ื“ื‘ืึธืงืก.

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’