Parasti Nginx darbÄ«bas uzraudzÄ«bai un analÄ«zei tiek izmantoti komerciÄli produkti vai gatavas atvÄrtÄ pirmkoda alternatÄ«vas, piemÄram, Prometheus + Grafana. Å Ä« ir laba iespÄja uzraudzÄ«bai vai reÄllaika analÄ«zei, taÄu ne pÄrÄk Ärta vÄsturiskai analÄ«zei. JebkurÄ populÄrajÄ resursÄ nginx žurnÄlu datu apjoms strauji pieaug, un, lai analizÄtu lielu datu apjomu, ir loÄ£iski izmantot kaut ko specializÄtÄku.
Å ajÄ rakstÄ es jums pastÄstÄ«Å”u, kÄ jÅ«s varat izmantot
TL:DR;
Lai apkopotu informÄciju, ko mÄs izmantojam
Nginx žurnÄlu vÄkÅ”ana
PÄc noklusÄjuma Nginx žurnÄli izskatÄs Å”Ädi:
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" "-"
Tos var parsÄt, taÄu ir daudz vieglÄk labot Nginx konfigurÄciju, lai tÄ izveidotu žurnÄlus 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 uzglabÄÅ”anai
Lai saglabÄtu žurnÄlus, mÄs izmantosim S3. Tas ļauj glabÄt un analizÄt žurnÄlus vienuviet, jo Athena var tieÅ”i strÄdÄt ar datiem S3. VÄlÄk rakstÄ es jums pastÄstÄ«Å”u, kÄ pareizi pievienot un apstrÄdÄt žurnÄlus, taÄu vispirms mums ir nepiecieÅ”ams tÄ«rs S3 spainis, kurÄ nekas cits netiks saglabÄts. Ir vÄrts iepriekÅ” apsvÄrt, kurÄ reÄ£ionÄ veidosit savu spaini, jo Athena nav pieejams visos reÄ£ionos.
ĶÄdes izveide Athena konsolÄ
AtÄnÄs izveidosim tabulu žurnÄliem. Tas ir nepiecieÅ”ams gan rakstÄ«Å”anai, gan lasÄ«Å”anai, ja plÄnojat izmantot Kinesis Firehose. Atveriet Athena konsoli un izveidojiet tabulu:
SQL tabulas izveide
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');
Kinesis Firehose Stream izveide
Kinesis Firehose no Nginx saÅemtos datus ierakstÄ«s uz S3 izvÄlÄtajÄ formÄtÄ, sadalot tos direktorijÄs GGGG/MM/DD/HH formÄtÄ. Tas noderÄs, lasot datus. JÅ«s, protams, varat rakstÄ«t tieÅ”i uz S3 no fluentd, taÄu Å”ajÄ gadÄ«jumÄ jums bÅ«s jÄraksta JSON, un tas ir neefektÄ«vi failu lielÄ izmÄra dÄļ. TurklÄt, izmantojot PrestoDB vai Athena, JSON ir lÄnÄkais datu formÄts. TÄtad atveriet Kinesis Firehose konsoli, noklikŔķiniet uz "Izveidot piegÄdes straumi", laukÄ "piegÄde" atlasiet "tieÅ”ais PUT":
NÄkamajÄ cilnÄ atlasiet āIeraksta formÄta konvertÄÅ”anaā - āIespÄjotsā un kÄ ierakstÄ«Å”anas formÄtu atlasiet āApache ORCā. SaskaÅÄ ar dažiem pÄtÄ«jumiem
MÄs izvÄlamies S3 glabÄÅ”anai un iepriekÅ” izveidoto spaini. Aws Glue Crawler, par kuru es runÄÅ”u nedaudz vÄlÄk, nevar strÄdÄt ar prefiksiem S3 spainÄ«, tÄpÄc ir svarÄ«gi atstÄt to tukÅ”u.
PÄrÄjÄs opcijas var mainÄ«t atkarÄ«bÄ no slodzes; es parasti izmantoju noklusÄjuma opcijas. Å emiet vÄrÄ, ka S3 saspieÅ”ana nav pieejama, bet ORC pÄc noklusÄjuma izmanto sÄkotnÄjo saspieÅ”anu.
tekoŔi
Tagad, kad esam konfigurÄjuÅ”i žurnÄlu glabÄÅ”anu un saÅemÅ”anu, mums ir jÄkonfigurÄ sÅ«tÄ«Å”ana. MÄs izmantosim
PirmkÄrt, mums ir nepiecieÅ”ams konfigurÄcijas fails fluent.conf. Izveidojiet to un pievienojiet avotu:
port 24224
saistīt 0.0.0.0
Tagad varat palaist Fluentd serveri. Ja jums nepiecieÅ”ama papildu konfigurÄcija, dodieties uz
$ 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
Å ajÄ konfigurÄcijÄ tiek izmantots ceļŔ /fluentd/log
keÅ”atmiÅÄ saglabÄt žurnÄlus pirms nosÅ«tÄ«Å”anas. JÅ«s varat iztikt bez Ŕī, taÄu, restartÄjot, varat zaudÄt visu, kas ir saglabÄts keÅ”atmiÅÄ, ko izraisa aizkavÄjoÅ”s darbs. Varat arÄ« izmantot jebkuru portu; 24224 ir noklusÄjuma Fluentd ports.
Tagad, kad darbojas Fluentd, mÄs varam tur nosÅ«tÄ«t Nginx žurnÄlus. MÄs parasti palaižam Nginx Docker konteinerÄ, un tÄdÄ gadÄ«jumÄ Docker ir vietÄjais Fluentd reÄ£istrÄÅ”anas draiveris:
$ 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
Ja palaižat Nginx citÄdi, varat izmantot žurnÄlfailus, ko piedÄvÄ Fluentd
Pievienosim iepriekÅ” konfigurÄto žurnÄla parsÄÅ”anu Fluent konfigurÄcijai:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
Un žurnÄlu nosÅ«tÄ«Å”ana uz Kinesis, izmantojot
<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
Ja esat visu pareizi konfigurÄjis, tad pÄc kÄda laika (pÄc noklusÄjuma Kinesis reÄ£istrÄ saÅemtos datus reizi 10 minÅ«tÄs) jums vajadzÄtu redzÄt žurnÄla failus S3. Kinesis Firehose izvÄlnÄ āUzraudzÄ«baā varat redzÄt, cik daudz datu ir ierakstÄ«ts S3, kÄ arÄ« kļūdas. Neaizmirstiet pieŔķirt Kinesis lomai rakstÄ«Å”anas piekļuvi S3 spainim. Ja Kinesis nevarÄja kaut ko parsÄt, tas pievienos kļūdas tam paÅ”am segmentam.
Tagad jÅ«s varat skatÄ«t datus pakalpojumÄ AtÄna. AtradÄ«sim jaunÄkos pieprasÄ«jumus, par kuriem atgriezÄm kļūdas:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
SkenÄ visus ierakstus katram pieprasÄ«jumam
Tagad mÅ«su žurnÄli ir apstrÄdÄti un saglabÄti S3 ORC, saspiesti un gatavi analÄ«zei. Kinesis Firehose pat organizÄja tos direktorijos katrai stundai. TomÄr, kamÄr tabula nav sadalÄ«ta, Athena ielÄdÄs visu laiku datus par katru pieprasÄ«jumu, ar retiem izÅÄmumiem. TÄ ir liela problÄma divu iemeslu dÄļ:
- Datu apjoms nepÄrtraukti pieaug, palÄninot vaicÄjumus;
- Maksa par Athena tiek iekasÄta, pamatojoties uz skenÄto datu apjomu, vismaz 10 MB vienam pieprasÄ«jumam.
Lai to novÄrstu, mÄs izmantojam AWS Glue Crawler, kas pÄrmeklÄs datus S3 un ierakstÄ«s nodalÄ«juma informÄciju Glue metastore. Tas ļaus mums izmantot nodalÄ«jumus kÄ filtru, veicot vaicÄjumu Athena, un tas skenÄs tikai vaicÄjumÄ norÄdÄ«tos direktorijus.
Amazon Glue Crawler iestatīŔana
Amazon Glue Crawler skenÄ visus S3 spainÄ« esoÅ”os datus un izveido tabulas ar nodalÄ«jumiem. Izveidojiet Glue Crawler no AWS Glue konsoles un pievienojiet spaini, kurÄ glabÄjat datus. Varat izmantot vienu rÄpuļprogrammu vairÄkiem segmentiem, un tÄdÄ gadÄ«jumÄ tas izveidos tabulas norÄdÄ«tajÄ datu bÄzÄ ar nosaukumiem, kas atbilst segmentu nosaukumiem. Ja plÄnojat regulÄri izmantot Å”os datus, noteikti konfigurÄjiet rÄpuļprogrammas palaiÅ”anas grafiku atbilstoÅ”i savÄm vajadzÄ«bÄm. MÄs izmantojam vienu rÄpuļprogrammu visiem galdiem, kas darbojas katru stundu.
Sadalītas tabulas
PÄc pirmÄs rÄpuļprogrammas palaiÅ”anas iestatÄ«jumos norÄdÄ«tajÄ datu bÄzÄ jÄparÄdÄs katra skenÄtÄ segmenta tabulÄm. Atveriet Athena konsoli un atrodiet tabulu ar Nginx žurnÄliem. MÄÄ£inÄsim kaut ko izlasÄ«t:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Å ajÄ vaicÄjumÄ tiks atlasÄ«ti visi ieraksti, kas saÅemti no 6. gada 7. aprīļa plkst. 8:2019 lÄ«dz plkst. XNUMX:XNUMX. Bet cik daudz efektÄ«vÄk tas ir nekÄ tikai lasÄ«Å”ana no nesadalÄ«tas tabulas? Noskaidrosim un atlasÄ«sim tos paÅ”us ierakstus, filtrÄjot tos pÄc laikspiedola:
3.59 sekundes un 244.34 megabaiti datu datu kopÄ ar tikai nedÄļas žurnÄliem. IzmÄÄ£inÄsim filtru pÄc nodalÄ«juma:
Nedaudz ÄtrÄk, bet pats galvenais ā tikai 1.23 megabaiti datu! Tas bÅ«tu daudz lÄtÄk, ja ne minimÄlie 10 megabaiti vienam pieprasÄ«jumam cenÄ. Bet tas joprojÄm ir daudz labÄks, un lielÄs datu kopÄs atŔķirÄ«ba bÅ«s daudz iespaidÄ«gÄka.
InformÄcijas paneļa izveide, izmantojot Cube.js
Lai saliktu informÄcijas paneli, mÄs izmantojam Cube.js analÄ«tisko sistÄmu. Tam ir diezgan daudz funkciju, taÄu mÅ«s interesÄ divas: iespÄja automÄtiski izmantot nodalÄ«jumu filtrus un datu iepriekÅ”Äja apkopoÅ”ana. Tas izmanto datu shÄmu
Izveidosim jaunu Cube.js lietojumprogrammu. TÄ kÄ mÄs jau izmantojam AWS steku, ir loÄ£iski izmantot Lambda izvietoÅ”anai. Varat izmantot ÄtrÄs veidnes Ä£enerÄÅ”anai, ja plÄnojat mitinÄt Cube.js aizmugursistÄmu Heroku vai Docker. DokumentÄcijÄ ir aprakstÄ«ti citi
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Vides mainÄ«gie tiek izmantoti, lai konfigurÄtu piekļuvi datubÄzei failÄ cube.js. Ä¢enerators izveidos .env failu, kurÄ varÄsiet norÄdÄ«t savas atslÄgas
Tagad mums vajag
DirektorijÄ schema
, izveidojiet failu Logs.js
. Å eit ir nginx datu modeļa piemÄrs:
Modeļa kods
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`
}
}
});
Å eit mÄs izmantojam mainÄ«go
MÄs arÄ« iestatÄm metriku un parametrus, ko vÄlamies parÄdÄ«t informÄcijas panelÄ«, un norÄdÄm iepriekÅ”Äju apkopojumu. Cube.js izveidos papildu tabulas ar iepriekÅ” apkopotiem datiem un automÄtiski atjauninÄs datus, tiklÄ«dz tie tiks saÅemti. Tas ne tikai paÄtrina vaicÄjumu izpildi, bet arÄ« samazina Athena lietoÅ”anas izmaksas.
Pievienosim Å”o informÄciju datu shÄmas failam:
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`
)
}
}
}
Å ajÄ modelÄ« mÄs norÄdÄm, ka ir nepiecieÅ”ams iepriekÅ” apkopot datus par visiem izmantotajiem rÄdÄ«tÄjiem un izmantot sadalÄ«jumu pa mÄneÅ”iem.
Tagad mÄs varam salikt informÄcijas paneli!
Cube.js aizmugure nodroŔina
Cube.js serveris pieÅem pieprasÄ«jumu
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
InstalÄsim Cube.js klientu un React komponentu bibliotÄku, izmantojot NPM:
$ npm i --save @cubejs-client/core @cubejs-client/react
MÄs importÄjam komponentus cubejs
Šø QueryRenderer
lai lejupielÄdÄtu datus un apkopotu informÄcijas paneli:
InformÄcijas paneļa kods
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>
);
}}
/>
)
}
InformÄcijas paneļa avoti ir pieejami vietnÄ
Avots: www.habr.com