Tipikament, prodotti kummerċjali jew alternattivi open-source lesti, bħal Prometheus + Grafana, jintużaw biex jimmonitorjaw u janalizzaw l-operat ta 'Nginx. Din hija għażla tajba għall-monitoraġġ jew l-analiżi f'ħin reali, iżda mhux konvenjenti ħafna għall-analiżi storika. Fuq kwalunkwe riżors popolari, il-volum ta 'dejta minn zkuk nginx qed jikber malajr, u biex tanalizza ammont kbir ta' dejta, huwa loġiku li tuża xi ħaġa aktar speċjalizzata.
F'dan l-artikolu ser ngħidlek kif tista 'tuża
TL:DR;
Biex niġbru informazzjoni li nużaw
Ġbir ta 'zkuk Nginx
B'mod awtomatiku, zkuk Nginx jidhru xi ħaġa bħal din:
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" "-"
Jistgħu jiġu analizzati, iżda huwa ħafna aktar faċli li tikkoreġi l-konfigurazzjoni Nginx sabiex tipproduċi zkuk f'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 għall-ħażna
Biex naħżnu zkuk, se nużaw S3. Dan jippermettilek taħżen u tanalizza zkuk f'post wieħed, peress li Athena tista 'taħdem bid-dejta f'S3 direttament. Aktar tard fl-artikolu ser ngħidlek kif iżżid u tipproċessa zkuk b'mod korrett, iżda l-ewwel neħtieġu barmil nadif f'S3, li fih ma jinħażen xejn aktar. Ta' min tikkunsidra minn qabel f'liema reġjun se tkun qed toħloq il-barmil tiegħek, għaliex Athena mhix disponibbli fir-reġjuni kollha.
Ħolqien ta 'ċirkwit fil-console Athena
Ejja noħolqu tabella f'Athena għal zkuk. Huwa meħtieġ kemm għall-kitba kif ukoll għall-qari jekk qed tippjana li tuża Kinesis Firehose. Iftaħ il-console Athena u oħloq tabella:
Ħolqien ta' tabella 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');
Ħolqien Kinesis Firehose Stream
Kinesis Firehose se jikteb id-dejta riċevuta minn Nginx għal S3 fil-format magħżul, u jaqsamha f'direttorji fil-format YYYY/MM/DD/HH. Dan se jkun utli meta taqra d-dejta. Tista', ovvjament, tikteb direttament lil S3 minn fluentd, iżda f'dan il-każ ikollok tikteb JSON, u dan huwa ineffiċjenti minħabba d-daqs kbir tal-fajls. Barra minn hekk, meta tuża PrestoDB jew Athena, JSON huwa l-aktar format tad-dejta bil-mod. Allura tiftaħ il-console Kinesis Firehose, ikklikkja "Oħloq fluss ta 'kunsinna", agħżel "PUT dirett" fil-qasam "kunsinna":
Fit-tab li jmiss, agħżel "Record format conversion" - "Enabled" u agħżel "Apache ORC" bħala l-format tar-reġistrazzjoni. Skond xi riċerka
Aħna nagħżlu S3 għall-ħażna u l-barmil li ħloqna qabel. Aws Glue Crawler, li se nitkellem dwaru ftit aktar tard, ma jistax jaħdem bi prefissi f'barmil S3, għalhekk huwa importanti li tħallih vojt.
L-għażliet li jifdal jistgħu jinbidlu skont it-tagħbija tiegħek normalment nuża dawk default. Innota li l-kompressjoni S3 mhix disponibbli, iżda ORC juża kompressjoni nattiva b'mod awtomatiku.
fluentd
Issa li kkonfigurajna l-ħażna u r-riċeviment ta' zkuk, irridu nikkonfiguraw li tibgħat. Aħna se nużaw
L-ewwel, għandna bżonn il-fajl tal-konfigurazzjoni fluent.conf. Oħloqha u żid is-sors:
port 24224
jorbot 0.0.0.0
Issa tista 'tibda s-server Fluentd. Jekk għandek bżonn konfigurazzjoni aktar avvanzata, mur fuq
$ 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
Din il-konfigurazzjoni tuża l-mogħdija /fluentd/log
għall-cache zkuk qabel ma tibgħat. Tista 'tagħmel mingħajr dan, iżda mbagħad meta terġa' tibda, tista 'titlef kollox fil-cache b'xogħol li jkisser id-dahar. Tista 'wkoll tuża kwalunkwe port 24224 huwa l-port Fluentd default.
Issa li għandna Fluentd qed jaħdem, nistgħu nibagħtu zkuk Nginx hemmhekk. Normalment inħaddmu Nginx f'kontenitur Docker, f'liema każ Docker għandu sewwieq ta 'logging indiġeni għal 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
Jekk tmexxi Nginx b'mod differenti, tista 'tuża log files, Fluentd għandu
Ejja nżidu l-parsing tal-log konfigurat hawn fuq mal-konfigurazzjoni Fluwenti:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
U tibgħat zkuk lil Kinesis bl-użu
<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
Jekk ikkonfigurajt kollox b'mod korrett, imbagħad wara xi żmien (b'mod awtomatiku, Kinesis jirrekordja d-dejta riċevuta darba kull 10 minuti) għandek tara fajls tal-ġurnal f'S3. Fil-menu ta '"monitoraġġ" ta' Kinesis Firehose tista 'tara kemm hija rreġistrata dejta f'S3, kif ukoll żbalji. Tinsiex li tagħti aċċess għall-kitba għall-barmil S3 għar-rwol Kinesis. Jekk Kinesis ma setgħetx parse xi ħaġa, se żżid l-iżbalji fl-istess barmil.
Issa tista 'tara d-dejta f'Athena. Ejja nsibu l-aħħar talbiet li għalihom irritornajna żbalji:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Skannjar tar-rekords kollha għal kull talba
Issa zkuk tagħna ġew ipproċessati u maħżuna f'S3 f'ORC, ikkompressati u lesti għall-analiżi. Kinesis Firehose saħansitra organizzahom f'direttorji għal kull siegħa. Madankollu, sakemm it-tabella ma tkunx maqsuma, Athena se tgħabbi d-dejta ta 'kull żmien fuq kull talba, b'eċċezzjonijiet rari. Din hija problema kbira għal żewġ raġunijiet:
- Il-volum tad-dejta qed jikber kontinwament, u jnaqqas il-mistoqsijiet;
- Athena tiġi ffatturata abbażi tal-volum ta' dejta skanjata, b'minimu ta' 10 MB għal kull talba.
Biex nirranġaw dan, nużaw AWS Glue Crawler, li se jitkaxkru d-dejta f'S3 u jikteb l-informazzjoni tal-partizzjoni fil-Glue Metastore. Dan se jippermettilna nużaw diviżorji bħala filtru meta nistaqsu lil Athena, u se tiskennja biss id-direttorji speċifikati fil-mistoqsija.
Twaqqif ta' Amazon Glue Crawler
Amazon Glue Crawler tiskennja d-dejta kollha fil-barmil S3 u toħloq tabelli b'diviżorji. Oħloq Glue Crawler mill-console AWS Glue u żid barmil fejn taħżen id-dejta. Tista 'tuża crawler wieħed għal diversi bramel, f'liema każ se toħloq tabelli fid-database speċifikata b'ismijiet li jaqblu mal-ismijiet tal-bramel. Jekk qed tippjana li tuża din id-dejta regolarment, kun żgur li tikkonfigura l-iskeda tat-tnedija ta' Crawler biex taqbel mal-bżonnijiet tiegħek. Aħna nużaw Crawler wieħed għat-tabelli kollha, li jimxi kull siegħa.
Imwejjed maqsuma
Wara l-ewwel tnedija tat-tkaxkir, it-tabelli għal kull barmil skennjat għandhom jidhru fid-database speċifikata fis-settings. Iftaħ il-console Athena u sib it-tabella bi zkuk Nginx. Ejja nippruvaw naqraw xi ħaġa:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Din il-mistoqsija se tagħżel ir-rekords kollha riċevuti bejn is-6 a.m. u s-7 a.m. fit-8 ta’ April, 2019. Imma kemm huwa aktar effiċjenti dan milli sempliċiment qari minn tabella mhux diviżorja? Ejja nsiru nafu u agħżel l-istess rekords, billi niffiltrawhom skont it-timbru tal-ħin:
3.59 sekondi u 244.34 megabytes ta' data fuq dataset b'ġimgħa biss ta' zkuk. Ejja nippruvaw filtru skond il-partizzjoni:
Ftit aktar mgħaġġla, iżda l-aktar importanti - 1.23 megabytes biss ta 'dejta! Ikun ferm irħas jekk mhux għall-minimu ta '10 megabytes għal kull talba fl-ipprezzar. Iżda xorta huwa ferm aħjar, u fuq settijiet ta 'dejta kbar id-differenza se tkun ħafna aktar impressjonanti.
Bini ta' dashboard bl-użu ta' Cube.js
Biex tgħaqqad id-dashboard, nużaw il-qafas analitiku Cube.js. Għandu ħafna funzjonijiet, iżda aħna interessati f'żewġ: il-kapaċità li nużaw awtomatikament filtri tal-partizzjoni u pre-aggregazzjoni tad-dejta. Hija tuża data schema
Ejja noħolqu applikazzjoni Cube.js ġdida. Peress li diġà qed nużaw il-munzell AWS, huwa loġiku li nużaw Lambda għall-iskjerament. Tista 'tuża l-mudell espress għall-ġenerazzjoni jekk qed tippjana li tospita l-backend ta' Cube.js f'Heroku jew Docker. Id-dokumentazzjoni tiddeskrivi oħrajn
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Il-varjabbli tal-ambjent jintużaw biex jiġi kkonfigurat l-aċċess tad-database f'cube.js. Il-ġeneratur se joħloq fajl .env li fih tista 'tispeċifika ċ-ċwievet tiegħek għal
Issa għandna bżonn
Fid-direttorju schema
, oħloq fajl Logs.js
. Hawn hu eżempju ta’ mudell ta’ data għal nginx:
Kodiċi tal-mudell
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`
}
}
});
Hawnhekk qed nużaw il-varjabbli
Aħna nissettjaw ukoll il-metriċi u l-parametri li rridu nuru fuq id-dashboard u nispeċifikaw pre-aggregazzjonijiet. Cube.js se joħloq tabelli addizzjonali b'dejta aggregata minn qabel u awtomatikament jaġġorna d-dejta hekk kif tasal. Dan mhux biss iħaffef il-mistoqsijiet, iżda jnaqqas ukoll l-ispiża tal-użu ta 'Athena.
Ejja nżidu din l-informazzjoni mal-fajl tal-iskema tad-dejta:
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`
)
}
}
}
Aħna nispeċifikaw f'dan il-mudell li huwa meħtieġ li d-dejta tiġi aggregata minn qabel għall-metriċi kollha użati, u nużaw il-qsim skond ix-xahar.
Issa nistgħu niġbru d-dashboard!
Backend Cube.js jipprovdi
Is-server Cube.js jaċċetta t-talba fil
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
Ejja ninstallaw il-klijent Cube.js u l-librerija tal-komponenti React permezz tal-NPM:
$ npm i --save @cubejs-client/core @cubejs-client/react
Aħna importazzjoni komponenti cubejs
и QueryRenderer
biex tniżżel id-dejta, u tiġbor id-dashboard:
Kodiċi tad-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>
);
}}
/>
)
}
Is-sorsi tad-dashboard huma disponibbli fuq
Sors: www.habr.com