Tipikman, pwodwi komèsyal oswa altènativ louvri-sous pare, tankou Prometheus + Grafana, yo itilize pou kontwole ak analize operasyon an nan Nginx. Sa a se yon bon opsyon pou siveyans oswa analiz an tan reyèl, men li pa trè pratik pou analiz istorik. Sou nenpòt resous popilè, volim done ki soti nan mòso bwa nginx ap grandi rapidman, epi analize yon gwo kantite done, li lojik pou itilize yon bagay ki pi espesyalize.
Nan atik sa a mwen pral di w ki jan ou ka itilize
TL:DR;
Pou kolekte enfòmasyon nou itilize
Kolekte mòso bwa Nginx
Pa default, mòso bwa Nginx sanble yon bagay tankou sa a:
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" "-"
Yo ka analize, men li pi fasil pou korije konfigirasyon Nginx pou li pwodui mòso bwa nan 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 pou depo
Pou estoke mòso bwa, nou pral sèvi ak S3. Sa a pèmèt ou estoke ak analize mòso bwa nan yon sèl kote, depi Athena ka travay ak done nan S3 dirèkteman. Pita nan atik la mwen pral di w ki jan yo kòrèkteman ajoute ak trete mòso bwa, men premye nou bezwen yon bokit pwòp nan S3, nan ki pa gen anyen lòt yo pral estoke. Li vo konsidere davans nan ki rejyon ou pral kreye bokit ou a, paske Athena pa disponib nan tout rejyon yo.
Kreye yon kous nan konsole Athena
Ann kreye yon tab nan Athena pou mòso bwa. Li nesesè pou ekri ak lekti si w gen plan pou itilize Kinesis Firehose. Louvri konsole Athena a epi kreye yon tab:
Kreyasyon tab 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');
Kreye Kinesis Firehose Stream
Kinesis Firehose pral ekri done yo resevwa nan men Nginx nan S3 nan fòma chwazi a, divize li an repèrtwar nan fòma YYYY/MM/DD/HH. Sa a pral itil lè w ap li done yo. Ou ka, nan kou, ekri dirèkteman nan S3 soti nan fluentd, men nan ka sa a ou pral oblije ekri JSON, ak sa a se rezèvwa akòz gwosè a gwo nan dosye yo. Anplis de sa, lè w ap itilize PrestoDB oswa Athena, JSON se fòma done ki pi dousman. Se konsa, louvri konsole Kinesis Firehose la, klike sou "Kreye kouran livrezon", chwazi "mete dirèk" nan jaden an "livrezon":
Nan pwochen onglet, chwazi "Dosye fòma konvèsyon" - "Pèmèt" epi chwazi "Apache ORC" kòm fòma anrejistreman an. Dapre kèk rechèch
Nou chwazi S3 pou depo ak bokit la ke nou te kreye pi bonè. Aws Glue Crawler, ke mwen pral pale sou yon ti kras pita, pa ka travay ak prefiks nan yon bokit S3, kidonk li enpòtan pou kite li vid.
Opsyon ki rete yo ka chanje depann sou chaj ou a; anjeneral mwen itilize sa yo default. Remake byen ke konpresyon S3 pa disponib, men ORC itilize konpresyon natif natal pa default.
fluentd
Kounye a ke nou te configuré estoke ak resevwa mòso bwa, nou bezwen konfigirasyon voye. Nou pral itilize
Premyèman, nou bezwen fichye konfigirasyon fluent.conf la. Kreye li epi ajoute sous:
pò 24224
mare 0.0.0.0
Koulye a, ou ka kòmanse sèvè Fluentd la. Si ou bezwen yon konfigirasyon ki pi avanse, ale nan
$ 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
Konfigirasyon sa a sèvi ak chemen an /fluentd/log
nan kachèt mòso bwa anvan yo voye. Ou ka fè san sa a, men Lè sa a, lè ou rekòmanse, ou ka pèdi tout bagay kachèt ak travay tounen-kraze. Ou ka itilize nenpòt pò tou; 24224 se pò Fluentd default la.
Kounye a ke nou gen Fluentd kouri, nou ka voye mòso bwa Nginx la. Nou anjeneral kouri Nginx nan yon veso Docker, nan ka sa a Docker gen yon chofè natif natal pou 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
Si ou kouri Nginx yon fason diferan, ou ka itilize dosye log, Fluentd genyen
Ann ajoute parsaj boutèy demi lit ki configuré pi wo a nan konfigirasyon Fluent la:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
Epi voye mòso bwa nan Kinesis lè l sèvi avèk
<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
Si ou te configuré tout bagay kòrèkteman, Lè sa a, apre yon ti tan (pa default, Kinesis dosye resevwa done yon fwa chak 10 minit) ou ta dwe wè dosye log nan S3. Nan meni "siveyans" Kinesis Firehose ou ka wè konbyen done ki anrejistre nan S3, osi byen ke erè. Pa bliye bay aksè ekri nan bokit S3 a nan wòl Kinesis la. Si Kinesis pa t 'kapab analize yon bagay, li pral ajoute erè yo nan menm bokit la.
Koulye a, ou ka wè done yo nan Athena. Ann jwenn dènye demann nou te retounen erè yo:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Analize tout dosye pou chak demann
Koulye a, mòso bwa nou yo te trete ak estoke nan S3 nan ORC, konprese ak pare pou analiz. Kinesis Firehose menm òganize yo nan anyè pou chak èdtan. Sepandan, osi lontan ke tab la pa divize, Athena pral chaje done tout tan sou chak demann, ak eksepsyon ki ra. Sa a se yon gwo pwoblèm pou de rezon:
- Volim done yo toujou ap grandi, ralanti demann yo;
- Athena faktire dapre volim done yo analize, ak yon minimòm de 10 MB pou chak demann.
Pou repare sa a, nou itilize AWS Glue Crawler, ki pral rale done yo nan S3 epi ekri enfòmasyon patisyon yo nan Glue Metastore la. Sa a pral pèmèt nou sèvi ak patisyon kòm yon filtè lè w ap chèche Athena, epi li pral sèlman eskane repèrtwar ki espesifye nan rechèch la.
Mete kanpe Amazon Glue Crawler
Amazon Glue Crawler analize tout done ki nan bokit S3 la epi li kreye tab ak patisyon yo. Kreye yon Glue Crawler nan konsole AWS Glue a epi ajoute yon bokit kote ou estoke done yo. Ou ka itilize yon sèl krole pou plizyè bokit, nan ka sa a li pral kreye tab nan baz done espesifye ak non ki matche ak non bokit yo. Si w gen plan pou itilize done sa yo regilyèman, asire w ke w configured orè lansman Crawler a pou adapte w ak bezwen w yo. Nou itilize yon sèl Crawler pou tout tab, ki kouri chak èdtan.
Tablo divize
Apre premye lansman krole a, tab pou chak bokit tcheke ta dwe parèt nan baz done ki espesifye nan paramèt yo. Louvri konsole Athena a epi jwenn tab la ak mòso bwa Nginx. Ann eseye li yon bagay:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Rekèt sa a pral chwazi tout dosye yo resevwa ant 6 a.m. ak 7 a.m. nan dat 8 avril 2019. Men, konbyen pi efikas sa a pase jis lekti nan yon tab ki pa patisyon? Ann chèche konnen epi chwazi menm dosye yo, filtre yo pa timestamp:
3.59 segonn ak 244.34 megabyte done sou yon seri done ak sèlman yon semèn nan mòso bwa. Ann eseye yon filtè pa patisyon:
Yon ti kras pi vit, men sa ki pi enpòtan - sèlman 1.23 megabyte nan done! Li ta pi bon mache si se pa pou minimòm 10 megabytes pou chak demann nan pri a. Men, li toujou pi bon, ak sou gwo datasets diferans lan pral pi enpresyonan.
Bati yon tablodbò lè l sèvi avèk Cube.js
Pou rasanble tablodbò a, nou itilize fondasyon analitik Cube.js. Li gen yon anpil nan fonksyon, men nou enterese nan de: kapasite nan otomatikman itilize filtè patisyon ak done pre-agregasyon. Li itilize schéma done
Ann kreye yon nouvo aplikasyon Cube.js. Piske nou deja itilize pile AWS a, li lojik pou nou itilize Lambda pou deplwaman. Ou ka itilize modèl eksprime pou jenerasyon si w gen plan pou òganize backend Cube.js nan Heroku oswa Docker. Dokiman an dekri lòt moun
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Varyab anviwònman yo itilize pou konfigirasyon aksè baz done nan cube.js. Dèlko a pral kreye yon fichye .env kote ou ka presize kle ou pou
Kounye a nou bezwen
Nan anyè schema
, kreye yon dosye Logs.js
. Men yon egzanp modèl done pou nginx:
Kòd modèl
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`
}
}
});
Isit la nou ap itilize varyab la
Nou menm tou nou mete mezi ak paramèt ke nou vle montre sou tablodbò a epi presize pre-agrégasyon. Cube.js pral kreye tab adisyonèl ak done pre-agrége epi yo pral otomatikman mete ajou done yo jan li rive. Sa a pa sèlman akselere demann, men tou, diminye pri pou itilize Athena.
Ann ajoute enfòmasyon sa yo nan dosye a chema done:
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`
)
}
}
}
Nou presize nan modèl sa a ke li nesesè pre-agrégation done pou tout mezi yo itilize, epi itilize patisyon pa mwa.
Koulye a, nou ka rasanble tablodbò a!
Backend Cube.js bay
Sèvè Cube.js la aksepte demann lan nan
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
Ann enstale kliyan Cube.js la ak bibliyotèk eleman React atravè NPM:
$ npm i --save @cubejs-client/core @cubejs-client/react
Nou enpòte konpozan cubejs
и QueryRenderer
pou telechaje done yo, epi kolekte tablodbò a:
Kòd tablodbò
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>
);
}}
/>
)
}
Sous tablodbò yo disponib nan
Sous: www.habr.com