Yn nodweddiadol, defnyddir cynhyrchion masnachol neu ddewisiadau amgen parod parod, megis Prometheus + Grafana, i fonitro a dadansoddi gweithrediad Nginx. Mae hwn yn opsiwn da ar gyfer monitro neu ddadansoddeg amser real, ond nid yw'n gyfleus iawn ar gyfer dadansoddiad hanesyddol. Ar unrhyw adnodd poblogaidd, mae cyfaint y data o logiau nginx yn tyfu'n gyflym, ac i ddadansoddi llawer iawn o ddata, mae'n rhesymegol defnyddio rhywbeth mwy arbenigol.
Yn yr erthygl hon byddaf yn dweud wrthych sut y gallwch ei ddefnyddio
TL:DR;
I gasglu gwybodaeth a ddefnyddiwn
Casglu logiau Nginx
Yn ddiofyn, mae logiau Nginx yn edrych rhywbeth fel hyn:
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" "-"
Gellir eu dosrannu, ond mae'n llawer haws cywiro cyfluniad Nginx fel ei fod yn cynhyrchu logiau yn 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 ar gyfer storio
I storio logiau, byddwn yn defnyddio S3. Mae hyn yn caniatΓ‘u ichi storio a dadansoddi logiau mewn un lle, oherwydd gall Athena weithio gyda data yn S3 yn uniongyrchol. Yn ddiweddarach yn yr erthygl byddaf yn dweud wrthych sut i ychwanegu a phrosesu logiau yn gywir, ond yn gyntaf mae angen bwced glΓ’n yn S3, lle na fydd unrhyw beth arall yn cael ei storio. Mae'n werth ystyried ymlaen llaw ym mha ranbarth y byddwch chi'n creu eich bwced, oherwydd nid yw Athena ar gael ym mhob rhanbarth.
Creu cylched yn y consol Athena
Gadewch i ni greu tabl yn Athena ar gyfer boncyffion. Mae ei angen ar gyfer ysgrifennu a darllen os ydych chi'n bwriadu defnyddio Kinesis Firehose. Agorwch y consol Athena a chreu bwrdd:
Creu tabl 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');
Creu Kinesis Firehose Stream
Bydd Kinesis Firehose yn ysgrifennu'r data a dderbyniwyd gan Nginx i S3 yn y fformat a ddewiswyd, gan ei rannu'n gyfeiriaduron yn y fformat BBBB / MM / DD / HH. Bydd hyn yn ddefnyddiol wrth ddarllen data. Gallwch, wrth gwrs, ysgrifennu'n uniongyrchol i S3 o fluentd, ond yn yr achos hwn bydd yn rhaid i chi ysgrifennu JSON, ac mae hyn yn aneffeithlon oherwydd maint mawr y ffeiliau. Yn ogystal, wrth ddefnyddio PrestoDB neu Athena, JSON yw'r fformat data arafaf. Felly agorwch y consol Kinesis Firehose, cliciwch βCreu ffrwd ddosbarthuβ, dewiswch βPUT uniongyrcholβ yn y maes βcyflenwiβ:
Yn y tab nesaf, dewiswch "Trosi fformat Cofnod" - "Galluogi" a dewiswch "Apache ORC" fel y fformat recordio. Yn Γ΄l peth ymchwil
Rydym yn dewis S3 ar gyfer storio a'r bwced a grΓ«wyd gennym yn gynharach. Ni all Aws Glue Crawler, y byddaf yn siarad amdano ychydig yn ddiweddarach, weithio gyda rhagddodiaid mewn bwced S3, felly mae'n bwysig ei adael yn wag.
Gellir newid yr opsiynau sy'n weddill yn dibynnu ar eich llwyth; Fel arfer rwy'n defnyddio'r rhai diofyn. Sylwch nad yw cywasgu S3 ar gael, ond mae ORC yn defnyddio cywasgu brodorol yn ddiofyn.
rhugl
Nawr ein bod wedi ffurfweddu storio a derbyn logiau, mae angen i ni ffurfweddu anfon. Byddwn yn defnyddio
Yn gyntaf, mae angen y ffeil ffurfweddu fluent.conf. Creu ac ychwanegu ffynhonnell:
porthladd 24224
rhwym 0.0.0.0
Nawr gallwch chi gychwyn y gweinydd Fluentd. Os oes angen cyfluniad mwy datblygedig arnoch, ewch i
$ 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
Mae'r cyfluniad hwn yn defnyddio'r llwybr /fluentd/log
i storio logiau cyn eu hanfon. Gallwch chi wneud heb hyn, ond yna pan fyddwch chi'n ailgychwyn, gallwch chi golli popeth sydd wedi'i storio Γ’ llafur sy'n torri'n Γ΄l. Gallwch hefyd ddefnyddio unrhyw borthladd; 24224 yw'r porthladd Fluentd rhagosodedig.
Nawr bod gennym ni Fluentd yn rhedeg, gallwn anfon logiau Nginx yno. Rydym fel arfer yn rhedeg Nginx mewn cynhwysydd Docker, ac os felly mae gan Docker yrrwr logio brodorol ar gyfer 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
Os ydych chi'n rhedeg Nginx yn wahanol, gallwch chi ddefnyddio ffeiliau log, mae gan Fluentd
Gadewch i ni ychwanegu'r dosrannu log sydd wedi'i ffurfweddu uchod i'r cyfluniad Rhugl:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
Ac anfon logiau i Kinesis gan ddefnyddio
<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
Os ydych chi wedi ffurfweddu popeth yn gywir, yna ar Γ΄l ychydig (yn ddiofyn, mae Kinesis yn cofnodi data a dderbyniwyd unwaith bob 10 munud) dylech weld ffeiliau log yn S3. Yn newislen βmonitroβ Kinesis Firehose gallwch weld faint o ddata sy'n cael ei gofnodi yn S3, yn ogystal Γ’ gwallau. Peidiwch ag anghofio rhoi mynediad ysgrifenedig i fwced S3 i rΓ΄l Kinesis. Os na allai Kinesis ddosrannu rhywbeth, bydd yn ychwanegu'r gwallau at yr un bwced.
Nawr gallwch chi weld y data yn Athena. Dewch i ni ddod o hyd i'r ceisiadau diweddaraf y gwnaethom ddychwelyd gwallau ar eu cyfer:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Sganio pob cofnod ar gyfer pob cais
Nawr mae ein logiau wedi'u prosesu a'u storio yn S3 yn ORC, wedi'u cywasgu ac yn barod i'w dadansoddi. Fe wnaeth Kinesis Firehose hyd yn oed eu trefnu'n gyfeiriaduron am bob awr. Fodd bynnag, cyn belled nad yw'r tabl wedi'i rannu, bydd Athena yn llwytho data amser llawn ar bob cais, gydag eithriadau prin. Mae hon yn broblem fawr am ddau reswm:
- Mae maint y data yn cynyddu'n gyson, gan arafu ymholiadau;
- Mae Athena yn cael ei bilio ar sail swm y data a sganiwyd, gydag o leiaf 10 MB fesul cais.
I drwsio hyn, rydym yn defnyddio AWS Glue Crawler, a fydd yn cropian y data yn S3 ac yn ysgrifennu'r wybodaeth rhaniad i'r Glue Metastore. Bydd hyn yn caniatΓ‘u i ni ddefnyddio rhaniadau fel hidlydd wrth ymholi Athena, a bydd ond yn sganio'r cyfeiriaduron a nodir yn yr ymholiad.
Sefydlu Amazon Glue Crawler
Mae Amazon Glue Crawler yn sganio'r holl ddata yn y bwced S3 ac yn creu tablau gyda rhaniadau. Creu Crawler Glud o'r consol Glud AWS ac ychwanegu bwced lle rydych chi'n storio'r data. Gallwch ddefnyddio un ymlusgo ar gyfer sawl bwced, ac os felly bydd yn creu tablau yn y gronfa ddata benodol gydag enwau sy'n cyfateb i enwau'r bwcedi. Os ydych chi'n bwriadu defnyddio'r data hwn yn rheolaidd, gwnewch yn siΕ΅r eich bod chi'n ffurfweddu amserlen lansio Crawler i weddu i'ch anghenion. Rydyn ni'n defnyddio un Crawler ar gyfer pob bwrdd, sy'n rhedeg bob awr.
Byrddau rhanedig
Ar Γ΄l lansiad cyntaf y crawler, dylai tablau ar gyfer pob bwced wedi'i sganio ymddangos yn y gronfa ddata a nodir yn y gosodiadau. Agorwch y consol Athena a dewch o hyd i'r bwrdd gyda logiau Nginx. Gadewch i ni geisio darllen rhywbeth:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Bydd yr ymholiad hwn yn dewis yr holl gofnodion a dderbyniwyd rhwng 6 a.m. a 7 am ar Ebrill 8, 2019. Ond faint yn fwy effeithlon yw hyn na darllen o dabl heb raniad yn unig? Dewch i ni ddarganfod a dewis yr un cofnodion, gan eu hidlo yn Γ΄l y stamp amser:
3.59 eiliad a 244.34 megabeit o ddata ar set ddata gyda dim ond wythnos o logiau. Gadewch i ni roi cynnig ar hidlydd yn Γ΄l rhaniad:
Ychydig yn gyflymach, ond yn bwysicaf oll - dim ond 1.23 megabeit o ddata! Byddai'n llawer rhatach os nad am yr isafswm o 10 megabeit fesul cais yn y prisiau. Ond mae'n llawer gwell o hyd, ac ar setiau data mawr bydd y gwahaniaeth yn llawer mwy trawiadol.
Adeiladu dangosfwrdd gan ddefnyddio Cube.js
I gydosod y dangosfwrdd, rydym yn defnyddio fframwaith dadansoddol Cube.js. Mae ganddo lawer iawn o swyddogaethau, ond mae gennym ddiddordeb mewn dau: y gallu i ddefnyddio hidlwyr rhaniad yn awtomatig a rhag-gasglu data. Mae'n defnyddio sgema data
Gadewch i ni greu cymhwysiad Cube.js newydd. Gan ein bod eisoes yn defnyddio pentwr AWS, mae'n rhesymegol defnyddio Lambda i'w ddefnyddio. Gallwch ddefnyddio'r templed cyflym ar gyfer cynhyrchu os ydych yn bwriadu cynnal yr backend Cube.js yn Heroku neu Docker. Mae'r ddogfennaeth yn disgrifio eraill
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Defnyddir newidynnau amgylchedd i ffurfweddu mynediad cronfa ddata yn cube.js. Bydd y generadur yn creu ffeil .env y gallwch chi nodi'ch allweddi ar ei chyfer
Nawr mae angen
Yn y cyfeiriadur schema
, creu ffeil Logs.js
. Dyma enghraifft o fodel data ar gyfer nginx:
Cod 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`
}
}
});
Yma rydym yn defnyddio'r newidyn
Rydym hefyd yn gosod y metrigau a'r paramedrau yr ydym am eu harddangos ar y dangosfwrdd ac yn nodi rhag-gasglu. Bydd Cube.js yn creu tablau ychwanegol gyda data wedi'i gydgrynhoi ymlaen llaw a bydd yn diweddaru'r data yn awtomatig wrth iddo gyrraedd. Mae hyn nid yn unig yn cyflymu ymholiadau, ond hefyd yn lleihau cost defnyddio Athena.
Gadewch i ni ychwanegu'r wybodaeth hon at y ffeil sgema 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`
)
}
}
}
Rydym yn nodi yn y model hwn bod angen rhag-gyfuno data ar gyfer yr holl fetrigau a ddefnyddir, a defnyddio rhaniad fesul mis.
Nawr gallwn ni gydosod y dangosfwrdd!
Mae backend Cube.js yn darparu
Mae gweinydd Cube.js yn derbyn y cais i mewn
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
Gadewch i ni osod y cleient Cube.js a'r llyfrgell cydrannau React trwy NPM:
$ npm i --save @cubejs-client/core @cubejs-client/react
Rydym yn mewnforio cydrannau cubejs
ΠΈ QueryRenderer
i lawrlwytho'r data, a chasglu'r dangosfwrdd:
Cod dangosfwrdd
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>
);
}}
/>
)
}
Mae ffynonellau dangosfwrdd ar gael yn
Ffynhonnell: hab.com