Biasane, produk komersial utawa alternatif open-source, kayata Prometheus + Grafana, digunakake kanggo ngawasi lan nganalisa operasi Nginx. Iki minangka pilihan sing apik kanggo ngawasi utawa analytics wektu nyata, nanging ora trep banget kanggo analisis sejarah. Ing sumber apa wae sing populer, volume data saka log nginx berkembang kanthi cepet, lan kanggo nganalisa data sing akeh, logis nggunakake sing luwih khusus.
Ing artikel iki aku bakal pitutur marang kowe carane sampeyan bisa nggunakake
TL:DR;
Kanggo ngumpulake informasi sing digunakake
Nglumpukake log Nginx
Secara default, log Nginx katon kaya iki:
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" "-"
Bisa diurai, nanging luwih gampang kanggo mbenerake konfigurasi Nginx supaya bisa ngasilake log ing 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 kanggo panyimpenan
Kanggo nyimpen log, kita bakal nggunakake S3. Iki ngidini sampeyan nyimpen lan nganalisa log ing sak panggonan, amarga Athena bisa langsung nggarap data ing S3. Mengko ing artikel aku bakal pitutur marang kowe carane nambah lan proses log bener, nanging pisanan kita kudu ember resik ing S3, kang ora ana liyane bakal disimpen. Sampeyan kudu nimbang luwih dhisik ing wilayah ngendi sampeyan bakal nggawe ember, amarga Athena ora kasedhiya ing kabeh wilayah.
Nggawe sirkuit ing console Athena
Ayo nggawe tabel ing Athena kanggo log. Perlu kanggo nulis lan maca yen sampeyan nggunakake Kinesis Firehose. Bukak konsol Athena lan gawe tabel:
Nggawe tabel 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');
Nggawe Kinesis Firehose Stream
Kinesis Firehose bakal nulis data sing ditampa saka Nginx menyang S3 ing format sing dipilih, dibagi dadi direktori ing format YYYY/MM/DD/HH. Iki bakal migunani nalika maca data. Sampeyan bisa, mesthi, nulis langsung menyang S3 saka fluentd, nanging ing kasus iki sampeyan kudu nulis JSON, lan iki ora efisien amarga ukuran gedhe saka file. Kajaba iku, nalika nggunakake PrestoDB utawa Athena, JSON minangka format data sing paling alon. Dadi mbukak console Kinesis Firehose, klik "Gawe stream pangiriman", pilih "langsung PUT" ing kolom "pangiriman":
Ing tab sabanjure, pilih "Konversi format rekaman" - "Aktif" lan pilih "Apache ORC" minangka format rekaman. Miturut sawetara riset
Kita milih S3 kanggo panyimpenan lan ember sing digawe sadurunge. Aws Glue Crawler, sing bakal dakkandhakake mengko, ora bisa digunakake karo prefiks ing ember S3, mula penting kanggo ninggalake kosong.
Opsi sing isih bisa diganti gumantung saka beban sampeyan; Aku biasane nggunakake sing standar. Elinga yen kompresi S3 ora kasedhiya, nanging ORC nggunakake komprèsi asli minangka standar.
lancar d
Saiki kita wis ngatur nyimpen lan nampa log, kita kudu ngatur ngirim. Kita bakal nggunakake
Pisanan, kita butuh file konfigurasi fluent.conf. Gawe lan tambahake sumber:
port 24224
ikatan 0.0.0.0
Saiki sampeyan bisa miwiti server Fluentd. Yen sampeyan butuh konfigurasi sing luwih maju, pindhah menyang
$ 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
Konfigurasi iki nggunakake path /fluentd/log
kanggo cache log sadurunge ngirim. Sampeyan bisa nindakake tanpa iki, nanging banjur nalika sampeyan miwiti maneh, sampeyan bisa ilang kabeh sing di-cache karo pegawe bali-bejat. Sampeyan uga bisa nggunakake port apa wae; 24224 minangka port Fluentd standar.
Saiki kita wis mlaku Fluentd, kita bisa ngirim log Nginx ing kana. Kita biasane mbukak Nginx ing wadhah Docker, saengga Docker duwe driver logging asli kanggo 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
Yen sampeyan mbukak Nginx kanthi beda, sampeyan bisa nggunakake file log, Fluentd duwe
Ayo nambahake parsing log sing dikonfigurasi ing ndhuwur menyang konfigurasi Fluent:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
Lan ngirim log menyang Kinesis nggunakake
<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
Yen sampeyan wis ngatur kabeh kanthi bener, banjur sawise sawetara wektu (kanthi standar, Kinesis ngrekam nampa data sapisan saben 10 menit) sampeyan kudu ndeleng file log ing S3. Ing menu "monitoring" Kinesis Firehose sampeyan bisa ndeleng jumlah data sing direkam ing S3, uga kesalahan. Aja lali menehi akses nulis menyang ember S3 menyang peran Kinesis. Yen Kinesis ora bisa ngurai soko, bakal nambah kesalahan menyang ember sing padha.
Saiki sampeyan bisa ndeleng data ing Athena. Ayo goleki panjalukan paling anyar sing kesalahane bali:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Pindai kabeh cathetan kanggo saben panyuwunan
Saiki log kita wis diproses lan disimpen ing S3 ing ORC, dikompres lan siap dianalisis. Kinesis Firehose malah ngatur dadi direktori saben jam. Nanging, anggere tabel ora dipisahake, Athena bakal mbukak data kabeh wektu ing saben panyuwunan, kanthi pangecualian sing langka. Iki minangka masalah gedhe amarga rong alasan:
- Volume data saya tambah akeh, alon-alon pitakon;
- Athena ditagih adhedhasar volume data sing dipindai, kanthi minimal 10 MB saben panyuwunan.
Kanggo ndandani iki, kita nggunakake AWS Glue Crawler, sing bakal nyusup data ing S3 lan nulis informasi partisi menyang Metastore Glue. Iki bakal ngidini kita nggunakake partisi minangka panyaring nalika takon Athena, lan mung bakal mindai direktori sing ditemtokake ing pitakonan kasebut.
Nggawe Amazon Glue Crawler
Amazon Glue Crawler mindhai kabeh data ing ember S3 lan nggawe tabel kanthi partisi. Nggawe Glue Crawler saka AWS Glue console lan nambah ember ngendi sampeyan nyimpen data. Sampeyan bisa nggunakake siji crawler kanggo sawetara ember, ing kasus iki bakal nggawe tabel ing basis data sing ditemtokake kanthi jeneng sing cocog karo jeneng ember. Yen sampeyan arep nggunakake data iki kanthi rutin, priksa manawa sampeyan ngatur jadwal peluncuran Crawler supaya cocog karo kabutuhan sampeyan. Kita nggunakake siji Crawler kanggo kabeh tabel, sing mlaku saben jam.
Tabel partisi
Sawise diluncurake pisanan crawler, tabel kanggo saben ember sing dipindai kudu katon ing basis data sing ditemtokake ing setelan kasebut. Bukak konsol Athena lan temokake tabel kanthi log Nginx. Ayo coba maca soko:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Pitakonan iki bakal milih kabeh rekaman sing ditampa antarane jam 6 esuk nganti jam 7 esuk tanggal 8 April 2019. Nanging kepiye luwih efisien tinimbang mung maca saka tabel sing ora dipisahake? Ayo goleki lan pilih cathetan sing padha, nyaring kanthi cap wektu:
3.59 detik lan 244.34 megabyte data ing set data kanthi mung seminggu log. Coba saringan kanthi partisi:
Luwih cepet, nanging sing paling penting - mung 1.23 megabyte data! Iku bakal luwih murah yen ora kanggo minimal 10 megabyte saben request ing reregan. Nanging isih luwih apik, lan ing dataset gedhe prabΓ©dan bakal luwih nyengsemaken.
Nggawe dashboard nggunakake Cube.js
Kanggo ngumpulake dashboard, kita nggunakake kerangka analitis Cube.js. Wis cukup akeh fungsi, nanging kita kasengsem ing loro: kemampuan kanggo otomatis nggunakake saringan partisi lan data pre-agregasi. Iku nggunakake skema data
Ayo nggawe aplikasi Cube.js anyar. Amarga kita wis nggunakake tumpukan AWS, iku logis kanggo nggunakake Lambda kanggo panyebaran. Sampeyan bisa nggunakake cithakan ekspres kanggo generasi yen sampeyan arep dadi tuan rumah backend Cube.js ing Heroku utawa Docker. Dokumentasi nggambarake wong liya
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Variabel lingkungan digunakake kanggo ngatur akses database ing cube.js. Generator bakal nggawe file .env sing bisa nemtokake kunci sampeyan
Saiki kita butuh
Ing direktori schema
, nggawe file Logs.js
. Mangkene conto model data kanggo nginx:
Kode model
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`
}
}
});
Ing kene kita nggunakake variabel
Kita uga nyetel metrik lan paramèter sing arep ditampilake ing dashboard lan nemtokake pra-agregasi. Cube.js bakal nggawe tabel tambahan kanthi data sing wis dikumpulake lan bakal nganyari data kanthi otomatis nalika teka. Iki ora mung nyepetake pitakon, nanging uga nyuda biaya nggunakake Athena.
Ayo ditambahake informasi iki menyang file skema data:
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`
)
}
}
}
Kita nemtokake ing model iki yen perlu kanggo pre-agregat data kanggo kabeh metrik sing digunakake, lan nggunakake partisi miturut sasi.
Saiki kita bisa ngumpulake dashboard!
Cube.js backend nyedhiyakake
Server Cube.js nampa panjalukan ing
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
Ayo nginstal klien Cube.js lan perpustakaan komponen React liwat NPM:
$ npm i --save @cubejs-client/core @cubejs-client/react
Kita ngimpor komponen cubejs
ΠΈ QueryRenderer
kanggo ngundhuh data, lan ngumpulake dashboard:
Kode dashboard
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>
);
}}
/>
)
}
sumber Dashboard kasedhiya ing
Source: www.habr.com