Na monitorovanie a analýzu fungovania Nginx sa zvyčajne používajú komerčné produkty alebo hotové alternatívy s otvoreným zdrojom, ako napríklad Prometheus + Grafana. Je to dobrá možnosť na monitorovanie alebo analýzu v reálnom čase, ale nie je veľmi vhodná na analýzu histórie. Na akomkoľvek populárnom zdroji objem údajov z protokolov nginx rýchlo rastie a na analýzu veľkého množstva údajov je logické použiť niečo špecializovanejšie.
V tomto článku vám poviem, ako ho môžete použiť
TL:DR;
Na zhromažďovanie informácií, ktoré používame
Zbieranie denníkov Nginx
V predvolenom nastavení vyzerajú protokoly Nginx asi takto:
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" "-"
Môžu byť analyzované, ale je oveľa jednoduchšie opraviť konfiguráciu Nginx tak, aby vytvárala protokoly v 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 na uskladnenie
Na ukladanie protokolov použijeme S3. To vám umožňuje ukladať a analyzovať protokoly na jednom mieste, pretože Athena môže pracovať s údajmi priamo v S3. Ďalej v článku vám poviem, ako správne pridávať a spracovávať protokoly, ale najprv potrebujeme čisté vedro v S3, v ktorom nebude uložené nič iné. Oplatí sa vopred zvážiť, v ktorom regióne budete svoj vedro vytvárať, pretože Athena nie je dostupná vo všetkých regiónoch.
Vytvorenie okruhu v konzole Athena
V Athene vytvoríme tabuľku pre protokoly. Je potrebný na písanie aj čítanie, ak plánujete používať Kinesis Firehose. Otvorte konzolu Athena a vytvorte tabuľku:
Vytvorenie SQL tabuľky
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');
Vytvorenie Kinesis Firehose Stream
Kinesis Firehose zapíše dáta prijaté z Nginx do S3 vo zvolenom formáte a rozdelí ich do adresárov vo formáte RRRR/MM/DD/HH. To sa vám bude hodiť pri čítaní údajov. Z fluentd môžete samozrejme zapisovať priamo do S3, ale v tomto prípade budete musieť napísať JSON, čo je neefektívne kvôli veľkej veľkosti súborov. Navyše, keď používate PrestoDB alebo Athena, JSON je najpomalší dátový formát. Otvorte teda konzolu Kinesis Firehose, kliknite na „Vytvoriť stream doručenia“, v poli „doručenie“ vyberte „priame PUT“:
Na ďalšej karte vyberte „Konverzia formátu záznamu“ - „Povolené“ a ako formát záznamu vyberte „Apache ORC“. Podľa niektorých výskumov
Na uloženie vyberieme S3 a vedro, ktoré sme vytvorili skôr. Aws Glue Crawler, o ktorom budem hovoriť o niečo neskôr, nemôže pracovať s predponami vo vedre S3, takže je dôležité nechať ho prázdny.
Zostávajúce možnosti je možné zmeniť v závislosti od vašej záťaže; zvyčajne používam predvolené. Upozorňujeme, že kompresia S3 nie je dostupná, ale ORC štandardne používa natívnu kompresiu.
Plynulé
Teraz, keď sme nakonfigurovali ukladanie a prijímanie protokolov, musíme nakonfigurovať odosielanie. Budeme používať
Najprv potrebujeme konfiguračný súbor fluent.conf. Vytvorte ho a pridajte zdroj:
Port 24224
viazať 0.0.0.0
Teraz môžete spustiť server Fluentd. Ak potrebujete pokročilejšiu konfiguráciu, prejdite na
$ 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
Táto konfigurácia používa cestu /fluentd/log
pred odoslaním uložiť denníky do vyrovnávacej pamäte. Môžete to urobiť bez toho, ale po reštarte môžete stratiť všetko, čo je uložené vo vyrovnávacej pamäti. Môžete tiež použiť ľubovoľný port; 24224 je predvolený port Fluentd.
Teraz, keď máme spustený Fluentd, môžeme tam posielať protokoly Nginx. Nginx zvyčajne spúšťame v kontajneri Docker, v takom prípade má Docker natívny ovládač protokolovania pre 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
Ak spustíte Nginx inak, môžete použiť protokolové súbory, ktoré má Fluentd
Pridajme analýzu protokolu nakonfigurovanú vyššie do konfigurácie Fluent:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
A odosielanie protokolov do Kinesis pomocou
<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
Ak ste všetko nakonfigurovali správne, po chvíli (štandardne Kinesis zaznamenáva prijaté údaje raz za 10 minút) by ste mali vidieť log súbory v S3. V ponuke „monitorovanie“ Kinesis Firehose môžete vidieť, koľko údajov je zaznamenaných v S3, ako aj chyby. Nezabudnite dať rolu Kinesis prístup na zápis do bloku S3. Ak Kinesis niečo nedokáže analyzovať, pridá chyby do toho istého vedra.
Teraz si môžete prezerať údaje v Athene. Poďme nájsť najnovšie žiadosti, pre ktoré sme vrátili chyby:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
Skenovanie všetkých záznamov pre každú požiadavku
Teraz sú naše protokoly spracované a uložené v S3 v ORC, komprimované a pripravené na analýzu. Kinesis Firehose ich dokonca usporiadal do adresárov na každú hodinu. Pokiaľ však tabuľka nie je rozdelená na partície, Athena načíta všetky údaje pri každej požiadavke, až na zriedkavé výnimky. Toto je veľký problém z dvoch dôvodov:
- Objem dát neustále rastie, čím sa spomaľujú dopyty;
- Athena sa účtuje na základe objemu naskenovaných dát, pričom na žiadosť je minimálne 10 MB.
Aby sme to vyriešili, používame AWS Glue Crawler, ktorý prehľadá údaje v S3 a zapíše informácie o oddieloch do Glue Metastore. To nám umožní použiť oddiely ako filter pri dopytovaní Atheny a bude skenovať iba adresáre uvedené v dotaze.
Nastavenie prehľadávača Amazon Glue Crawler
Amazon Glue Crawler naskenuje všetky údaje vo vedre S3 a vytvorí tabuľky s oddielmi. Vytvorte Glue Crawler z konzoly AWS Glue a pridajte vedro, kde ukladáte dáta. Jeden prehľadávač môžete použiť pre niekoľko segmentov, v takom prípade vytvorí tabuľky v zadanej databáze s názvami, ktoré sa zhodujú s názvami segmentov. Ak plánujete tieto údaje používať pravidelne, nezabudnite nakonfigurovať plán spúšťania Crawlera tak, aby vyhovoval vašim potrebám. Na všetky stoly používame jeden Crawler, ktorý beží každú hodinu.
Rozdelené stoly
Po prvom spustení prehľadávača by sa tabuľky pre každý naskenovaný segment mali objaviť v databáze špecifikovanej v nastaveniach. Otvorte konzolu Athena a nájdite tabuľku s protokolmi Nginx. Skúsme si niečo prečítať:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
Tento dopyt vyberie všetky záznamy prijaté medzi 6:7 a 8:2019 dňa XNUMX. apríla XNUMX. O čo je to však efektívnejšie ako len čítanie z nerozdelenej tabuľky? Poďme zistiť a vybrať rovnaké záznamy, filtrovať ich podľa časovej pečiatky:
3.59 sekundy a 244.34 megabajtov údajov v súbore údajov iba s týždennými protokolmi. Skúsme filtrovať podľa oddielu:
O niečo rýchlejšie, ale čo je najdôležitejšie – iba 1.23 MB dát! Bolo by to oveľa lacnejšie, ak by v cene nebolo minimálne 10 megabajtov na požiadavku. Stále je to však oveľa lepšie a na veľkých súboroch údajov bude rozdiel oveľa pôsobivejší.
Vytvorenie dashboardu pomocou Cube.js
Na zostavenie dashboardu používame analytický rámec Cube.js. Má pomerne veľa funkcií, ale nás zaujímajú dve: možnosť automatického používania filtrov partícií a predagregácie dát. Používa dátovú schému
Poďme vytvoriť novú aplikáciu Cube.js. Keďže už používame zásobník AWS, je logické použiť na nasadenie Lambda. Express šablónu môžete použiť na generovanie, ak plánujete hostiť backend Cube.js v Heroku alebo Docker. Dokumentácia popisuje ostatné
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
Premenné prostredia sa používajú na konfiguráciu prístupu k databáze v cube.js. Generátor vytvorí súbor .env, v ktorom môžete špecifikovať svoje kľúče
Teraz potrebujeme
V adresári schema
, vytvorte súbor Logs.js
. Tu je príklad dátového modelu pre nginx:
Kód modelu
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`
}
}
});
Tu používame premennú
Nastavíme tiež metriky a parametre, ktoré chceme zobraziť na dashboarde a určíme predagregácie. Cube.js vytvorí ďalšie tabuľky s vopred agregovanými údajmi a automaticky aktualizuje údaje, keď prídu. To nielen zrýchľuje dopyty, ale aj znižuje náklady na používanie Atheny.
Pridajme tieto informácie do súboru dátovej schémy:
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`
)
}
}
}
V tomto modeli špecifikujeme, že je potrebné vopred agregovať údaje pre všetky použité metriky a použiť rozdelenie podľa mesiacov.
Teraz môžeme zostaviť palubnú dosku!
Backend Cube.js poskytuje
Server Cube.js prijme požiadavku
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
Nainštalujeme klienta Cube.js a knižnicu komponentov React cez NPM:
$ npm i --save @cubejs-client/core @cubejs-client/react
Dovážame komponenty cubejs
и QueryRenderer
stiahnuť údaje a zhromaždiť informačný panel:
Kód palubnej dosky
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>
);
}}
/>
)
}
Zdroje palubnej dosky sú dostupné na
Zdroj: hab.com