Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

ОбикновСно Π·Π° ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΈ Π°Π½Π°Π»ΠΈΠ· Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° Nginx сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Ρ‚ΡŠΡ€Π³ΠΎΠ²ΡΠΊΠΈ ΠΏΡ€ΠΎΠ΄ΡƒΠΊΡ‚ΠΈ ΠΈΠ»ΠΈ Π³ΠΎΡ‚ΠΎΠ²ΠΈ open-source Π°Π»Ρ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²ΠΈ, ΠΊΠ°Ρ‚ΠΎ Prometheus + Grafana. Π’ΠΎΠ²Π° Π΅ Π΄ΠΎΠ±ΡŠΡ€ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ Π·Π° ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΈΠ»ΠΈ Ρ€Π΅Π°Π»Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅ Π°Π½Π°Π»ΠΈΡ‚ΠΈΠΊΠ°, Π½ΠΎ Π½Π΅ Π΅ особСно ΡƒΠ΄ΠΎΠ±Π½ΠΎ Π·Π° историчСски Π°Π½Π°Π»ΠΈΠ·. На ΠΊΠΎΠΉΡ‚ΠΎ ΠΈ Π΄Π° Π΅ популярСн рСсурс ΠΎΠ±Π΅ΠΌΡŠΡ‚ ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ Π² Π»ΠΎΠ³ΠΎΠ²Π΅Ρ‚Π΅ Π½Π° nginx Π±ΡŠΡ€Π·ΠΎ нараства ΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·Π° Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈ ΠΎΠ±Π΅ΠΌΠΈ Π΄Π°Π½Π½ΠΈ Π΅ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π½Π΅Ρ‰ΠΎ ΠΏΠΎ-спСциализирано.

Π’ Ρ‚Π°Π·ΠΈ статия Ρ‰Π΅ опиша ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Athena Π·Π° Π°Π½Π°Π»ΠΈΠ· Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅Ρ‚Π΅, Π²Π·ΠΈΠΌΠ°ΠΉΠΊΠΈ Nginx Π·Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΈ Ρ‰Π΅ ΠΏΠΎΠΊΠ°ΠΆΠ° ΠΊΠ°ΠΊ ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ Π΄Π° сС създадС Π°Π½Π°Π»ΠΈΡ‚ΠΈΡ‡Π΅Π½ Π΄Π°ΡˆΠ±ΠΎΡ€Π΄, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ open-source Ρ„Ρ€Π΅ΠΉΠΌΡƒΡŠΡ€ΠΊΠ° cube.js. Π•Ρ‚ΠΎ ΠΏΡŠΠ»Π½Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π½Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ:

Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

TL:DR;
Π’Ρ€ΡŠΠ·ΠΊΠ° към готовия Π΄Π°ΡˆΠ±ΠΎΡ€Π΄.

Π—Π° ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° информацията ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Fluentd, Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° β€” AWS Kinesis Data Firehose ΠΈ AWS Glue, Π·Π° ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ β€” AWS S3. Π‘ ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° Ρ‚Π°Π·ΠΈ комбинация ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΡΡŠΡ…Ρ€Π°Π½ΡΠ²Π°ΠΌΠ΅ Π½Π΅ само Π»ΠΎΠ³ΠΎΠ²Π΅Ρ‚Π΅ Π½Π° 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β€œ:

Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

На слСдващата страница ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žRecord format conversionβ€œ β€” β€žEnabledβ€œ ΠΈ ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žApache ORCβ€œ ΠΊΠ°Ρ‚ΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° запис. Π‘ΠΏΠΎΡ€Π΅Π΄ изслСдвания Π½Π° някои ΠžΡƒΠ΅Π½ Πžβ€™ΠœΠ°Π»Π»Π΅ΠΉ, Ρ‚ΠΎΠ²Π° Π΅ оптималният Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° PrestoDB ΠΈ Athena. ΠšΠ°Ρ‚ΠΎ схСма посочСтС Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°, която ΡΡŠΠ·Π΄Π°Π΄ΠΎΡ…ΠΌΠ΅ ΠΏΠΎ-Π³ΠΎΡ€Π΅. ΠžΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Π΅ мСстополоТСниСто S3 Π² kinesis ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС всяко, ΠΎΡ‚ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° само схСмата. Но Π°ΠΊΠΎ посочитС Π΄Ρ€ΡƒΠ³ΠΎ мСстополоТСниС S3, няма Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Ρ‡Π΅Ρ‚Π΅Ρ‚Π΅ Ρ‚Π΅Π·ΠΈ записи ΠΎΡ‚ Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ‚Π°.

Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

Π˜Π·Π±ΠΈΡ€Π°ΠΌΠ΅ S3 Π·Π° ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΈ Π±Π°ΠΊΠ΅Ρ‚Π°, ΠΊΠΎΠΉΡ‚ΠΎ ΡΡŠΠ·Π΄Π°Π΄ΠΎΡ…ΠΌΠ΅ ΠΏΠΎ-Ρ€Π°Π½ΠΎ. Aws Glue Crawler, Π·Π° ΠΊΠΎΠΉΡ‚ΠΎ Ρ‰Π΅ Ρ€Π°Π·ΠΊΠ°ΠΆΠ° ΠΏΠΎ-късно, Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ с прСфикси Π² S3 Π±Π°ΠΊΠ΅Ρ‚Π°, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° Π³ΠΎ оставитС ΠΏΡ€Π°Π·Π΅Π½.

Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

ΠžΡΡ‚Π°Π½Π°Π»ΠΈΡ‚Π΅ ΠΎΠΏΡ†ΠΈΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС промСнят Π² зависимост ΠΎΡ‚ Π²Π°ΡˆΠΈΡ‚Π΅ натоварвания, Π°Π· ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌ стандартнитС. ΠžΠ±ΡŠΡ€Π½Π΅Ρ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Π΅ компрСсията Π² S3 Π½Π΅ Π΅ Π½Π°Π»ΠΈΡ‡Π½Π°, Π½ΠΎ ORC ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° собствСна компрСсия ΠΏΠΎ ΠΏΠΎΠ΄Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅.

Fluentd

Π‘Π΅Π³Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ смС настроили ΡΡŠΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅, трябва Π΄Π° настроим ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅Ρ‚ΠΎ. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Fluentd, Π·Π°Ρ‰ΠΎΡ‚ΠΎ ΠΎΠ±ΠΈΡ‡Π°ΠΌ Ruby, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Logstash ΠΈΠ»ΠΈ Π΄Π° ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Ρ‚Π΅ Π»ΠΎΠ³ΠΎΠ²Π΅Ρ‚Π΅ Π² kinesis Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ. Π‘Π΅Ρ€Π²Π΅Ρ€ΡŠΡ‚ Fluentd ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС пуснат ΠΏΠΎ няколко Π½Π°Ρ‡ΠΈΠ½Π°, Ρ‰Π΅ Ρ€Π°Π·ΠΊΠ°ΠΆΠ° Π·Π° docker, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Π΅ просто ΠΈ ΡƒΠ΄ΠΎΠ±Π½ΠΎ.

ΠŸΡŠΡ€Π²ΠΎ, Π½ΠΈ трябва Ρ„Π°ΠΉΠ»ΡŠΡ‚ Π·Π° конфигурация fluent.conf. Π‘ΡŠΠ·Π΄Π°ΠΉΡ‚Π΅ Π³ΠΎ ΠΈ Π΄ΠΎΠ±Π°Π²Π΅Ρ‚Π΅ source:

Ρ‚ΠΈΠΏ forward
ΠΏΠΎΡ€Ρ‚ 24224
ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ 0.0.0.0

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° стартиратС ΡΡŠΡ€Π²ΡŠΡ€ Fluentd. Ако ΠΈΠΌΠ°Ρ‚Π΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ ΠΏΠΎ-слоТна конфигурация, Π½Π° Docker Hub ΠΈΠΌΠ° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π΅Π½ Π³Π°ΠΉΠ΄, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΊΠ°ΠΊ Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ свой ΠΎΠ±Ρ€Π°Π·.

$ 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 ΠΈΠΌΠ° file tail plugin.

НСка Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π² конфигурацията Fluent парсинг Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅Ρ‚Π΅, настройкитС ΠΎΡ‚Π³ΠΎΡ€Π΅:

@type parser
  key_name log
  emit_invalid_record_to_error false
  
    @type json

И ΠΈΠ·ΠΏΡ€Π°Ρ‰Π°Π½Π΅ Π½Π° Π»ΠΎΠ³ΠΎΠ²Π΅Ρ‚Π΅ Π² Kinesis, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ kinesis firehose plugin:

@type kinesis_firehose
    region region
    delivery_stream_name 
    aws_key_id 
    aws_sec_key

Athena

Ако стС настроили всичко ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ, слСд извСстно Π²Ρ€Π΅ΠΌΠ΅ (ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ 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 Π³ΠΎΠ΄ΠΈΠ½Π°. Но ΠΊΠΎΠ»ΠΊΠΎ ΠΏΠΎ-Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ Π΅ Ρ‚ΠΎΠ²Π° Π² сравнСниС с просто Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΎΡ‚ Π½Π΅ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΎΠ½ΠΈΡ€Π°Π½Π° Ρ‚Π°Π±Π»ΠΈΡ†Π°? НСка Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ ΠΈ Π΄Π° ΠΈΠ·Π±Π΅Ρ€Π΅ΠΌ ΡΡŠΡ‰ΠΈΡ‚Π΅ записи, Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈΡ€Π°ΠΉΠΊΠΈ Π³ΠΈ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π²ΠΈ ΡˆΡ‚Π°ΠΌΠΏ:

Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

3.59 сСкунди ΠΈ 244.34 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡ‚Π° Π΄Π°Π½Π½ΠΈ Π½Π° датасСт, Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΈΠΌΠ° само сСдмица Π»ΠΎΠ³ΠΎΠ²Π΅. НСка ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Ρ„ΠΈΠ»Ρ‚ΡŠΡ€ ΠΏΠΎ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ:

Аналитика Π»ΠΎΠ³ΠΎΠ² Nginx с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Amazon Athena ΠΈ Cube.js

Малко ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ, Π½ΠΎ Π½Π°ΠΉ-Π²Π°ΠΆΠ½ΠΎΡ‚ΠΎ β€” само 1.23 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡ‚Π° Π΄Π°Π½Π½ΠΈ! Π’ΠΎΠ²Π° Π±ΠΈ Π±ΠΈΠ»ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π΅Π²Ρ‚ΠΈΠ½ΠΎ, Π°ΠΊΠΎ Π½Π΅ бСшС минималният Π»ΠΈΠΌΠΈΡ‚ ΠΎΡ‚ 10 ΠΌΠ΅Π³Π°Π±Π°ΠΉΡ‚Π° Π·Π° заявка Π² Ρ†Π΅Π½ΠΎΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ. Но всС ΠΎΡ‰Π΅ Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅, Π° ΠΏΡ€ΠΈ Π³ΠΎΠ»Π΅ΠΌΠΈ датасСти Ρ€Π°Π·Π»ΠΈΠΊΠ°Ρ‚Π° Ρ‰Π΅ бъдС ΠΎΡ‰Π΅ ΠΏΠΎ-впСчатляваща.

Π‘ΠΎΠ±ΠΈΡ€Π°Π΅ΠΌ Π΄ΡΡˆΠ±ΠΎΡ€Π΄ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Cube.js

Π—Π° Π΄Π° ΡΡŠΠ±Π΅Ρ€Π΅ΠΌ Ρ‚Π°Π±Π»ΠΎ, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π°Π½Π°Π»ΠΈΡ‚ΠΈΡ‡Π½Π°Ρ‚Π° Ρ€Π°ΠΌΠΊΠ° Cube.js. Вя ΠΏΡ€Π΅Π΄Π»Π°Π³Π° доста Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½ΠΎ нас Π½ΠΈ интСрСсуват Π΄Π²Π΅: Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π½ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈ ΠΏΠΎ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ ΠΈ ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½Π° агрСгация Π½Π° Π΄Π°Π½Π½ΠΈ. Вя ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° схСма Π½Π° Π΄Π°Π½Π½ΠΈ data schema, написана Π½Π° 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, Π² ΠΊΠΎΠΉΡ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° посочитС Π²Π°ΡˆΠΈΡ‚Π΅ ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ Π·Π° Athena.

Π‘Π΅Π³Π° Ρ‰Π΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° схСма Π½Π° Π΄Π°Π½Π½ΠΈ, Π² която Ρ‰Π΅ посочим ΠΊΠ°ΠΊ Ρ‚ΠΎΡ‡Π½ΠΎ сС съ хранят Π½Π°ΡˆΠΈΡ‚Π΅ Π»ΠΎΠ³ΠΎΠ²Π΅. Π’Π°ΠΌ ΡΡŠΡ‰ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈ ΠΊΠ°ΠΊ Π΄Π° сС изчисляват ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈΡ‚Π΅ Π·Π° Π΄Π°ΡˆΠ±ΠΎΡ€Π΄ΠΎΠ²Π΅Ρ‚Π΅.

Π’ дирСкторията 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`
    }
  }
});

Π’ΡƒΠΊ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π°Ρ‚Π° FILTER_PARAMS, Π·Π° Π΄Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΠΌΠ΅ 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 прСдоставя REST API ΠΈ Π½Π°Π±ΠΎΡ€ клиСнтски Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Π·Π° популярни Ρ„Ρ€ΠΎΠ½Ρ‚Π΅Π½Π΄ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠ²Π΅. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ React вСрсията Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π·Π° ΠΈΠ·Π³Ρ€Π°ΠΆΠ΄Π°Π½Π΅ Π½Π° Π΄Π°ΡˆΠ±ΠΎΡ€Π΄Π°. Cube.js прСдоставя само Π΄Π°Π½Π½ΠΈ, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Ρ‰Π΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π° Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ β€” Π½Π° ΠΌΠ΅Π½ ΠΌΠΈ харСсва recharts, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ ΠΊΠ°ΠΊΠ²Π°Ρ‚ΠΎ ΠΈ Π΄Π° Π΅.

Π‘ΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Cube.js ΠΏΡ€ΠΈΠ΅ΠΌΠ° запитвания Π² JSON Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, Π² ΠΊΠΎΠΉΡ‚ΠΎ са посочСни Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ ΠΌΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ. НапримСр, Π·Π° Π΄Π° изчислим ΠΊΠΎΠ»ΠΊΠΎ Π³Ρ€Π΅ΡˆΠΊΠΈ Π΅ Π΄Π°Π» 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 (
          
            
            
            
          
        );
      }}
    />
  )
}

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈΡ‚Π΅ Π½Π° Π΄Π°ΡˆΠ±ΠΎΡ€Π΄Π° са Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π½Π° CodeSandbox.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster