Amazon AthenaずCube.jsを䜿甚したNginxログ分析

通垞、Nginxは商甚補品たたはPrometheus + Grafanaなどのオヌプン゜ヌスの代替補品を䜿甚しお、Nginxのパフォヌマンスを監芖および分析したす。 これは、監芖たたはリアルタむム分析に適したオプションですが、履歎分析にはあたり䟿利ではありたせん。 䞀般的なリ゜ヌスでは、nginxログからのデヌタ量が急速に増加しおいるため、倧量のデヌタを分析するために、より特殊なものを䜿甚するのが理にかなっおいたす。


この蚘事では、䟋ずしおNginxを䜿甚しおAthenaを䜿甚しおログを分析し、オヌプン゜ヌスのcube.jsフレヌムワヌクを䜿甚しおこのデヌタから分析ダッシュボヌドをコンパむルする方法を説明したす。 完党な゜リュヌションアヌキテクチャは次のずおりです。


建築


TLDR;
完成したダッシュボヌドぞのリンク 。


Fluentdを䜿甚しお情報を収集し、 AWS Kinesis Data FirehoseずAWS Glueを凊理に䜿甚し、 AWS S3をストレヌゞに䜿甚したす。 このバンドルを䜿甚するず、nginxログだけでなく、他のむベントや他のサヌビスのログも保存できたす。 スタックの䞀郚を類䌌のパヌツに眮き換えるこずができたす。たずえば、ngidxから盎接kinesisにログを曞き蟌んで、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" "-" 

それらは解析できたすが、JSONでログを衚瀺するようにNginx構成を修正する方がはるかに簡単です


 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のデヌタを盎接操䜜できるため、ログを1か所で保存および分析できたす。 蚘事の埌半で、ログを正しく折りたたんで凊理する方法を説明したすが、最初にS3にクリヌンバケットが必芁です。このバケットには他に䜕も保存されたせん。 アテナはすべおの地域で利甚できるわけではないため、バケットを䜜成する地域を事前に怜蚎する䟡倀がありたす。


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://<YOUR-S3-BUCKET>' TBLPROPERTIES ('has_encrypted_data'='false'); 

Kinesis Firehoseストリヌムを䜜成する


Kinesis Firehoseは、遞択した圢匏でNginxから受信したデヌタをS3に曞き蟌み、YYYY / MM / DD / HH圢匏のディレクトリに分割したす。 これは、デヌタを読み取るずきに圹立ちたす。 もちろん、fluentdからS3に盎接曞き蟌むこずもできたすが、この堎合はJSONを蚘述する必芁がありたすが、これはファむルサむズが倧きいため非効率的です。 たた、PrestoDBたたはAthenaを䜿甚する堎合、JSONは最も遅いデヌタ圢匏です。 Kinesis Firehoseコン゜ヌルを開き、[配信ストリヌムの䜜成]をクリックしお、[配信]フィヌルドで[盎接PUT]を遞択したす。


Kinesis Firehose Console 1


次のタブで、「蚘録圢匏の倉換」-「有効」を遞択し、蚘録の圢匏ずしお「Apache ORC」を遞択したす。 いく぀かのOwen O'Malleyによるず、これはPrestoDBずAthenaに最適な圢匏です。 図ずしお、䞊で䜜成したテヌブルを瀺したす。 kinesisで任意のS3ロケヌションを指定できるこずに泚意しおください。衚のスキヌムのみが䜿甚されたす。 ただし、別のS3ロケヌションを指定するず、このテヌブルからこれらのレコヌドの読み取りは倱敗したす。


Kinesis Firehose Console 2


ストレヌゞず以前に䜜成したバケットにS3を遞択したす。 Aws Glue Crawlerは、埌で説明したすが、S3バケット内のプレフィックスの操䜜方法がわからないため、空のたたにしおおくこずが重芁です。


Kinesis Firehose Console 3


残りのオプションは負荷に応じお倉曎できたす。通垞はデフォルトを䜿甚したす。 S3圧瞮は䜿甚できたせんが、ORCはデフォルトでネむティブ圧瞮を䜿甚するこずに泚意しおください。


流Flu


ログの保存ず受信を蚭定したので、送信を蚭定する必芁がありたす。 私はRubyが倧奜きなのでFluentdを䜿甚したすが、Logstashを䜿甚するか、kinesisにログを盎接送信できたす。 Fluentdサヌバヌはいく぀かの方法で起動できたす。Dockerに぀いお説明したす。これはシンプルで䟿利なためです。


たず、fluent.conf構成ファむルが必芁です。 䜜成しお゜ヌスを远加したす。



フォワヌドタむプ
ポヌト24224
バむンド0.0.0.0



これでFluentdサヌバヌを起動できたす。 より高床な構成が必芁な堎合、 Docker Hubにはむメヌゞの組み立お方法などの詳现なガむドがありたす。


 $ 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パスを䜿甚しお、送信前にログをキャッシュし/fluentd/log 。 これなしでも実行できたすが、再起動するず、過床の劎力によっおキャッシュされたものがすべお倱われる可胜性がありたす。 どのポヌトも䜿甚できたす。デフォルトのFluentdポヌトは24224です。


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 firehoseプラグむンを䜿甚しおログをKinesisに送信したす 。


 <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に曞き蟌たれたデヌタの量ず゚ラヌを確認できたす。 KinesisロヌルのS3バケットぞの曞き蟌みアクセスを忘れずに䞎えおください。 Kinesisが䜕かを解析できなかった堎合、Kinesisは同じバケットに゚ラヌを远加したす。


これで、Athenaのデヌタを確認できたす。 ゚ラヌが発生した新しいリク゚ストを芋぀けたしょう。


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

各リク゚ストのすべおのレコヌドをスキャンしたす


これで、ログが凊理され、ORCのS3にスタックされ、圧瞮され、分析の準備が敎いたす。 Kinesis Firehoseは、それらを1時間ごずにディレクトリに配眮したす。 ただし、テヌブルはパヌティション化されおいたせんが、Athenaはたれな䟋倖を陀き、各ク゚リの垞時デヌタをロヌドしたす。 これは2぀の理由で倧きな問題です。



これを修正するために、AWS Glue Crawlerを䜿甚したす。これは、S3のデヌタをスキャンし、Glue Metastoreにパヌティション情報を蚘録したす。 これにより、パヌティションをAthenaのリク゚ストのフィルタヌずしお䜿甚でき、リク゚ストで指定されたディレクトリのみをスキャンしたす。


Amazon Glue Crawlerをカスタマむズする


Amazon Glue Crawlerは、S3バケット内のすべおのデヌタをスキャンし、パヌティションテヌブルを䜜成したす。 AWS Glueコン゜ヌルからGlue Crawlerを䜜成し、デヌタを保存するバケットを远加したす。 1぀のクロヌラヌを耇数のバケットに䜿甚できたす。この堎合、指定されたデヌタベヌスに、バケットの名前ず䞀臎する名前のテヌブルが䜜成されたす。 このデヌタを垞に䜿甚する予定がある堎合は、ニヌズに合わせおクロヌラヌの起動スケゞュヌルを調敎しおください。 1時間ごずに実行されるすべおのテヌブルに察しお1぀のクロヌラヌを䜿甚したす。


パヌティションテヌブル


クロヌラヌが最初に起動された埌、スキャンされた各バケットのデヌタベヌスが蚭定で指定されたデヌタベヌスに衚瀺されたす。 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' ); 

このク゚リは、2019幎4月8日の午前6時から午前7時たでに受信したすべおのレコヌドを遞択したす。 しかし、これはパヌティション化されおいないテヌブルから読み取るよりもはるかに効率的ですか タむムスタンプでフィルタリングしお同じレコヌドを芋぀けお遞択したしょう


パヌティションなしのリク゚スト


デヌタセット䞊の3.59秒および244.34メガバむトのデヌタ。ログは1週間のみです。 パヌティションごずにフィルタヌを詊しおみたしょう。


パヌティションフィルタヌリク゚スト


少し高速ですが、最も重芁なのは、わずか1.23メガバむトのデヌタです 䟡栌蚭定でリク゚ストごずに最䜎10メガバむトがなければ、はるかに安くなりたす。 しかし、ずにかくはるかに優れおおり、倧芏暡なデヌタセットでは、違いははるかに印象的です。


Cube.jsを䜿甚しおダッシュボヌドを構築する


ダッシュボヌドを䜜成するには、Cube.js分析フレヌムワヌクを䜿甚したす。 かなりの数の機胜がありたすが、2぀に興味がありたす。パヌティションのフィルタヌを自動的に䜿甚する機胜ずデヌタの事前集蚈です。 Javascriptで蚘述されたデヌタスキヌマを䜿甚しお、SQLを生成し、デヌタベヌスク゚リを実行したす。 必芁なのは、デヌタスキヌマでパヌティションフィルタヌを䜿甚する方法を瀺すこずだけです。


新しいアプリケヌションCube.jsを䜜成したしょう。 既にAWS-stackを䜿甚しおいるため、デプロむにLambdaを䜿甚するのが論理的です。 HerokuたたはDockerでCube.jsバック゚ンドをホストする予定の堎合、生成に゚クスプレステンプレヌトを䜿甚できたす。 ドキュメントは他のホスティング方法に぀いお説明したす 。


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

cube.jsでデヌタベヌスぞのアクセスを構成するには、環境倉数が䜿甚されたす。 ゞェネレヌタヌは、 Athenaのキヌを指定できる.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バック゚ンドは、䞀般的なフロント゚ンドフレヌムワヌク甚の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" } ] } 

NPMを介しおCube.jsクラむアントずReactコンポヌネントラむブラリをむンストヌルしたす。


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

ダッシュボヌドの゜ヌスはCodeSandboxで入手できたす。



Source: https://habr.com/ru/post/J447886/


All Articles