ΠΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ Π·Π° ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³ ΠΈ Π°Π½Π°Π»ΠΈΠ· Π½Π° ΡΠ°Π±ΠΎΡΠ°ΡΠ° Π½Π° Nginx ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ ΡΡΡΠ³ΠΎΠ²ΡΠΊΠΈ ΠΏΡΠΎΠ΄ΡΠΊΡΠΈ ΠΈΠ»ΠΈ Π³ΠΎΡΠΎΠ²ΠΈ open-source Π°Π»ΡΠ΅ΡΠ½Π°ΡΠΈΠ²ΠΈ, ΠΊΠ°ΡΠΎ Prometheus + Grafana. Π’ΠΎΠ²Π° Π΅ Π΄ΠΎΠ±ΡΡ Π²Π°ΡΠΈΠ°Π½Ρ Π·Π° ΠΌΠΎΠ½ΠΈΡΠΎΡΠΈΠ½Π³ ΠΈΠ»ΠΈ ΡΠ΅Π°Π»Π½ΠΎ Π²ΡΠ΅ΠΌΠ΅ Π°Π½Π°Π»ΠΈΡΠΈΠΊΠ°, Π½ΠΎ Π½Π΅ Π΅ ΠΎΡΠΎΠ±Π΅Π½ΠΎ ΡΠ΄ΠΎΠ±Π½ΠΎ Π·Π° ΠΈΡΡΠΎΡΠΈΡΠ΅ΡΠΊΠΈ Π°Π½Π°Π»ΠΈΠ·. ΠΠ° ΠΊΠΎΠΉΡΠΎ ΠΈ Π΄Π° Π΅ ΠΏΠΎΠΏΡΠ»ΡΡΠ΅Π½ ΡΠ΅ΡΡΡΡ ΠΎΠ±Π΅ΠΌΡΡ ΠΎΡ Π΄Π°Π½Π½ΠΈ Π² Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π½Π° nginx Π±ΡΡΠ·ΠΎ Π½Π°ΡΠ°ΡΡΠ²Π° ΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈ ΠΎΠ±Π΅ΠΌΠΈ Π΄Π°Π½Π½ΠΈ Π΅ Π»ΠΎΠ³ΠΈΡΠ½ΠΎ Π΄Π° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π½Π΅ΡΠΎ ΠΏΠΎ-ΡΠΏΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½ΠΎ.
Π ΡΠ°Π·ΠΈ ΡΡΠ°ΡΠΈΡ ΡΠ΅ ΠΎΠΏΠΈΡΠ° ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° Π°Π½Π°Π»ΠΈΠ· Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅, Π²Π·ΠΈΠΌΠ°ΠΉΠΊΠΈ Nginx Π·Π° ΠΏΡΠΈΠΌΠ΅Ρ, ΠΈ ΡΠ΅ ΠΏΠΎΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ ΠΎΡ ΡΠ΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ Π΄Π° ΡΠ΅ ΡΡΠ·Π΄Π°Π΄Π΅ Π°Π½Π°Π»ΠΈΡΠΈΡΠ΅Π½ Π΄Π°ΡΠ±ΠΎΡΠ΄, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ open-source ΡΡΠ΅ΠΉΠΌΡΡΡΠΊΠ° cube.js. ΠΡΠΎ ΠΏΡΠ»Π½Π°ΡΠ° Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° Π½Π° ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ:

TL:DR;
.
ΠΠ° ΡΡΠ±ΠΈΡΠ°Π½Π΅ Π½Π° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡΡΠ° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ , Π·Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° β ΠΈ , Π·Π° ΡΡΡ ΡΠ°Π½Π΅Π½ΠΈΠ΅ β . Π‘ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π° ΡΠ°Π·ΠΈ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΡ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΡΡΡ ΡΠ°Π½ΡΠ²Π°ΠΌΠ΅ Π½Π΅ ΡΠ°ΠΌΠΎ Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π½Π° nginx, Π½ΠΎ ΠΈ Π΄ΡΡΠ³ΠΈ ΡΡΠ±ΠΈΡΠΈΡ, ΠΊΠ°ΠΊΡΠΎ ΠΈ Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π½Π° Π΄ΡΡΠ³ΠΈ ΡΡΠ»ΡΠ³ΠΈ. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π·Π°ΠΌΠ΅Π½ΠΈΡΠ΅ Π½ΡΠΊΠΎΠΈ ΡΠ°ΡΡΠΈ Ρ Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΈ Π½Π° Π²Π°ΡΠΈΡ ΡΡΠ΅ΠΊ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΠΈΡΠ΅ΡΠ΅ Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π² kinesis Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ ΠΎΡ nginx, Π·Π°ΠΎΠ±ΠΈΠΊΠ°Π»ΡΠΉΠΊΠΈ 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
Π©Π΅ ΡΡΠ·Π΄Π°Π΄Π΅ΠΌ ΡΠ°Π±Π»ΠΈΡΠ° Π² Athena Π·Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅. Π’Ρ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠ° ΠΊΠ°ΠΊΡΠΎ Π·Π° Π·Π°ΠΏΠΈΡ, ΡΠ°ΠΊΠ° ΠΈ Π·Π° ΡΠ΅ΡΠ΅Π½Π΅, Π°ΠΊΠΎ ΠΏΠ»Π°Π½ΠΈΡΠ°ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Kinesis Firehose. ΠΡΠ²ΠΎΡΠ΅ΡΠ΅ ΠΊΠΎΠ½Π·ΠΎΠ»Π°ΡΠ° Athena ΠΈ ΡΡΠ·Π΄Π°ΠΉΡΠ΅ ΡΠ°Π±Π»ΠΈΡΠ°:
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://'
TBLPROPERTIES ('has_encrypted_data'='false');Π‘ΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ Kinesis Firehose Stream
Kinesis Firehose ΡΠ΅ Π·Π°ΠΏΠΈΡΠ΅ Π΄Π°Π½Π½ΠΈΡΠ΅, ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈ ΠΎΡ Nginx, Π² S3 Π² ΠΈΠ·Π±ΡΠ°Π½ΠΈΡ ΡΠΎΡΠΌΠ°Ρ, ΡΠ°Π·Π΄Π΅Π»ΡΠΉΠΊΠΈ Π³ΠΈ ΠΏΠΎ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΈ Π² ΡΠΎΡΠΌΠ°Ρ ΠΠΠΠ/ΠΠ/ΠΠ/Π§Π§. Π’ΠΎΠ²Π° ΡΠ΅ Π±ΡΠ΄Π΅ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ ΠΏΡΠΈ ΡΠ΅ΡΠ΅Π½Π΅ Π½Π° Π΄Π°Π½Π½ΠΈΡΠ΅. ΠΠΎΠΆΠ΅ΡΠ΅, ΡΠ°Π·Π±ΠΈΡΠ° ΡΠ΅, Π΄Π° Π·Π°ΠΏΠΈΡΠ²Π°ΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ Π² S3 ΠΎΡ fluentd, Π½ΠΎ Π² ΡΠΎΠ·ΠΈ ΡΠ»ΡΡΠ°ΠΉ ΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° ΠΏΠΈΡΠ΅ΡΠ΅ JSON, ΠΊΠΎΠ΅ΡΠΎ Π½Π΅ Π΅ Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ ΠΏΠΎΡΠ°Π΄ΠΈ Π³ΠΎΠ»Π΅ΠΌΠΈΡ ΡΠ°Π·ΠΌΠ΅Ρ Π½Π° ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ΡΠ΅. ΠΡΠ²Π΅Π½ ΡΠΎΠ²Π°, ΠΏΡΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ΡΠΎ Π½Π° PrestoDB ΠΈΠ»ΠΈ Athena, JSON Π΅ Π½Π°ΠΉ-Π±Π°Π²Π½ΠΈΡΡ ΡΠΎΡΠΌΠ°Ρ Π½Π° Π΄Π°Π½Π½ΠΈ. Π’Π°ΠΊΠ° ΡΠ΅ ΠΎΡΠ²ΠΎΡΠ΅ΡΠ΅ ΠΊΠΎΠ½Π·ΠΎΠ»Π°ΡΠ° Kinesis Firehose, Π½Π°ΡΠΈΡΠ½Π΅ΡΠ΅ βCreate delivery streamβ, ΠΈΠ·Π±Π΅ΡΠ΅ΡΠ΅ βdirect PUTβ Π² ΠΏΠΎΠ»Π΅ΡΠΎ βdeliveryβ:

ΠΠ° ΡΠ»Π΅Π΄Π²Π°ΡΠ°ΡΠ° ΡΡΡΠ°Π½ΠΈΡΠ° ΠΈΠ·Π±Π΅ΡΠ΅ΡΠ΅ βRecord format conversionβ β βEnabledβ ΠΈ ΠΈΠ·Π±Π΅ΡΠ΅ΡΠ΅ βApache ORCβ ΠΊΠ°ΡΠΎ ΡΠΎΡΠΌΠ°Ρ Π·Π° Π·Π°ΠΏΠΈΡ. Π‘ΠΏΠΎΡΠ΅Π΄ ΠΈΠ·ΡΠ»Π΅Π΄Π²Π°Π½ΠΈΡ Π½Π° Π½ΡΠΊΠΎΠΈ , ΡΠΎΠ²Π° Π΅ ΠΎΠΏΡΠΈΠΌΠ°Π»Π½ΠΈΡΡ ΡΠΎΡΠΌΠ°Ρ Π·Π° PrestoDB ΠΈ Athena. ΠΠ°ΡΠΎ ΡΡ Π΅ΠΌΠ° ΠΏΠΎΡΠΎΡΠ΅ΡΠ΅ ΡΠ°Π±Π»ΠΈΡΠ°ΡΠ°, ΠΊΠΎΡΡΠΎ ΡΡΠ·Π΄Π°Π΄ΠΎΡ ΠΌΠ΅ ΠΏΠΎ-Π³ΠΎΡΠ΅. ΠΠ±ΡΡΠ½Π΅ΡΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΡΠ΅ ΠΌΠ΅ΡΡΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ S3 Π² kinesis ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ Π²ΡΡΠΊΠΎ, ΠΎΡ ΡΠ°Π±Π»ΠΈΡΠ°ΡΠ° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΡΠ°ΠΌΠΎ ΡΡ Π΅ΠΌΠ°ΡΠ°. ΠΠΎ Π°ΠΊΠΎ ΠΏΠΎΡΠΎΡΠΈΡΠ΅ Π΄ΡΡΠ³ΠΎ ΠΌΠ΅ΡΡΠΎΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ S3, Π½ΡΠΌΠ° Π΄Π° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠ΅ΡΠ΅ΡΠ΅ ΡΠ΅Π·ΠΈ Π·Π°ΠΏΠΈΡΠΈ ΠΎΡ ΡΠ°Π±Π»ΠΈΡΠ°ΡΠ°.

ΠΠ·Π±ΠΈΡΠ°ΠΌΠ΅ S3 Π·Π° ΡΡΡ ΡΠ°Π½Π΅Π½ΠΈΠ΅ ΠΈ Π±Π°ΠΊΠ΅ΡΠ°, ΠΊΠΎΠΉΡΠΎ ΡΡΠ·Π΄Π°Π΄ΠΎΡ ΠΌΠ΅ ΠΏΠΎ-ΡΠ°Π½ΠΎ. Aws Glue Crawler, Π·Π° ΠΊΠΎΠΉΡΠΎ ΡΠ΅ ΡΠ°Π·ΠΊΠ°ΠΆΠ° ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ, Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ°Π±ΠΎΡΠΈ Ρ ΠΏΡΠ΅ΡΠΈΠΊΡΠΈ Π² S3 Π±Π°ΠΊΠ΅ΡΠ°, ΡΠ°ΠΊΠ° ΡΠ΅ Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° Π³ΠΎ ΠΎΡΡΠ°Π²ΠΈΡΠ΅ ΠΏΡΠ°Π·Π΅Π½.

ΠΡΡΠ°Π½Π°Π»ΠΈΡΠ΅ ΠΎΠΏΡΠΈΠΈ ΠΌΠΎΠ³Π°Ρ Π΄Π° ΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΡΡ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡ ΠΎΡ Π²Π°ΡΠΈΡΠ΅ Π½Π°ΡΠΎΠ²Π°ΡΠ²Π°Π½ΠΈΡ, Π°Π· ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΈΡΠ΅. ΠΠ±ΡΡΠ½Π΅ΡΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΡΠ΅ ΠΊΠΎΠΌΠΏΡΠ΅ΡΠΈΡΡΠ° Π² S3 Π½Π΅ Π΅ Π½Π°Π»ΠΈΡΠ½Π°, Π½ΠΎ ORC ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΡΠΎΠ±ΡΡΠ²Π΅Π½Π° ΠΊΠΎΠΌΠΏΡΠ΅ΡΠΈΡ ΠΏΠΎ ΠΏΠΎΠ΄ΡΠ°Π·Π±ΠΈΡΠ°Π½Π΅.
Fluentd
Π‘Π΅Π³Π°, ΠΊΠΎΠ³Π°ΡΠΎ ΡΠΌΠ΅ Π½Π°ΡΡΡΠΎΠΈΠ»ΠΈ ΡΡΡ ΡΠ°Π½Π΅Π½ΠΈΠ΅ΡΠΎ ΠΈ ΠΏΠΎΠ»ΡΡΠ°Π²Π°Π½Π΅ΡΠΎ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅, ΡΡΡΠ±Π²Π° Π΄Π° Π½Π°ΡΡΡΠΎΠΈΠΌ ΠΈΠ·ΠΏΡΠ°ΡΠ°Π½Π΅ΡΠΎ. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ , Π·Π°ΡΠΎΡΠΎ ΠΎΠ±ΠΈΡΠ°ΠΌ Ruby, Π½ΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Logstash ΠΈΠ»ΠΈ Π΄Π° ΠΈΠ·ΠΏΡΠ°ΡΠ°ΡΠ΅ Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π² kinesis Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ. Π‘Π΅ΡΠ²Π΅ΡΡΡ Fluentd ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ ΠΏΡΡΠ½Π°Ρ ΠΏΠΎ Π½ΡΠΊΠΎΠ»ΠΊΠΎ Π½Π°ΡΠΈΠ½Π°, ΡΠ΅ ΡΠ°Π·ΠΊΠ°ΠΆΠ° Π·Π° docker, Π·Π°ΡΠΎΡΠΎ Π΅ ΠΏΡΠΎΡΡΠΎ ΠΈ ΡΠ΄ΠΎΠ±Π½ΠΎ.
ΠΡΡΠ²ΠΎ, Π½ΠΈ ΡΡΡΠ±Π²Π° ΡΠ°ΠΉΠ»ΡΡ Π·Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ fluent.conf. Π‘ΡΠ·Π΄Π°ΠΉΡΠ΅ Π³ΠΎ ΠΈ Π΄ΠΎΠ±Π°Π²Π΅ΡΠ΅ source:
forward
ΠΏΠΎΡΡ 24224
ΡΠ²ΡΡΠ·Π²Π°Π½Π΅ 0.0.0.0
Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ°ΡΠ΅ ΡΡΡΠ²ΡΡ Fluentd. ΠΠΊΠΎ ΠΈΠΌΠ°ΡΠ΅ Π½ΡΠΆΠ΄Π° ΠΎΡ ΠΏΠΎ-ΡΠ»ΠΎΠΆΠ½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ, Π½Π° ΠΈΠΌΠ° ΠΏΠΎΠ΄ΡΠΎΠ±Π΅Π½ Π³Π°ΠΉΠ΄, Π²ΠΊΠ»ΡΡΠΈΡΠ΅Π»Π½ΠΎ ΠΊΠ°ΠΊ Π΄Π° ΡΡΠ·Π΄Π°Π΄Π΅ΡΠ΅ ΡΠ²ΠΎΠΉ ΠΎΠ±ΡΠ°Π·.
$ docker run
-d
-p 24224:24224
-p 24224:24224/udp
-v /data:/fluentd/log
-v :/fluentd/etc fluentd
-c /fluentd/etc/fluent.conf
fluent/fluentd:stableΠ’Π°Π·ΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΡΡΡ /fluentd/log Π·Π° ΠΊΠ΅ΡΠΈΡΠ°Π½Π΅ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ ΠΏΡΠ΅Π΄ΠΈ ΠΈΠ·ΠΏΡΠ°ΡΠ°Π½Π΅. ΠΠΎΠΆΠ΅ Π΄Π° ΠΌΠΈΠ½Π΅ΡΠ΅ ΠΈ Π±Π΅Π· ΡΠΎΠ²Π°, Π½ΠΎ ΠΏΡΠΈ ΡΠ΅ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π·Π°Π³ΡΠ±ΠΈΡΠ΅ Π²ΡΠΈΡΠΊΠΈ ΠΊΠ΅ΡΠΈΡΠ°Π½ΠΈ Π΄Π°Π½Π½ΠΈ, Π·Π° ΠΊΠΎΠΈΡΠΎ ΡΡΠ΅ ΡΠ°Π±ΠΎΡΠΈΠ»ΠΈ ΡΡΡΡΠ΄Π½ΠΎ. ΠΠΎΡΡΡΡ ΡΡΡΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΡΠ΄Π΅ Π²ΡΡΠΊΠ°ΠΊΡΠ², 24224 Π΅ ΠΏΠΎΠ΄ΡΠ°Π·Π±ΠΈΡΠ°ΡΠΈΡΡ ΡΠ΅ ΠΏΠΎΡΡ Π½Π° Fluentd.
Π‘Π΅Π³Π°, ΠΊΠΎΠ³Π°ΡΠΎ ΠΈΠΌΠ°ΠΌΠ΅ ΡΡΠ°ΡΡΠΈΡΠ°Π½ Fluentd, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·ΠΏΡΠ°ΡΠΈΠΌ Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π½Π° Nginx ΡΠ°ΠΌ. ΠΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΡΡΠ°ΡΡΠΈΡΠ°ΠΌΠ΅ Nginx Π² Docker ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ, ΠΈ Π² ΡΠΎΠ·ΠΈ ΡΠ»ΡΡΠ°ΠΉ Docker ΠΈΠΌΠ° Π²Π³ΡΠ°Π΄Π΅Π½ΠΈ Π΄ΡΠ°ΠΉΠ²Π΅ΡΠΈ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π·Π° Fluentd:
$ docker run
--log-driver=fluentd
--log-opt fluentd-address=
--log-opt tag="{{.Name}}"
-v /some/content:/usr/share/nginx/html:ro
-d
nginxΠΠΊΠΎ ΡΡΠ°ΡΡΠΈΡΠ°ΡΠ΅ Nginx ΠΏΠΎ Π΄ΡΡΠ³ Π½Π°ΡΠΈΠ½, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Π»ΠΎΠ³ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ΡΠ΅, Π² Fluentd ΠΈΠΌΠ° .
ΠΠ΅ΠΊΠ° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡΡΠ° Fluent ΠΏΠ°ΡΡΠΈΠ½Π³ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅, Π½Π°ΡΡΡΠΎΠΉΠΊΠΈΡΠ΅ ΠΎΡΠ³ΠΎΡΠ΅:
@type parser
key_name log
emit_invalid_record_to_error false
@type jsonΠ ΠΈΠ·ΠΏΡΠ°ΡΠ°Π½Π΅ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π² Kinesis, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ :
@type kinesis_firehose
region region
delivery_stream_name
aws_key_id
aws_sec_keyAthena
ΠΠΊΠΎ ΡΡΠ΅ Π½Π°ΡΡΡΠΎΠΈΠ»ΠΈ Π²ΡΠΈΡΠΊΠΎ ΠΏΡΠ°Π²ΠΈΠ»Π½ΠΎ, ΡΠ»Π΅Π΄ ΠΈΠ·Π²Π΅ΡΡΠ½ΠΎ Π²ΡΠ΅ΠΌΠ΅ (ΠΏΡΡΠ²ΠΎΠ½Π°ΡΠ°Π»Π½ΠΎ Kinesis Π·Π°ΠΏΠΈΡΠ²Π° ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡΠ΅ Π΄Π°Π½Π½ΠΈ Π½Π° Π²ΡΠ΅ΠΊΠΈ 10 ΠΌΠΈΠ½ΡΡΠΈ) ΡΡΡΠ±Π²Π° Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅ ΡΠ°ΠΉΠ»ΠΎΠ²Π΅ΡΠ΅ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π² S3. Π ΠΌΠ΅Π½ΡΡΠΎ βmonitoringβ Π½Π° 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 ΠΎΡ ΠΊΠΎΠ½Π·ΠΎΠ»Π°ΡΠ° Π½Π° AWS Glue ΠΈ Π΄ΠΎΠ±Π°Π²Π΅ΡΠ΅ ΠΊΠΎΡΠ°ΡΠ°, Π² ΠΊΠΎΡΡΠΎ ΡΡΡ ΡΠ°Π½ΡΠ²Π°ΡΠ΅ Π΄Π°Π½Π½ΠΈ. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ Π΅Π΄ΠΈΠ½ ΠΊΡΠ°ΡΠ»Π΅Ρ Π·Π° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΊΠΎΡΠΈ, Π² ΡΠΎΠ·ΠΈ ΡΠ»ΡΡΠ°ΠΉ ΡΠΎΠΉ ΡΠ΅ ΡΡΠ·Π΄Π°Π΄Π΅ ΡΠ°Π±Π»ΠΈΡΠΈ Π² ΡΠΊΠ°Π·Π°Π½Π°ΡΠ° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ Ρ ΠΈΠΌΠ΅Π½Π°, ΡΡΠ²ΠΏΠ°Π΄Π°ΡΠΈ Ρ ΠΈΠΌΠ΅Π½Π°ΡΠ° Π½Π° ΠΊΠΎΡΠΈΡΠ΅. ΠΠΊΠΎ ΠΏΠ»Π°Π½ΠΈΡΠ°ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ ΡΠ΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ, Π½Π΅ Π·Π°Π±ΡΠ°Π²ΡΠΉΡΠ΅ Π΄Π° Π½Π°ΡΡΡΠΎΠΈΡΠ΅ ΡΠ°Π·ΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π·Π° ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° Crawler Π² ΡΡΠΎΡΠ²Π΅ΡΡΡΠ²ΠΈΠ΅ Ρ Π½ΡΠΆΠ΄ΠΈΡΠ΅ ΡΠΈ. ΠΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π΅Π΄ΠΈΠ½ Crawler Π·Π° Π²ΡΠΈΡΠΊΠΈ ΡΠ°Π±Π»ΠΈΡΠΈ, ΠΊΠΎΠΉΡΠΎ ΡΡΠ°ΡΡΠΈΡΠ° Π½Π° Π²ΡΠ΅ΠΊΠΈ ΡΠ°Ρ.
ΠΠ°ΡΡΠΈΡΠΈΠΎΠ½ΠΈΡΠ°Π½ΠΈ ΡΠ°Π±Π»ΠΈΡΠΈ
Π‘Π»Π΅Π΄ ΠΏΡΡΠ²ΠΎΡΠΎ ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° ΠΊΡΠ°ΡΠ»Π΅ΡΠ° Π² Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ, ΠΏΠΎΡΠΎΡΠ΅Π½Π° Π² Π½Π°ΡΡΡΠΎΠΉΠΊΠΈΡΠ΅, ΡΡΡΠ±Π²Π° Π΄Π° ΡΠ΅ ΠΏΠΎΡΠ²ΡΡ ΡΠ°Π±Π»ΠΈΡΠΈ Π·Π° Π²ΡΡΠΊΠ° ΡΠΊΠ°Π½ΠΈΡΠ°Π½Π° ΠΊΠΎΡΠ°. ΠΡΠ²ΠΎΡΠ΅ΡΠ΅ ΠΊΠΎΠ½Π·ΠΎΠ»Π°ΡΠ° Π½Π° Athena ΠΈ Π½Π°ΠΌΠ΅ΡΠ΅ΡΠ΅ ΡΠ°Π±Π»ΠΈΡΠ° Ρ Π»ΠΎΠ³ΠΎΠ²Π΅ΡΠ΅ Π½Π° 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 Π³ΠΎΠ΄ΠΈΠ½Π°. ΠΠΎ ΠΊΠΎΠ»ΠΊΠΎ ΠΏΠΎ-Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ Π΅ ΡΠΎΠ²Π° Π² ΡΡΠ°Π²Π½Π΅Π½ΠΈΠ΅ Ρ ΠΏΡΠΎΡΡΠΎ ΡΠ΅ΡΠ΅Π½Π΅ ΠΎΡ Π½Π΅ΠΏΠ°ΡΡΠΈΡΠΈΠΎΠ½ΠΈΡΠ°Π½Π° ΡΠ°Π±Π»ΠΈΡΠ°? ΠΠ΅ΠΊΠ° ΡΠ°Π·Π±Π΅ΡΠ΅ΠΌ ΠΈ Π΄Π° ΠΈΠ·Π±Π΅ΡΠ΅ΠΌ ΡΡΡΠΈΡΠ΅ Π·Π°ΠΏΠΈΡΠΈ, ΡΠΈΠ»ΡΡΠΈΡΠ°ΠΉΠΊΠΈ Π³ΠΈ ΠΏΠΎ Π²ΡΠ΅ΠΌΠ΅Π²ΠΈ ΡΡΠ°ΠΌΠΏ:

3.59 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ ΠΈ 244.34 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡΠ° Π΄Π°Π½Π½ΠΈ Π½Π° Π΄Π°ΡΠ°ΡΠ΅Ρ, Π² ΠΊΠΎΠΉΡΠΎ ΠΈΠΌΠ° ΡΠ°ΠΌΠΎ ΡΠ΅Π΄ΠΌΠΈΡΠ° Π»ΠΎΠ³ΠΎΠ²Π΅. ΠΠ΅ΠΊΠ° ΠΎΠΏΠΈΡΠ°ΠΌΠ΅ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ ΠΏΠ°ΡΡΠΈΡΠΈΠΈ:

ΠΠ°Π»ΠΊΠΎ ΠΏΠΎ-Π±ΡΡΠ·ΠΎ, Π½ΠΎ Π½Π°ΠΉ-Π²Π°ΠΆΠ½ΠΎΡΠΎ β ΡΠ°ΠΌΠΎ 1.23 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡΠ° Π΄Π°Π½Π½ΠΈ! Π’ΠΎΠ²Π° Π±ΠΈ Π±ΠΈΠ»ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π΅Π²ΡΠΈΠ½ΠΎ, Π°ΠΊΠΎ Π½Π΅ Π±Π΅ΡΠ΅ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½ΠΈΡΡ Π»ΠΈΠΌΠΈΡ ΠΎΡ 10 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡΠ° Π·Π° Π·Π°ΡΠ²ΠΊΠ° Π² ΡΠ΅Π½ΠΎΠΎΠ±ΡΠ°Π·ΡΠ²Π°Π½Π΅ΡΠΎ. ΠΠΎ Π²ΡΠ΅ ΠΎΡΠ΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π΄ΠΎΠ±ΡΠ΅, Π° ΠΏΡΠΈ Π³ΠΎΠ»Π΅ΠΌΠΈ Π΄Π°ΡΠ°ΡΠ΅ΡΠΈ ΡΠ°Π·Π»ΠΈΠΊΠ°ΡΠ° ΡΠ΅ Π±ΡΠ΄Π΅ ΠΎΡΠ΅ ΠΏΠΎ-Π²ΠΏΠ΅ΡΠ°ΡΠ»ΡΠ²Π°ΡΠ°.
Π‘ΠΎΠ±ΠΈΡΠ°Π΅ΠΌ Π΄ΡΡΠ±ΠΎΡΠ΄ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Cube.js
ΠΠ° Π΄Π° ΡΡΠ±Π΅ΡΠ΅ΠΌ ΡΠ°Π±Π»ΠΎ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π°Π½Π°Π»ΠΈΡΠΈΡΠ½Π°ΡΠ° ΡΠ°ΠΌΠΊΠ° Cube.js. Π’Ρ ΠΏΡΠ΅Π΄Π»Π°Π³Π° Π΄ΠΎΡΡΠ° ΡΡΠ½ΠΊΡΠΈΠΈ, Π½ΠΎ Π½Π°Ρ Π½ΠΈ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΡΠ²Π°Ρ Π΄Π²Π΅: Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΡΠΈΠ»ΡΡΠΈ ΠΏΠΎ ΠΏΠ°ΡΡΠΈΡΠΈΠΈ ΠΈ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»Π½Π° Π°Π³ΡΠ΅Π³Π°ΡΠΈΡ Π½Π° Π΄Π°Π½Π½ΠΈ. Π’Ρ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΡΡ Π΅ΠΌΠ° Π½Π° Π΄Π°Π½Π½ΠΈ , Π½Π°ΠΏΠΈΡΠ°Π½Π° Π½Π° Javascript, Π·Π° Π΄Π° Π³Π΅Π½Π΅ΡΠΈΡΠ° SQL ΠΈ Π΄Π° ΠΈΠ·ΠΏΡΠ»Π½ΠΈ Π·Π°ΠΏΠΈΡΠ²Π°Π½Π΅ ΠΊΡΠΌ Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ. ΠΡ Π½Π°Ρ ΡΠ΅ ΠΈΠ·ΠΈΡΠΊΠ²Π° ΡΠ°ΠΌΠΎ Π΄Π° ΠΏΠΎΡΠΎΡΠΈΠΌ ΠΊΠ°ΠΊ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΠΈΠ»ΡΠ΅ΡΠ° ΠΏΠΎ ΠΏΠ°ΡΡΠΈΡΠΈΠΈ Π² ΡΡ Π΅ΠΌΠ°ΡΠ° Π½Π° Π΄Π°Π½Π½ΠΈ.
Π‘ΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ Π½ΠΎΠ²ΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Cube.js. Π’ΡΠΉ ΠΊΠ°ΡΠΎ Π²Π΅ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ AWS ΡΡΠ΅ΠΊ, Π΅ Π»ΠΎΠ³ΠΈΡΠ½ΠΎ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Lambda Π·Π° ΡΠ°Π·ΠΏΠΎΠ»Π°Π³Π°Π½Π΅. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ express ΡΠ°Π±Π»ΠΎΠ½ Π·Π° Π³Π΅Π½Π΅ΡΠΈΡΠ°Π½Π΅, Π°ΠΊΠΎ ΠΏΠ»Π°Π½ΠΈΡΠ°ΡΠ΅ Π΄Π° Ρ ΠΎΡΡΠ²Π°ΡΠ΅ Cube.js Π±Π΅ΠΊΠ΅Π½Π΄Π° Π² Heroku ΠΈΠ»ΠΈ Docker. Π Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡΡΠ° ΡΠ° ΠΎΠΏΠΈΡΠ°Π½ΠΈ ΠΈ Π΄ΡΡΠ³ΠΈ .
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athenaΠΠ° Π½Π°ΡΡΡΠΎΠΉΠΊΠ° Π½Π° Π΄ΠΎΡΡΡΠΏΠ° Π΄ΠΎ Π±Π°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ Π² cube.js ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π½Π° ΡΡΠ΅Π΄Π°ΡΠ°. ΠΠ΅Π½Π΅ΡΠ°ΡΠΎΡΡΡ ΡΠ΅ ΡΡΠ·Π΄Π°Π΄Π΅ ΡΠ°ΠΉΠ» .env, Π² ΠΊΠΎΠΉΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΏΠΎΡΠΎΡΠΈΡΠ΅ Π²Π°ΡΠΈΡΠ΅ ΠΊΠ»ΡΡΠΎΠ²Π΅ Π·Π° .
Π‘Π΅Π³Π° ΡΠ΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠ° , Π² ΠΊΠΎΡΡΠΎ ΡΠ΅ ΠΏΠΎΡΠΎΡΠΈΠΌ ΠΊΠ°ΠΊ ΡΠΎΡΠ½ΠΎ ΡΠ΅ ΡΡ Ρ ΡΠ°Π½ΡΡ Π½Π°ΡΠΈΡΠ΅ Π»ΠΎΠ³ΠΎΠ²Π΅. Π’Π°ΠΌ ΡΡΡΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈ ΠΊΠ°ΠΊ Π΄Π° ΡΠ΅ ΠΈΠ·ΡΠΈΡΠ»ΡΠ²Π°Ρ ΠΌΠ΅ΡΡΠΈΠΊΠΈΡΠ΅ Π·Π° Π΄Π°ΡΠ±ΠΎΡΠ΄ΠΎΠ²Π΅ΡΠ΅.
Π Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΡΡΠ° schema, ΡΡΠ·Π΄Π°ΠΉΡΠ΅ ΡΠ°ΠΉΠ» Logs.js. ΠΡΠΎ ΠΏΡΠΈΠΌΠ΅Ρ Π½Π° Π΄Π°Π½Π½Π° ΠΌΠΎΠ΄Π΅Π» Π·Π° nginx:
ΠΠΎΠ΄ Π½Π° ΠΌΠΎΠ΄Π΅Π»Π°
const partitionFilter = (from, to) => `
date(from_iso8601_timestamp(${from})) = 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`
}
}
});Π’ΡΠΊ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°ΡΠ° , Π·Π° Π΄Π° Π³Π΅Π½Π΅ΡΠΈΡΠ°ΠΌΠ΅ SQL Π·Π°ΡΠ²ΠΊΠ° Ρ ΡΠΈΠ»ΡΡΡ ΠΏΠΎ ΠΏΠ°ΡΡΠΈΡΠΈΠΈ.
Π‘ΡΡΠΎ ΡΠ°ΠΊΠ° Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈΡΠ΅ ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈΡΠ΅, ΠΊΠΎΠΈΡΠΎ ΠΈΡΠΊΠ°ΠΌΠ΅ Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ Π½Π° Π΄Π°ΡΠ±ΠΎΡΠ΄Π°, ΠΈ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠΌΠ΅ ΠΏΡΠ΅-Π°Π³ΡΠ΅Π³Π°ΡΠΈΠΈΡΠ΅. Cube.js ΡΠ΅ ΡΡΠ·Π΄Π°Π΄Π΅ Π΄ΠΎΠΏΡΠ»Π½ΠΈΡΠ΅Π»Π½ΠΈ ΡΠ°Π±Π»ΠΈΡΠΈ Ρ ΠΏΡΠ΅-Π°Π³ΡΠ΅Π³ΠΈΡΠ°Π½ΠΈ Π΄Π°Π½Π½ΠΈ ΠΈ ΡΠ΅ Π°ΠΊΡΡΠ°Π»ΠΈΠ·ΠΈΡΠ° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ Π΄Π°Π½Π½ΠΈΡΠ΅ ΠΏΡΠΈ ΠΏΠΎΡΡΡΠΏΠ²Π°Π½Π΅ΡΠΎ ΠΈΠΌ. Π’ΠΎΠ²Π° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° Π½Π΅ ΡΠ°ΠΌΠΎ Π΄Π° ΡΠ΅ ΡΡΠΊΠΎΡΡΡ Π·Π°ΡΠ²ΠΊΠΈΡΠ΅, Π½ΠΎ ΠΈ Π΄Π° ΡΠ΅ Π½Π°ΠΌΠ°Π»ΡΡ ΡΠ°Π·Ρ ΠΎΠ΄ΠΈΡΠ΅ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Athena.
ΠΠ΅ΠΊΠ° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΡΠ°Π·ΠΈ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π² ΡΠ°ΠΉΠ»Π° Π½Π° ΡΡ Π΅ΠΌΠ°ΡΠ° Π½Π° Π΄Π°Π½Π½ΠΈ:
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 ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Ρ ΠΈ Π½Π°Π±ΠΎΡ ΠΊΠ»ΠΈΠ΅Π½ΡΡΠΊΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π·Π° ΠΏΠΎΠΏΡΠ»ΡΡΠ½ΠΈ ΡΡΠΎΠ½ΡΠ΅Π½Π΄ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΎΠ²Π΅. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ React Π²Π΅ΡΡΠΈΡΡΠ° Π½Π° ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Π·Π° ΠΈΠ·Π³ΡΠ°ΠΆΠ΄Π°Π½Π΅ Π½Π° Π΄Π°ΡΠ±ΠΎΡΠ΄Π°. Cube.js ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Ρ ΡΠ°ΠΌΠΎ Π΄Π°Π½Π½ΠΈ, ΡΠ°ΠΊΠ° ΡΠ΅ ΡΠ΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π·Π° Π²ΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ β Π½Π° ΠΌΠ΅Π½ ΠΌΠΈ Ρ Π°ΡΠ΅ΡΠ²Π° , Π½ΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ ΠΊΠ°ΠΊΠ²Π°ΡΠΎ ΠΈ Π΄Π° Π΅.
Π‘ΡΡΠ²ΡΡΡΡ Cube.js ΠΏΡΠΈΠ΅ΠΌΠ° Π·Π°ΠΏΠΈΡΠ²Π°Π½ΠΈΡ Π² , Π² ΠΊΠΎΠΉΡΠΎ ΡΠ° ΠΏΠΎΡΠΎΡΠ΅Π½ΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΈΡΠ΅ ΠΌΠ΅ΡΡΠΈΠΊΠΈ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π·Π° Π΄Π° ΠΈΠ·ΡΠΈΡΠ»ΠΈΠΌ ΠΊΠΎΠ»ΠΊΠΎ Π³ΡΠ΅ΡΠΊΠΈ Π΅ Π΄Π°Π» 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, Π·Π° Π΄Π° ΠΈΠ·Π²Π»Π΅ΡΠ΅ΠΌ Π΄Π°Π½Π½ΠΈ, ΠΈ ΡΡΠ·Π΄Π°Π²Π°ΠΌΠ΅ Π΄Π°ΡΠ±ΠΎΡΠ΄Π°:
ΠΠΎΠ΄ΡΡ Π½Π° Π΄Π°ΡΠ±ΠΎΡΠ΄Π°
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 (
{
if (!resultSet) {
return 'Loading...';
}
return (
);
}}
/>
)
}ΠΠ·ΡΠΎΡΠ½ΠΈΡΠΈΡΠ΅ Π½Π° Π΄Π°ΡΠ±ΠΎΡΠ΄Π° ΡΠ° Π½Π°Π»ΠΈΡΠ½ΠΈ Π½Π° .
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
