Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

Ихэвчлэн арилжааны бүтээгдэхүүнүүд эсвэл Prometheus + Grafana зэрэг бэлэн нээлттэй эхийн хувилбаруудыг Nginx-ийн ажиллагааг хянах, шинжлэхэд ашигладаг. Энэ нь мониторинг эсвэл бодит цагийн аналитик хийхэд тохиромжтой сонголт боловч түүхэн шинжилгээ хийхэд тийм ч тохиромжтой биш юм. Аливаа алдартай нөөц дээр nginx бүртгэлийн өгөгдлийн хэмжээ хурдацтай нэмэгдэж байгаа бөгөөд их хэмжээний өгөгдөлд дүн шинжилгээ хийхийн тулд илүү нарийн мэргэшсэн зүйлийг ашиглах нь логик юм.

Энэ нийтлэлд би танд хэрхэн ашиглах талаар хэлэх болно Athena логуудыг шинжлэхийн тулд Nginx-ийг жишээ болгон авч, би нээлттэй эхийн cube.js хүрээг ашиглан энэ өгөгдлөөс аналитик хяналтын самбарыг хэрхэн угсрахыг харуулах болно. Энд бүрэн шийдлийн архитектур байна:

Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

TL: DR;
Дууссан хяналтын самбар руу холбоно уу.

Мэдээлэл цуглуулахын тулд бид ашигладаг Чадварлаг, боловсруулахад - AWS Kinesis Data Firehose и AWS цавуу, хадгалах зориулалттай - AWS S3. Энэ багцыг ашигласнаар та зөвхөн nginx бүртгэлүүд төдийгүй бусад үйл явдлууд болон бусад үйлчилгээний бүртгэлийг хадгалах боломжтой. Та стекийнхээ зарим хэсгийг ижил төстэй хэсгүүдээр сольж болно, жишээлбэл, nginx-с шууд 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" "-"

Тэдгээрийг задлан шинжилж болох боловч 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://<YOUR-S3-BUCKET>'
TBLPROPERTIES ('has_encrypted_data'='false');

Kinesis Firehose Stream үүсгэх

Kinesis Firehose нь Nginx-ээс S3 руу хүлээн авсан өгөгдлийг сонгосон форматаар бичиж, YYYY/MM/DD/HH форматын лавлах болгон хуваах болно. Энэ нь өгөгдлийг уншихад хэрэг болно. Мэдээжийн хэрэг та fluentd-ээс S3 руу шууд бичиж болно, гэхдээ энэ тохиолдолд та JSON бичих хэрэгтэй болно, энэ нь файлын хэмжээ том учраас үр ашиггүй юм. Нэмж дурдахад, PrestoDB эсвэл Athena ашиглах үед JSON нь хамгийн удаан өгөгдлийн формат юм. Тиймээс Kinesis Firehose консолыг нээгээд "Хүргэлтийн урсгалыг үүсгэх" дээр товшоод "хүргэх" талбарт "шууд PUT" -ийг сонгоно уу:

Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

Дараагийн табаас "Бичлэгийн формат хөрвүүлэлт" - "Идэвхжүүлсэн" гэж сонгоод бичлэгийн форматаар "Apache ORC"-г сонгоно уу. Зарим судалгаагаар Оуэн О'Мэлли, энэ нь PrestoDB болон Athena-ийн оновчтой формат юм. Дээр үүсгэсэн хүснэгтээ бид схем болгон ашигладаг. Та Kinesis-д ямар ч S3 байршлыг зааж өгч болно гэдгийг анхаарна уу, зөвхөн схемийг хүснэгтээс ашиглана. Гэхдээ хэрэв та өөр S3 байршлыг зааж өгвөл энэ хүснэгтээс эдгээр бүртгэлийг унших боломжгүй болно.

Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

Хадгалалт болон өмнө нь үүсгэсэн хувингаар бид S3-г сонгоно. Би бага зэрэг ярих болно Aws Glue Crawler нь S3 хувин дахь угтвартай ажиллах боломжгүй тул үүнийг хоосон орхих нь чухал юм.

Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

Үлдсэн сонголтуудыг таны ачааллаас хамааран өөрчилж болно; Би ихэвчлэн үндсэн сонголтуудыг ашигладаг. S3 шахалтыг ашиглах боломжгүй боловч ORC нь анхдагчаар үндсэн шахалтыг ашигладаг гэдгийг анхаарна уу.

Чадварлаг

Одоо бид бүртгэлийг хадгалах, хүлээн авах тохиргоог хийсэн тул илгээх тохиргоог хийх хэрэгтэй. Бид ашиглах болно Чадварлаг, учир нь би Ruby-д дуртай, гэхдээ та Logstash-ийг ашиглах эсвэл шууд kinesis руу лог илгээх боломжтой. Fluentd серверийг хэд хэдэн аргаар ажиллуулж болох бөгөөд энэ нь энгийн бөгөөд тохиромжтой тул би докерын талаар танд хэлэх болно.

Эхлээд бидэнд 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>

Athena

Хэрэв та бүх зүйлийг зөв тохируулсан бол хэсэг хугацааны дараа (анхдагчаар Kinesis нь хүлээн авсан өгөгдлийг 10 минут тутамд нэг удаа бүртгэдэг) S3 дээр бүртгэлийн файлуудыг харах болно. Kinesis Firehose-ийн "хяналт" цэснээс та S3-д хэр их өгөгдөл бичигдсэн, мөн алдааг харж болно. Kinesis дүрд S3 хувин руу бичих эрхийг өгөхөө бүү мартаарай. Хэрэв Kinesis ямар нэг зүйлийг задлан шинжилж чадаагүй бол алдааг ижил хувин дээр нэмнэ.

Одоо та Афина дахь өгөгдлийг үзэх боломжтой. Бид алдаа гаргасан хамгийн сүүлийн хүсэлтүүдийг олцгооё:

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

Хүсэлт бүрийн бүх бүртгэлийг сканнердаж байна

Одоо бидний бүртгэлийг ORC-д S3-д боловсруулж, хадгалж, шахаж, дүн шинжилгээ хийхэд бэлэн болсон. Kinesis Firehose тэдгээрийг цаг тутамд лавлах болгон зохион байгуулдаг. Гэсэн хэдий ч хүснэгтийг хуваахгүй бол Athena нь ховор тохиолдлуудыг эс тооцвол хүсэлт болгонд бүх цаг үеийн өгөгдлийг ачаалах болно. Энэ нь хоёр шалтгааны улмаас том асуудал юм:

  • Өгөгдлийн хэмжээ байнга нэмэгдэж, асуулга удаашруулж байна;
  • Athena-ийн төлбөрийг сканнердсан өгөгдлийн хэмжээн дээр үндэслэн тооцдог бөгөөд хүсэлт бүрт хамгийн багадаа 10 MB байх ёстой.

Үүнийг засахын тулд бид AWS Glue Crawler ашигладаг бөгөөд энэ нь S3 дээрх өгөгдлийг мөлхөж, хуваалтын мэдээллийг Glue Metastore руу бичих болно. Энэ нь бидэнд Athena-д асуулга хийх үед хуваалтуудыг шүүлтүүр болгон ашиглах боломжийг олгох бөгөөд энэ нь зөвхөн асуулгад заасан сангуудыг сканнердах болно.

Amazon Glue Crawler-г тохируулж байна

Amazon Glue Crawler нь S3 хувин дахь бүх өгөгдлийг сканнердаж, хуваалт бүхий хүснэгтүүдийг үүсгэдэг. AWS Glue консолоос Glue Crawler үүсгэж, өгөгдөл хадгалах хувин нэмнэ үү. Та нэг мөлхөгчийг хэд хэдэн хувин дээр ашиглаж болох бөгөөд энэ тохиолдолд энэ нь хувингийн нэрэнд тохирсон нэрээр заасан мэдээллийн санд хүснэгтүүдийг үүсгэх болно. Хэрэв та энэ өгөгдлийг тогтмол ашиглахаар төлөвлөж байгаа бол 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 цагаас өглөөний XNUMX цагийн хооронд хүлээн авсан бүх бүртгэлийг сонгоно. Гэхдээ энэ нь хуваагдаагүй хүснэгтээс уншихаас хамаагүй илүү үр дүнтэй вэ? Ижил бичлэгүүдийг цаг хугацааны тэмдгээр шүүж олж сонгоцгооё:

Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

3.59 секунд, 244.34 мегабайт өгөгдөлтэй, ердөө долоо хоногийн бүртгэлтэй. Хуваалтаар шүүж үзье:

Amazon Athena болон Cube.js ашиглан Nginx бүртгэлийн аналитик

Бага зэрэг хурдан, гэхдээ хамгийн чухал нь - ердөө 1.23 мегабайт өгөгдөл! Үнийн хувьд хүсэлт бүрт хамгийн багадаа 10 мегабайт байхгүй бол хамаагүй хямд байх болно. Гэхдээ энэ нь хамаагүй дээр хэвээр байгаа бөгөөд том өгөгдлийн багц дээр ялгаа нь илүү гайхалтай байх болно.

Cube.js ашиглан хяналтын самбар бүтээх

Хяналтын самбарыг угсрахдаа бид Cube.js аналитик хүрээг ашигладаг. Энэ нь маш олон функцтэй боловч бид хоёрыг сонирхож байна: хуваалтын шүүлтүүрийг автоматаар ашиглах чадвар, өгөгдлийг урьдчилан нэгтгэх чадвар. Энэ нь өгөгдлийн схемийг ашигладаг өгөгдлийн схем, Javascript дээр бичигдсэн бөгөөд SQL-г үүсгэж, өгөгдлийн сангийн хайлтыг гүйцэтгэнэ. Бид зөвхөн өгөгдлийн схемд хуваалтын шүүлтүүрийг хэрхэн ашиглахыг зааж өгөх хэрэгтэй.

Шинэ Cube.js програм үүсгэцгээе. Бид AWS стекийг аль хэдийн ашиглаж байгаа тул Lambda-г байршуулахдаа ашиглах нь логик юм. Хэрэв та Cube.js backend-ийг 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') 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 өгдөг REST 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

сэтгэгдэл нэмэх