Bi gelemperî, hilberên bazirganî an alternatîfên çavkaniya vekirî ya amade, wekî Prometheus + Grafana, ji bo şopandin û analîzkirina xebata Nginx têne bikar anîn. Ev vebijarkek baş e ji bo şopandin an analîzên rast-dem, lê ji bo analîzên dîrokî ne pir hêsan e. Li ser her çavkaniyek populer, qebareya daneyên ji têketinên nginx bi lez mezin dibe, û ji bo analîzkirina hejmareke mezin a daneyan, mentiqî ye ku meriv tiştek pisportir bikar bîne.
Di vê gotarê de ez ê ji we re vebêjim ka hûn çawa dikarin bikar bînin
TL:DR;
Ji bo berhevkirina agahdariyê em bikar tînin
Komkirina têketinên Nginx
Bi xwerû, têketinên Nginx bi vî rengî xuya dikin:
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" "-"
Ew dikarin bêne pars kirin, lê pir hêsantir e ku meriv veavakirina Nginx rast bike da ku ew di JSON de têketin çêbike:
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 ji bo hilanînê
Ji bo tomarkirina têketin, em ê S3 bikar bînin. Ev dihêle hûn têketin li yek cîhek hilînin û analîz bikin, ji ber ku Athena dikare rasterast bi daneyên S3 re bixebite. Dûv re di gotarê de ez ê ji we re vebêjim ka meriv çawa têketinên rast lê zêde bike û pêvajoyê bike, lê pêşî ji me re kelek paqij di S3 de hewce ye, ku tê de tiştek din neyê hilanîn. Hêja ye ku meriv berê xwe bide ber çavan ku hûn ê li kîjan herêmê kepçeya xwe biafirînin, ji ber ku Athena li hemî deveran peyda nabe.
Di konsolê Athena de çerxek çêbikin
Ka em li Athena ji bo têketin tabloyek çêbikin. Heke hûn plan dikin ku Kinesis Firehose bikar bînin hem ji bo nivîsandinê hem jî ji bo xwendinê hewce ye. Konsolê Athena vekin û tabloyek çêbikin:
Afirandina tabloya 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');
Afirandina Kinesis Firehose Stream
Kinesis Firehose dê daneyên ku ji Nginx-ê ji S3-ê hatî wergirtin di forma hilbijartî de binivîsîne, wê li pelrêçan di forma YYYY/MM/DD/HH de dabeş bike. Ev dê di dema xwendina daneyan de bi kêr were. Bê guman, hûn dikarin rasterast li S3-ê ji fluentd-ê binivîsin, lê di vê rewşê de hûn neçar in ku JSON binivîsin, û ev ji ber mezinahiya pelan bêbandor e. Wekî din, dema ku PrestoDB an Athena bikar tînin, JSON formata daneya herî hêdî ye. Ji ber vê yekê konsolê Kinesis Firehose vekin, bikirtînin "Çaxa radestkirinê biafirînin", di qada "radestkirinê" de "PUT rasterast" hilbijêrin:
Di tabloya paşîn de, "Veguheztina formata tomarkirinê" - "Enabled" hilbijêrin û "Apache ORC" wekî forma tomarkirinê hilbijêrin. Li gorî hin lêkolînan
Em ji bo hilanînê S3 û kepçeya ku me berê afirandiye hilbijêrin. Aws Glue Crawler, ya ku ez ê piçekî paşê qala wê bikim, nikare bi pêşgiran di kelek S3 de bixebite, ji ber vê yekê girîng e ku ew vala bihêlin.
Vebijarkên mayî dikarin li gorî barkirina we werin guheztin; Ez bi gelemperî yên xwerû bikar tînim. Bala xwe bidinê ku kompresyona S3 ne berdest e, lê ORC ji hêla xwerû ve berhevkirina xwemalî bikar tîne.
herikandin
Naha ku me tomarkirin û wergirtina têketin mîheng kiriye, pêdivî ye ku em şandinê mîheng bikin. Em ê bikar bînin
Pêşî, pêdiviya me bi pelê veavakirina fluent.conf heye. Wê biafirînin û çavkaniyê lê zêde bikin:
Port 24224
girêdan 0.0.0.0
Naha hûn dikarin servera Fluentd dest pê bikin. Ger hewceyê vesazkirinek pêşkeftî be, biçin
$ 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
Ev veavakirin rê bi kar tîne /fluentd/log
berî şandina têketinên cache. Hûn dikarin bêyî vê yekê bikin, lê dûv re gava ku hûn ji nû ve dest pê bikin, hûn dikarin her tiştê ku bi keda paşverû hatî girtin winda bikin. Her weha hûn dikarin her portê bikar bînin; 24224 porta Fluentd ya xwerû ye.
Naha ku me Fluentd dimeşîne, em dikarin têketinên Nginx li wir bişînin. Em bi gelemperî Nginx-ê di konteynirek Docker de dimeşînin, di vê rewşê de Docker ji bo Fluentd ajokarek têketinê ya xwecihî heye:
$ 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
Ger hûn Nginx-ê cûda dimeşînin, hûn dikarin pelên têketinê bikar bînin, Fluentd heye
Ka em parsinga têketinê ya ku li jor hatî mîheng kirin li veavakirina Fluent zêde bikin:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
Û şandina têketinên Kinesis bi kar tînin
<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>
Atena
Ger we her tişt rast mîheng kiriye, wê hingê piştî demekê (bi xwerû, Kinesis her 10 hûrdem carekê daneyan distîne) divê hûn pelên têketinê li S3 bibînin. Di menuya "şopandinê" ya Kinesis Firehose de hûn dikarin bibînin ka çiqas daneya di S3 de têne tomar kirin, û hem jî xeletiyan. Ji bîr nekin ku hûn gihandina nivîsandinê bidin berika S3 rola Kinesis. Ger Kinesis nekari tiştek parsek bike, ew ê xeletiyan li heman kelê zêde bike.
Niha hûn dikarin daneyên li Athena bibînin. Ka em daxwazên herî paşîn ên ku me xeletî vedigerin bibînin:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Ji bo her daxwazê hemû tomar dişoxilînin
Naha têketinên me di S3-ê de di ORC de hatine pêvajo kirin û hilanîn, hatine berhev kirin û ji bo analîzê amade ne. Kinesis Firehose tewra ji bo her demjimêrê wan di pelrêçan de organîze kir. Lêbelê, heya ku tablo neyê dabeş kirin, Athena dê li ser her daxwazê, bi îstîsnayên hindik, daneyên hemî-demê bar bike. Ji ber du sedeman ev pirsgirêkek mezin e:
- Hêjmara daneyan her ku diçe mezin dibe, pirsan hêdî dike;
- Athena li ser bingeha qebareya daneya ku hatî şopandin, bi her daxwazek herî kêm 10 MB tê hesab kirin.
Ji bo rastkirina vê yekê, em AWS Glue Crawler bikar tînin, ku dê daneya di S3 de bişopîne û agahdariya dabeşkirinê li Glue Metastore binivîse. Ev ê bihêle ku em dema ku pirsa Athena-yê dipirsin, dabeşan wekî parzûnek bikar bînin, û ew ê tenê pelrêçiyên ku di pirsnameyê de hatine destnîşan kirin bigerin.
Sazkirina Amazon Glue Crawler
Amazon Glue Crawler hemî daneyên di kepçeya S3 de dişoxilîne û bi dabeşan tabloyan diafirîne. Ji konsolê AWS Glue Crawlerek Glue biafirînin û kelekek lê zêde bikin ku hûn daneyan hilînin. Hûn dikarin ji bo çend kepçeyan yek crawler bikar bînin, di vê rewşê de ew ê di databasa diyarkirî de tabloyan bi navên ku navên kepçeyan li hev dikin biafirîne. Ger hûn plan dikin ku van daneyan bi rêkûpêk bikar bînin, bê guman nexşeya destpêkirina Crawler-ê li gorî hewcedariyên we mîheng bikin. Em ji bo hemî tabloyan yek Crawler bikar tînin, ku her demjimêr dimeşe.
Maseyên dabeşkirî
Piştî destpêkirina yekem a crawler, divê tabloyên ji bo her kelek skankirî di databasa ku di mîhengan de hatî destnîşan kirin xuya bibin. Konsolê Athena vekin û tabloya bi têketinên Nginx re bibînin. Ka em hewl bidin ku tiştek bixwînin:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Ev pirs dê hemî tomarên ku di navbera 6-ê sibehê û 7-ê sibehê de 8ê Avrêl, 2019-an de hatine wergirtin hilbijêrin. Lê ev ji xwendina ji tabloyek ne-parvekirî çiqas bikêrtir e? Ka em heman tomaran bibînin û hilbijêrin, wan li gorî demjimêrê fîlter bikin:
3.59 saniye û 244.34 megabytes daneya li ser daneyek bi tenê hefteyek têketin. Ka em parzûnek bi dabeşkirinê biceribînin:
Piçek zûtir, lê ya herî girîng - tenê 1.23 megabytes daneyê! Ger di nirxê de her daxwazek herî kêm 10 megabayt nebe dê pir erzantir be. Lê ew hîn jî pir çêtir e, û li ser daneyên mezin cûdahî dê pir bi heybettir be.
Avakirina dashboardek bi karanîna Cube.js
Ji bo komkirina dashboardê, em çarçoveya analîtîk Cube.js bikar tînin. Gelek fonksiyonên wê hene, lê em bi du kesan re eleqedar dibin: şiyana ku bixweber bikar anîna fîlterên dabeşkirinê û berhevkirina daneyan. Ew şema daneyê bikar tîne
Werin em serîlêdanek nû ya Cube.js biafirînin. Ji ber ku em berê steka AWS bikar tînin, mentiqî ye ku meriv Lambda ji bo bicîhkirinê bikar bîne. Heke hûn plan dikin ku paşîna Cube.js-ê li Heroku an Docker-ê mêvandar bikin, hûn dikarin ji bo nifşê şablonê ekspres bikar bînin. Belgekirin yên din diyar dike
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Guherbarên jîngehê ji bo mîhengkirina gihîştina databasê di cube.js de têne bikar anîn. Dê jenerator pelek .env biafirîne ku tê de hûn dikarin mifteyên xwe ji bo diyar bikin
Niha em hewce ne
Di pelrêça schema
, pelek çêbikin Logs.js
. Li vir mînakek modela daneyê ji bo nginx heye:
Koda 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`
}
}
});
Li vir em guhêrbar bikar tînin
Me her weha metrîk û pîvanên ku em dixwazin li ser tabloyê nîşan bidin destnîşan dikin û berhevokên pêşîn diyar dikin. Cube.js dê bi daneyên pêş-hevkirî tabloyên zêde biafirîne û gava ku ew digihîje dê bixweber daneyan nûve bike. Ev ne tenê pirsan bilez dike, lê di heman demê de lêçûna karanîna Athena jî kêm dike.
Ka em vê agahiyê li pelê şema daneyê zêde bikin:
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`
)
}
}
}
Em di vê modelê de diyar dikin ku pêdivî ye ku ji bo hemî metrîkên ku têne bikar anîn daneyan pêş-kom bikin, û dabeşkirina mehane bikar bînin.
Naha em dikarin dashboardê bicivînin!
Cube.js paşperdeya peyda dike
Pêşkêşkara Cube.js daxwazê qebûl dike
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
Werin em muwekîlê Cube.js û pirtûkxaneya pêkhateya React bi navgîniya NPM-ê saz bikin:
$ npm i --save @cubejs-client/core @cubejs-client/react
Em pêkhateyan îthal dikin cubejs
и QueryRenderer
daxistina daneyan, û berhevkirina dashboardê:
Koda 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>
);
}}
/>
)
}
Çavkaniyên dashboardê li ser hene
Source: www.habr.com