Анализа Π½Π° Π΅Π²ΠΈΠ΄Π΅Π½Ρ†ΠΈΡ˜Π° Π½Π° Nginx ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Amazon Athena ΠΈ Cube.js

ΠžΠ±ΠΈΡ‡Π½ΠΎ, ΠΊΠΎΠΌΠ΅Ρ€Ρ†ΠΈΡ˜Π°Π»Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈ ΠΈΠ»ΠΈ Π³ΠΎΡ‚ΠΎΠ²ΠΈ Π°Π»Ρ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²ΠΈ со ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄, ΠΊΠ°ΠΊΠΎ ΡˆΡ‚ΠΎ сС Prometheus + Grafana, сС користат Π·Π° слСдСњС ΠΈ Π°Π½Π°Π»ΠΈΠ·Π° Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° Nginx. Ова Π΅ Π΄ΠΎΠ±Ρ€Π° ΠΎΠΏΡ†ΠΈΡ˜Π° Π·Π° слСдСњС ΠΈΠ»ΠΈ Π°Π½Π°Π»ΠΈΡ‚ΠΈΠΊΠ° Π²ΠΎ Ρ€Π΅Π°Π»Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅, Π½ΠΎ Π½Π΅ Π΅ ΠΌΠ½ΠΎΠ³Ρƒ ΠΏΠΎΠ³ΠΎΠ΄Π½Π° Π·Π° историска Π°Π½Π°Π»ΠΈΠ·Π°. На кој Π±ΠΈΠ»ΠΎ ΠΏΠΎΠΏΡƒΠ»Π°Ρ€Π΅Π½ рСсурс, ΠΎΠ±Π΅ΠΌΠΎΡ‚ Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ ΠΎΠ΄ Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈΡ‚Π΅ Π½Π° nginx Ρ€Π°ΠΏΠΈΠ΄Π½ΠΎ растС, Π° Π·Π° Π΄Π° сС Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π° Π³ΠΎΠ»Π΅ΠΌΠ° ΠΊΠΎΠ»ΠΈΡ‡ΠΈΠ½Π° Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ, Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΅ Π΄Π° сС користи Π½Π΅ΡˆΡ‚ΠΎ ΠΏΠΎΡΠΏΠ΅Ρ†ΠΈΡ˜Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ΠΎ.

Π’ΠΎ ΠΎΠ²Π°Π° ΡΡ‚Π°Ρ‚ΠΈΡ˜Π° ќС Π²ΠΈ ΠΊΠ°ΠΆΠ°ΠΌ ΠΊΠ°ΠΊΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ користитС АтСна Π΄Π° Π³ΠΈ Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈΡ‚Π΅, зСмајќи Π³ΠΎ Nginx ΠΊΠ°ΠΊΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΈ ќС ΠΏΠΎΠΊΠ°ΠΆΠ°ΠΌ ΠΊΠ°ΠΊΠΎ Π΄Π° составам Π°Π½Π°Π»ΠΈΡ‚ΠΈΡ‡ΠΊΠ° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π½Π° Ρ‚Π°Π±Π»Π° ΠΎΠ΄ ΠΎΠ²ΠΈΠ΅ ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ ја Ρ€Π°ΠΌΠΊΠ°Ρ‚Π° со ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ ΠΊΠΎΠ΄ cube.js. Π•Π²Π΅ ја цСлосната Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π½Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ:

Анализа Π½Π° Π΅Π²ΠΈΠ΄Π΅Π½Ρ†ΠΈΡ˜Π° Π½Π° Nginx ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Amazon Athena ΠΈ Cube.js

TL:DR;
Врска Π΄ΠΎ Π·Π°Π²Ρ€ΡˆΠ΅Π½Π°Ρ‚Π° ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π½Π° Ρ‚Π°Π±Π»Π°.

Π—Π° ΡΠΎΠ±ΠΈΡ€Π°ΡšΠ΅ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΡˆΡ‚ΠΎ Π³ΠΈ користимС Π’Π΅Ρ‡Π½ΠΎ, Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° - AWS Kinesis Data Firehose ΠΈ AWS Π»Π΅ΠΏΠ°ΠΊ, Π·Π° ΡΠΊΠ»Π°Π΄ΠΈΡ€Π°ΡšΠ΅ - AWS S3. ΠšΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Π³ΠΎ овој ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° складиратС Π½Π΅ само Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈ Π½Π° nginx, Ρ‚ΡƒΠΊΡƒ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ настани, ΠΊΠ°ΠΊΠΎ ΠΈ Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈ Π½Π° Π΄Ρ€ΡƒΠ³ΠΈ услуги. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π·Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π΅ΠΊΠΎΠΈ Π΄Π΅Π»ΠΎΠ²ΠΈ со слични Π·Π° Π²Π°ΡˆΠΈΠΎΡ‚ стСк, Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ Π»ΠΎΠ³ΠΎΠ²ΠΈ Π²ΠΎ кинСзис Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ ΠΎΠ΄ 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 Π½Π΅ Π΅ достапна Π²ΠΎ ситС Ρ€Π΅Π³ΠΈΠΎΠ½ΠΈ.

БоздавањС ΠΊΠΎΠ»ΠΎ Π²ΠΎ ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Атина

АјдС Π΄Π° создадСмС Ρ‚Π°Π±Π΅Π»Π° Π²ΠΎ Атина Π·Π° Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈ. ΠŸΠΎΡ‚Ρ€Π΅Π±Π΅Π½ Π΅ ΠΈ Π·Π° ΠΏΠΈΡˆΡƒΠ²Π°ΡšΠ΅ ΠΈ Π·Π° Ρ‡ΠΈΡ‚Π°ΡšΠ΅ Π΄ΠΎΠΊΠΎΠ»ΠΊΡƒ ΠΏΠ»Π°Π½ΠΈΡ€Π°Ρ‚Π΅ Π΄Π° користитС 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://<YOUR-S3-BUCKET>'
TBLPROPERTIES ('has_encrypted_data'='false');

БоздавањС Π½Π° Kinesis Firehose ΠΏΠΎΡ‚ΠΎΠΊ

Kinesis Firehose ќС Π³ΠΈ запишС ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈΡ‚Π΅ Π΄ΠΎΠ±ΠΈΠ΅Π½ΠΈ ΠΎΠ΄ Nginx Π²ΠΎ S3 Π²ΠΎ ΠΈΠ·Π±Ρ€Π°Π½ΠΈΠΎΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚, ΠΏΠΎΠ΄Π΅Π»ΡƒΠ²Π°Ρ˜ΡœΠΈ Π³ΠΈ Π²ΠΎ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡƒΠΌΠΈ Π²ΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π“Π“Π“Π“/ММ/Π”Π”/Π’Π’. Ова ќС Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ ΠΏΡ€ΠΈ Ρ‡ΠΈΡ‚Π°ΡšΠ΅ ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ. Π‘Π΅ Ρ€Π°Π·Π±ΠΈΡ€Π°, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΠΈΡˆΡƒΠ²Π°Ρ‚Π΅ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π½Π° S3 ΠΎΠ΄ fluentd, Π½ΠΎ Π²ΠΎ овој ΡΠ»ΡƒΡ‡Π°Ρ˜ ќС ΠΌΠΎΡ€Π° Π΄Π° Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ JSON, Π° Ρ‚ΠΎΠ° Π΅ нССфикасно ΠΏΠΎΡ€Π°Π΄ΠΈ Π³ΠΎΠ»Π΅ΠΌΠ°Ρ‚Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π° Π½Π° Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈΡ‚Π΅. Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΎ, ΠΊΠΎΠ³Π° користитС PrestoDB ΠΈΠ»ΠΈ Athena, JSON Π΅ Π½Π°Ρ˜Π±Π°Π²Π½ΠΈΠΎΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ. Π—Π°Ρ‚ΠΎΠ°, ΠΎΡ‚Π²ΠΎΡ€Π΅Ρ‚Π΅ ја ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π° Kinesis Firehose, ΠΊΠ»ΠΈΠΊΠ½Π΅Ρ‚Π΅ β€žΠšΡ€Π΅ΠΈΡ€Π°Ρ˜ ΠΏΠΎΡ‚ΠΎΠΊ Π·Π° ΠΈΡΠΏΠΎΡ€Π°ΠΊΠ°β€œ, ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žΠ΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ PUTβ€œ Π²ΠΎ ΠΏΠΎΠ»Π΅Ρ‚ΠΎ β€žΠΈΡΠΏΠΎΡ€Π°ΠΊΠ°β€œ:

Анализа Π½Π° Π΅Π²ΠΈΠ΄Π΅Π½Ρ†ΠΈΡ˜Π° Π½Π° Nginx ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Amazon Athena ΠΈ Cube.js

Π’ΠΎ слСдното Ρ˜Π°Π·ΠΈΡ‡Π΅, ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žΠšΠΎΠ½Π²Π΅Ρ€Π·ΠΈΡ˜Π° Π½Π° Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° ΡΠ½ΠΈΠΌΠ°ΡšΠ΅β€œ - β€žΠžΠ²ΠΎΠ·ΠΌΠΎΠΆΠ΅Π½ΠΎβ€œ ΠΈ ΠΈΠ·Π±Π΅Ρ€Π΅Ρ‚Π΅ β€žApache ORCβ€œ ΠΊΠ°ΠΊΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° снимањС. Π‘ΠΏΠΎΡ€Π΅Π΄ Π½Π΅ΠΊΠΎΠΈ ΠΈΡΡ‚Ρ€Π°ΠΆΡƒΠ²Π°ΡšΠ° ОвСн О'Мали, ΠΎΠ²Π° Π΅ ΠΎΠΏΡ‚ΠΈΠΌΠ°Π»Π½ΠΈΠΎΡ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° PrestoDB ΠΈ Athena. Ја користимС Ρ‚Π°Π±Π΅Π»Π°Ρ‚Π° ΡˆΡ‚ΠΎ ја создадовмС ΠΏΠΎΠ³ΠΎΡ€Π΅ ΠΊΠ°ΠΊΠΎ шСма. Π’Π΅ ΠΌΠΎΠ»ΠΈΠΌΠ΅ ΠΈΠΌΠ°Ρ˜Ρ‚Π΅ ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄ Π΄Π΅ΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π½Π°Π²Π΅Π΄Π΅Ρ‚Π΅ која Π±ΠΈΠ»ΠΎ Π»ΠΎΠΊΠ°Ρ†ΠΈΡ˜Π° S3 Π²ΠΎ ΠΊΠΈΠ½Π΅Π·Π°; само ΡˆΠ΅ΠΌΠ°Ρ‚Π° сС користи ΠΎΠ΄ Ρ‚Π°Π±Π΅Π»Π°Ρ‚Π°. Но, Π°ΠΊΠΎ Π½Π°Π²Π΅Π΄Π΅Ρ‚Π΅ Π΄Ρ€ΡƒΠ³Π° Π»ΠΎΠΊΠ°Ρ†ΠΈΡ˜Π° Π½Π° S3, Ρ‚ΠΎΠ³Π°Ρˆ Π½Π΅ΠΌΠ° Π΄Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΈ Ρ‡ΠΈΡ‚Π°Ρ‚Π΅ ΠΎΠ²ΠΈΠ΅ записи ΠΎΠ΄ ΠΎΠ²Π°Π° Ρ‚Π°Π±Π΅Π»Π°.

Анализа Π½Π° Π΅Π²ΠΈΠ΄Π΅Π½Ρ†ΠΈΡ˜Π° Π½Π° Nginx ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Amazon Athena ΠΈ Cube.js

Π˜Π·Π±ΠΈΡ€Π°ΠΌΠ΅ S3 Π·Π° ΡΠΊΠ»Π°Π΄ΠΈΡ€Π°ΡšΠ΅ ΠΈ ΠΊΠΎΡ€ΠΏΠ°Ρ‚Π° ΡˆΡ‚ΠΎ ја создадовмС ΠΏΡ€Π΅Ρ‚Ρ…ΠΎΠ΄Π½ΠΎ. Aws Glue Crawler, Π·Π° кој ќС Π·Π±ΠΎΡ€ΡƒΠ²Π°ΠΌ ΠΌΠ°Π»ΠΊΡƒ ΠΏΠΎΠ΄ΠΎΡ†Π½Π°, Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ со прСфикси Π²ΠΎ ΠΊΠΎΡ„Π° S3, ΠΏΠ° Π·Π°Ρ‚ΠΎΠ° Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° Π³ΠΎ оставитС ΠΏΡ€Π°Π·Π΅Π½.

Анализа Π½Π° Π΅Π²ΠΈΠ΄Π΅Π½Ρ†ΠΈΡ˜Π° Π½Π° Nginx ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ Amazon Athena ΠΈ Cube.js

ΠžΡΡ‚Π°Π½Π°Ρ‚ΠΈΡ‚Π΅ ΠΎΠΏΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΡ€ΠΎΠΌΠ΅Π½Π°Ρ‚ Π²ΠΎ зависност ΠΎΠ΄ Π²Π°ΡˆΠ΅Ρ‚ΠΎ ΠΎΠΏΡ‚ΠΎΠ²Π°Ρ€ΡƒΠ²Π°ΡšΠ΅; јас ΠΎΠ±ΠΈΡ‡Π½ΠΎ Π³ΠΈ користам стандарднитС. Π—Π°Π±Π΅Π»Π΅ΠΆΠ΅Ρ‚Π΅ Π΄Π΅ΠΊΠ° ΠΊΠΎΠΌΠΏΡ€Π΅ΡΠΈΡ˜Π°Ρ‚Π° S3 Π½Π΅ Π΅ достапна, Π½ΠΎ ORC стандардно користи ΠΌΠ°Ρ˜Ρ‡ΠΈΠ½ ΠΊΠΎΠΌΠΏΡ€Π΅ΡΠΈΡ˜Π°.

Π’Π΅Ρ‡Π½ΠΎ

Π‘Π΅Π³Π° ΠΊΠΎΠ³Π° ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π²ΠΌΠ΅ ΡΠΊΠ»Π°Π΄ΠΈΡ€Π°ΡšΠ΅ ΠΈ ΠΏΡ€ΠΈΠΌΠ°ΡšΠ΅ Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈ, Ρ‚Ρ€Π΅Π±Π° Π΄Π° Π³ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°ΠΌΠ΅ ΠΈΡΠΏΡ€Π°ΡœΠ°ΡšΠ΅Ρ‚ΠΎ. НиС ќС користимС Π’Π΅Ρ‡Π½ΠΎ, Π·Π°Ρ‚ΠΎΠ° ΡˆΡ‚ΠΎ ја сакам Π ΡƒΠ±ΠΈ, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° користитС Logstash ΠΈΠ»ΠΈ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π΄Π° ΠΈΡΠΏΡ€Π°ΡœΠ°Ρ‚Π΅ Π»ΠΎΠ³ΠΎΠ²ΠΈ Π½Π° кинСзис. Π‘Π΅Ρ€Π²Π΅Ρ€ΠΎΡ‚ Fluentd ΠΌΠΎΠΆΠ΅ Π΄Π° сС стартува Π½Π° Π½Π΅ΠΊΠΎΠ»ΠΊΡƒ Π½Π°Ρ‡ΠΈΠ½ΠΈ, ќС Π²ΠΈ ΠΊΠ°ΠΆΠ°ΠΌ Π·Π° docker бидСјќи Π΅ СдноставСн ΠΈ ΡƒΠ΄ΠΎΠ±Π΅Π½.

ΠŸΡ€Π²ΠΎ, ΠΏΠΎΡ‚Ρ€Π΅Π±Π½Π° Π½ΠΈ Π΅ конфигурациската Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠ° fluent.conf. НаправСтС Π³ΠΎ ΠΈ Π΄ΠΎΠ΄Π°Ρ˜Ρ‚Π΅ ΠΈΠ·Π²ΠΎΡ€:

Ρ‚ΠΈΠΏ Π½Π°ΠΏΡ€Π΅Π΄
ΠΏΠΎΡ€Ρ‚ 24224
Π²Ρ€Π·ΡƒΠ²Π° 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 Π΅ стандардната ΠΏΠΎΡ€Ρ‚Π° Fluentd.

Π‘Π΅Π³Π° ΠΊΠΎΠ³Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌΠ΅ Fluentd, ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° ΠΈΡΠΏΡ€Π°ΡœΠ°ΠΌΠ΅ Π»ΠΎΠ³ΠΎΠ²ΠΈ Π½Π° Nginx Ρ‚Π°ΠΌΡƒ. НиС ΠΎΠ±ΠΈΡ‡Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚ΠΈΠΌΠ΅ Nginx Π²ΠΎ ΠΊΠΎΠ½Ρ‚Π΅Ρ˜Π½Π΅Ρ€ Docker, Π²ΠΎ Ρ‚ΠΎΡ˜ ΡΠ»ΡƒΡ‡Π°Ρ˜ 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 ΠΏΡ€ΠΈΠΊΠ»ΡƒΡ‡ΠΎΠΊ Π·Π° опашка Π½Π° Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠ°.

АјдС Π΄Π° Π³ΠΎ Π΄ΠΎΠ΄Π°Π΄Π΅ΠΌΠ΅ ΠΏΠ°Ρ€ΡΠΈΡ€Π°ΡšΠ΅Ρ‚ΠΎ Π½Π° Π΄Π½Π΅Π²Π½ΠΈΠΊΠΎΡ‚ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π½ΠΎ ΠΏΠΎΠ³ΠΎΡ€Π΅ Π²ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΡ˜Π°Ρ‚Π° Fluent:

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

И ΠΈΡΠΏΡ€Π°ΡœΠ°ΡšΠ΅ Π»ΠΎΠ³ΠΎΠ²ΠΈ Π½Π° Kinesis ΠΊΠΎΡ€ΠΈΡΡ‚Π΅Ρ˜ΡœΠΈ 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>

АтСна

Ако стС ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°Π»Π΅ сè ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ, Ρ‚ΠΎΠ³Π°Ρˆ ΠΏΠΎ Π½Π΅ΠΊΠΎΠ΅ Π²Ρ€Π΅ΠΌΠ΅ (стандардно, Kinesis Π³ΠΈ снима ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ Сднаш Π½Π° сСкои 10 ΠΌΠΈΠ½ΡƒΡ‚ΠΈ) Ρ‚Ρ€Π΅Π±Π° Π΄Π° Π³ΠΈ Π²ΠΈΠ΄ΠΈΡ‚Π΅ Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠΈΡ‚Π΅ Π·Π° Π΅Π²ΠΈΠ΄Π΅Π½Ρ†ΠΈΡ˜Π° Π²ΠΎ S3. Π’ΠΎ ΠΌΠ΅Π½ΠΈΡ‚ΠΎ β€žΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³β€œ Π½Π° Kinesis Firehose ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ ΠΊΠΎΠ»ΠΊΡƒ ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ сС снимСни Π²ΠΎ S3, ΠΊΠ°ΠΊΠΎ ΠΈ Π³Ρ€Π΅ΡˆΠΊΠΈ. НС Π·Π°Π±ΠΎΡ€Π°Π²Π°Ρ˜Ρ‚Π΅ Π΄Π° Π΄Π°Π΄Π΅Ρ‚Π΅ пристап Π·Π° ΠΏΠΈΡˆΡƒΠ²Π°ΡšΠ΅ Π΄ΠΎ ΠΊΠΎΡ€ΠΏΠ°Ρ‚Π° S3 Π΄ΠΎ ΡƒΠ»ΠΎΠ³Π°Ρ‚Π° Π½Π° Kinesis. Ако Kinesis Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° Π°Π½Π°Π»ΠΈΠ·ΠΈΡ€Π° Π½Π΅ΡˆΡ‚ΠΎ, ќС Π³ΠΈ Π΄ΠΎΠ΄Π°Π΄Π΅ Π³Ρ€Π΅ΡˆΠΊΠΈΡ‚Π΅ Π²ΠΎ истата ΠΊΠΎΡ„Π°.

Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΈ Π²ΠΈΠ΄ΠΈΡ‚Π΅ ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈΡ‚Π΅ Π²ΠΎ Атина. АјдС Π΄Π° Π³ΠΈ најдСмС Π½Π°Ρ˜Π½ΠΎΠ²ΠΈΡ‚Π΅ Π±Π°Ρ€Π°ΡšΠ° Π·Π° ΠΊΠΎΠΈ Π²Ρ€Π°Ρ‚ΠΈΠ²ΠΌΠ΅ Π³Ρ€Π΅ΡˆΠΊΠΈ:

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

Π‘ΠΊΠ΅Π½ΠΈΡ€Π°ΡšΠ΅ Π½Π° ситС записи Π·Π° сСкоС Π±Π°Ρ€Π°ΡšΠ΅

Π‘Π΅Π³Π° Π½Π°ΡˆΠΈΡ‚Π΅ Π΄Π½Π΅Π²Π½ΠΈΡ†ΠΈ сС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π΅Π½ΠΈ ΠΈ складирани Π²ΠΎ S3 Π²ΠΎ ORC, компрСсирани ΠΈ ΠΏΠΎΠ΄Π³ΠΎΡ‚Π²Π΅Π½ΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·Π°. Kinesis Firehose Π΄ΡƒΡ€ΠΈ Π³ΠΈ ΠΎΡ€Π³Π°Π½ΠΈΠ·ΠΈΡ€Π°ΡˆΠ΅ Π²ΠΎ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡƒΠΌΠΈ Π·Π° сСкој час. Π‘Π΅ΠΏΠ°ΠΊ, сС Π΄ΠΎΠ΄Π΅ΠΊΠ° Ρ‚Π°Π±Π΅Π»Π°Ρ‚Π° Π½Π΅ Π΅ ΠΏΠΎΠ΄Π΅Π»Π΅Π½Π°, Athena ќС Π²Ρ‡ΠΈΡ‚Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ Π·Π° ситС Π²Ρ€Π΅ΠΌΠΈΡšΠ° Π½Π° сСкоС Π±Π°Ρ€Π°ΡšΠ΅, со Ρ€Π΅Ρ‚ΠΊΠΈ исклучоци. Ова Π΅ Π³ΠΎΠ»Π΅ΠΌ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΎΠ΄ Π΄Π²Π΅ ΠΏΡ€ΠΈΡ‡ΠΈΠ½ΠΈ:

  • ΠžΠ±Π΅ΠΌΠΎΡ‚ Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ ΠΏΠΎΡΡ‚ΠΎΡ˜Π°Π½ΠΎ растС, Π·Π°Π±Π°Π²ΡƒΠ²Π°Ρ˜ΡœΠΈ Π³ΠΈ Π±Π°Ρ€Π°ΡšΠ°Ρ‚Π°;
  • Атина сС наплаќа Π²Ρ€Π· основа Π½Π° ΠΎΠ±Π΅ΠΌΠΎΡ‚ Π½Π° скСнирани ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ, со ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ 10 MB ΠΏΠΎ Π±Π°Ρ€Π°ΡšΠ΅.

Π—Π° Π΄Π° Π³ΠΎ ΠΏΠΎΠΏΡ€Π°Π²ΠΈΠΌΠ΅ ΠΎΠ²Π°, користимС AWS Glue Crawler, кој ќС Π³ΠΈ индСксира ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈΡ‚Π΅ Π²ΠΎ S3 ΠΈ ќС Π³ΠΈ запишС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈΡ‚Π΅ Π·Π° ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΡ˜Π°Ρ‚Π° Π²ΠΎ Glue Metastore. Ова ќС Π½ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΠΈ Π΄Π° користимС ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ ΠΊΠ°ΠΊΠΎ Ρ„ΠΈΠ»Ρ‚Π΅Ρ€ ΠΏΡ€ΠΈ Π±Π°Ρ€Π°ΡšΠ΅Ρ‚ΠΎ Π½Π° Athena ΠΈ ќС Π³ΠΈ скСнира само Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡƒΠΌΠΈΡ‚Π΅ Π½Π°Π²Π΅Π΄Π΅Π½ΠΈ Π²ΠΎ Π±Π°Ρ€Π°ΡšΠ΅Ρ‚ΠΎ.

ΠŸΠΎΡΡ‚Π°Π²ΡƒΠ²Π°ΡšΠ΅ Π½Π° Amazon Glue Crawler

Amazon Glue Crawler Π³ΠΈ скСнира ситС ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ Π²ΠΎ ΠΊΠΎΡ€ΠΏΠ°Ρ‚Π° S3 ΠΈ создава Ρ‚Π°Π±Π΅Π»ΠΈ со ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ. Π‘ΠΎΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ Π»Π΅ΠΏΠ°ΠΊ 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. Има доста Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½ΠΎ Π½ΠΈΠ΅ смС заинтСрСсирани Π·Π° Π΄Π²Π΅: способност Π·Π° автоматско ΠΊΠΎΡ€ΠΈΡΡ‚Π΅ΡšΠ΅ Π½Π° Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈ Π·Π° ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ ΠΈ ΠΏΡ€Π΅Π΄-Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΡ˜Π° Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ. Π’Π°Π° користи ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ‡Π½Π° шСма ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ‡Π½Π° шСма, напишана Π²ΠΎ Javascript Π·Π° Π΄Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° SQL ΠΈ Π΄Π° ΠΈΠ·Π²Ρ€ΡˆΠΈ Π±Π°Ρ€Π°ΡšΠ΅ Π·Π° Π±Π°Π·Π°Ρ‚Π° Π½Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ. Π’Ρ€Π΅Π±Π° само Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌΠ΅ ΠΊΠ°ΠΊΠΎ Π΄Π° Π³ΠΎ користимС Ρ„ΠΈΠ»Ρ‚Π΅Ρ€ΠΎΡ‚ Π·Π° ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ Π²ΠΎ ΡˆΠ΅ΠΌΠ°Ρ‚Π° Π·Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ.

АјдС Π΄Π° создадСмС Π½ΠΎΠ²Π° Π°ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΡ˜Π° Cube.js. Π‘ΠΈΠ΄Π΅Ρ˜ΡœΠΈ вСќС Π³ΠΎ користимС стСкот AWS, Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΅ Π΄Π° сС користи Lambda Π·Π° Ρ€Π°ΡΠΏΠΎΡ€Π΅Π΄ΡƒΠ²Π°ΡšΠ΅. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ користитС СкспрСсниот шаблон Π·Π° Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°ΡšΠ΅ Π°ΠΊΠΎ ΠΏΠ»Π°Π½ΠΈΡ€Π°Ρ‚Π΅ Π΄Π° Π³ΠΎ хостиратС Π·Π°Π΄Π½ΠΈΠ½Π°Ρ‚Π° Π½Π° 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') 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 ќС создадС Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»Π½ΠΈ Ρ‚Π°Π±Π΅Π»ΠΈ со ΠΏΡ€Π΅Ρ‚Ρ…ΠΎΠ΄Π½ΠΎ собрани ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ ΠΈ автоматски ќС Π³ΠΈ Π°ΠΆΡƒΡ€ΠΈΡ€Π° ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈΡ‚Π΅ ΠΊΠΎΠ³Π° ќС пристигнС. Ова Π½Π΅ само ΡˆΡ‚ΠΎ Π³ΠΈ Π·Π°Π±Ρ€Π·ΡƒΠ²Π° Π±Π°Ρ€Π°ΡšΠ°Ρ‚Π°, Ρ‚ΡƒΠΊΡƒ ΠΈ Π³ΠΈ Π½Π°ΠΌΠ°Π»ΡƒΠ²Π° Ρ‚Ρ€ΠΎΡˆΠΎΡ†ΠΈΡ‚Π΅ Π·Π° ΠΊΠΎΡ€ΠΈΡΡ‚Π΅ΡšΠ΅ Π½Π° 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 backend ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡƒΠ²Π° ОБВАНАВОВО API ΠΈ Π·Π±ΠΈΡ€ Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΈ Π·Π° ΠΏΠΎΠΏΡƒΠ»Π°Ρ€Π½ΠΈ Ρ€Π°ΠΌΠΊΠΈ ΠΎΠ΄ ΠΏΡ€Π΅Π΄Π½ΠΈΠΎΡ‚ Π΄Π΅Π». ЌС ја користимС Π²Π΅Ρ€Π·ΠΈΡ˜Π°Ρ‚Π° React Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΡ‚ Π·Π° Π΄Π° ја ΠΈΠ·Π³Ρ€Π°Π΄ΠΈΠΌΠ΅ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π½Π°Ρ‚Π° Ρ‚Π°Π±Π»Π°. Cube.js ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡƒΠ²Π° само ΠΏΠΎΠ΄Π°Ρ‚ΠΎΡ†ΠΈ, Ρ‚Π°ΠΊΠ° ΡˆΡ‚ΠΎ ќС Π½ΠΈ Ρ‚Ρ€Π΅Π±Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π° Π²ΠΈΠ·ΡƒΠ΅Π»ΠΈΠ·Π°Ρ†ΠΈΡ˜Π° - ΠΌΠΈ сС Π΄ΠΎΠΏΠ°Ρ“Π° ΠΏΡ€Π΅ΡΠ»ΠΈΠΊΡƒΠ²Π°ΡšΠ°, Π½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° користитС Π±ΠΈΠ»ΠΎ кој.

Π‘Π΅Ρ€Π²Π΅Ρ€ΠΎΡ‚ 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 (
    <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

Π”ΠΎΠ΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€