సాధారణంగా, వాణిజ్య ఉత్పత్తులు లేదా ప్రోమేథియస్ + గ్రాఫానా వంటి రెడీమేడ్ ఓపెన్ సోర్స్ ప్రత్యామ్నాయాలు Nginx యొక్క ఆపరేషన్ను పర్యవేక్షించడానికి మరియు విశ్లేషించడానికి ఉపయోగించబడతాయి. ఇది పర్యవేక్షణ లేదా నిజ-సమయ విశ్లేషణలకు మంచి ఎంపిక, కానీ చారిత్రక విశ్లేషణకు చాలా సౌకర్యవంతంగా లేదు. ఏదైనా జనాదరణ పొందిన వనరుపై, nginx లాగ్ల నుండి డేటా పరిమాణం వేగంగా పెరుగుతోంది మరియు పెద్ద మొత్తంలో డేటాను విశ్లేషించడానికి, మరింత ప్రత్యేకమైనదాన్ని ఉపయోగించడం తార్కికం.
మీరు ఎలా ఉపయోగించవచ్చో ఈ వ్యాసంలో నేను మీకు చెప్తాను
TL:DR;
మేము ఉపయోగించే సమాచారాన్ని సేకరించడానికి
Nginx లాగ్లను సేకరిస్తోంది
డిఫాల్ట్గా, Nginx లాగ్లు ఇలా కనిపిస్తాయి:
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" "-"
వాటిని అన్వయించవచ్చు, కానీ Nginx కాన్ఫిగరేషన్ను సరిచేయడం చాలా సులభం, తద్వారా ఇది 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
లాగ్లను నిల్వ చేయడానికి, మేము S3ని ఉపయోగిస్తాము. ఎథీనా నేరుగా S3లోని డేటాతో పని చేయగలదు కాబట్టి, లాగ్లను ఒకే చోట నిల్వ చేయడానికి మరియు విశ్లేషించడానికి ఇది మిమ్మల్ని అనుమతిస్తుంది. తరువాత వ్యాసంలో లాగ్లను ఎలా సరిగ్గా జోడించాలో మరియు ప్రాసెస్ చేయాలో నేను మీకు చెప్తాను, అయితే మొదట మనకు S3 లో క్లీన్ బకెట్ అవసరం, దీనిలో మరేమీ నిల్వ చేయబడదు. ఎథీనా అన్ని ప్రాంతాలలో అందుబాటులో లేనందున మీరు మీ బకెట్ను ఏ ప్రాంతంలో సృష్టించాలనుకుంటున్నారో ముందుగానే పరిగణించాలి.
ఎథీనా కన్సోల్లో సర్క్యూట్ను సృష్టిస్తోంది
లాగ్ల కోసం ఎథీనాలో టేబుల్ని క్రియేట్ చేద్దాం. మీరు కైనెసిస్ ఫైర్హోస్ని ఉపయోగించాలని ప్లాన్ చేస్తే, ఇది రాయడం మరియు చదవడం రెండింటికీ అవసరం. ఎథీనా కన్సోల్ని తెరిచి, పట్టికను సృష్టించండి:
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');
కైనెసిస్ ఫైర్హోస్ స్ట్రీమ్ను సృష్టిస్తోంది
Kinesis Firehose ఎంచుకున్న ఫార్మాట్లో Nginx నుండి S3కి స్వీకరించిన డేటాను వ్రాసి, దానిని YYYY/MM/DD/HH ఆకృతిలో డైరెక్టరీలుగా విభజిస్తుంది. డేటాను చదివేటప్పుడు ఇది ఉపయోగపడుతుంది. మీరు fluentd నుండి నేరుగా S3కి వ్రాయవచ్చు, కానీ ఈ సందర్భంలో మీరు JSON అని వ్రాయవలసి ఉంటుంది మరియు ఫైల్ల యొక్క పెద్ద పరిమాణం కారణంగా ఇది అసమర్థంగా ఉంటుంది. అదనంగా, PrestoDB లేదా Athenaని ఉపయోగిస్తున్నప్పుడు, JSON అనేది నెమ్మదిగా డేటా ఫార్మాట్. కాబట్టి కైనెసిస్ ఫైర్హోస్ కన్సోల్ని తెరిచి, "డెలివరీ స్ట్రీమ్ని సృష్టించు" క్లిక్ చేసి, "డెలివరీ" ఫీల్డ్లో "డైరెక్ట్ PUT"ని ఎంచుకోండి:
తదుపరి ట్యాబ్లో, “రికార్డ్ ఫార్మాట్ మార్పిడి” - “ప్రారంభించబడింది” ఎంచుకోండి మరియు రికార్డింగ్ ఫార్మాట్గా “Apache ORC” ఎంచుకోండి. కొన్ని పరిశోధనల ప్రకారం
మేము నిల్వ కోసం S3ని మరియు ముందుగా సృష్టించిన బకెట్ని ఎంచుకుంటాము. Aws Glue Crawler, నేను కొంచెం తర్వాత మాట్లాడతాను, S3 బకెట్లోని ప్రిఫిక్స్లతో పని చేయలేము, కాబట్టి దానిని ఖాళీగా ఉంచడం ముఖ్యం.
మీ లోడ్ను బట్టి మిగిలిన ఎంపికలను మార్చవచ్చు; నేను సాధారణంగా డిఫాల్ట్ వాటిని ఉపయోగిస్తాను. S3 కంప్రెషన్ అందుబాటులో లేదని గమనించండి, కానీ ORC డిఫాల్ట్గా స్థానిక కుదింపును ఉపయోగిస్తుంది.
నిష్ణాతులు
ఇప్పుడు మేము లాగ్లను నిల్వ చేయడం మరియు స్వీకరించడం కాన్ఫిగర్ చేసాము, మనం పంపడాన్ని కాన్ఫిగర్ చేయాలి. మేము ఉపయోగిస్తాము
ముందుగా, మనకు fluent.conf కాన్ఫిగరేషన్ ఫైల్ అవసరం. దీన్ని సృష్టించండి మరియు మూలాన్ని జోడించండి:
పోర్ట్ 24224
కట్టు 0.0.0.0
ఇప్పుడు మీరు Fluentd సర్వర్ని ప్రారంభించవచ్చు. మీకు మరింత అధునాతన కాన్ఫిగరేషన్ అవసరమైతే, వెళ్ళండి
$ 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
ఈ కాన్ఫిగరేషన్ మార్గాన్ని ఉపయోగిస్తుంది /fluentd/log
పంపే ముందు లాగ్లను కాష్ చేయడానికి. మీరు ఇది లేకుండా చేయవచ్చు, కానీ మీరు పునఃప్రారంభించినప్పుడు, మీరు బ్యాక్ బ్రేకింగ్ లేబర్తో కాష్ చేయబడిన ప్రతిదాన్ని కోల్పోవచ్చు. మీరు ఏదైనా పోర్ట్ని కూడా ఉపయోగించవచ్చు; 24224 అనేది డిఫాల్ట్ Fluentd పోర్ట్.
ఇప్పుడు మనము Fluentd నడుస్తున్నందున, మేము అక్కడ Nginx లాగ్లను పంపవచ్చు. మేము సాధారణంగా డాకర్ కంటైనర్లో Nginxని నడుపుతాము, ఈ సందర్భంలో డాకర్ 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
మీరు Nginxని విభిన్నంగా అమలు చేస్తే, మీరు లాగ్ ఫైల్లను ఉపయోగించవచ్చు, Fluentd ఉంది
పైన కాన్ఫిగర్ చేసిన లాగ్ పార్సింగ్ను ఫ్లూయెంట్ కాన్ఫిగరేషన్కు జోడిద్దాం:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
మరియు ఉపయోగించి కైనెసిస్కు లాగ్లను పంపడం
<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>
ఎథీనా
మీరు ప్రతిదీ సరిగ్గా కాన్ఫిగర్ చేసి ఉంటే, కొంత సమయం తర్వాత (డిఫాల్ట్గా, కైనెసిస్ రికార్డ్లు ప్రతి 10 నిమిషాలకు ఒకసారి డేటాను స్వీకరించాయి) మీరు S3లో లాగ్ ఫైల్లను చూడాలి. కైనెసిస్ ఫైర్హోస్ యొక్క "పర్యవేక్షణ" మెనులో మీరు S3లో ఎంత డేటా నమోదు చేయబడిందో అలాగే లోపాలను చూడవచ్చు. కైనెసిస్ పాత్రకు S3 బకెట్కు రైట్ యాక్సెస్ ఇవ్వడం మర్చిపోవద్దు. కైనెసిస్ ఏదైనా అన్వయించలేకపోతే, అది అదే బకెట్కు లోపాలను జోడిస్తుంది.
ఇప్పుడు మీరు ఎథీనాలో డేటాను చూడవచ్చు. మేము లోపాలను అందించిన తాజా అభ్యర్థనలను కనుగొనండి:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
ప్రతి అభ్యర్థన కోసం అన్ని రికార్డులను స్కాన్ చేస్తోంది
ఇప్పుడు మా లాగ్లు ORCలో S3లో ప్రాసెస్ చేయబడ్డాయి మరియు నిల్వ చేయబడ్డాయి, కుదించబడ్డాయి మరియు విశ్లేషణకు సిద్ధంగా ఉన్నాయి. Kinesis Firehose వాటిని ప్రతి గంటకు డైరెక్టరీలుగా కూడా ఏర్పాటు చేసింది. అయినప్పటికీ, పట్టికను విభజించనంత వరకు, అరుదైన మినహాయింపులతో ప్రతి అభ్యర్థనపై ఎథీనా ఆల్-టైమ్ డేటాను లోడ్ చేస్తుంది. ఇది రెండు కారణాల వల్ల పెద్ద సమస్య:
- డేటా పరిమాణం నిరంతరం పెరుగుతోంది, ప్రశ్నలను నెమ్మదిస్తుంది;
- ఎథీనా స్కాన్ చేయబడిన డేటా పరిమాణం ఆధారంగా బిల్ చేయబడుతుంది, ఒక్కో అభ్యర్థనకు కనీసం 10 MB.
దీన్ని పరిష్కరించడానికి, మేము AWS గ్లూ క్రాలర్ని ఉపయోగిస్తాము, ఇది S3లో డేటాను క్రాల్ చేస్తుంది మరియు విభజన సమాచారాన్ని గ్లూ మెటాస్టోర్కు వ్రాస్తాము. ఇది ఎథీనాను ప్రశ్నించేటప్పుడు విభజనలను ఫిల్టర్గా ఉపయోగించడానికి అనుమతిస్తుంది మరియు ఇది ప్రశ్నలో పేర్కొన్న డైరెక్టరీలను మాత్రమే స్కాన్ చేస్తుంది.
Amazon Glue Crawlerని సెటప్ చేస్తోంది
Amazon Glue Crawler S3 బకెట్లోని మొత్తం డేటాను స్కాన్ చేస్తుంది మరియు విభజనలతో పట్టికలను సృష్టిస్తుంది. AWS గ్లూ కన్సోల్ నుండి గ్లూ క్రాలర్ను సృష్టించండి మరియు మీరు డేటాను నిల్వ చేసే బకెట్ను జోడించండి. మీరు అనేక బకెట్ల కోసం ఒక క్రాలర్ను ఉపయోగించవచ్చు, ఈ సందర్భంలో అది బకెట్ల పేర్లతో సరిపోలే పేర్లతో పేర్కొన్న డేటాబేస్లో పట్టికలను సృష్టిస్తుంది. మీరు ఈ డేటాను క్రమం తప్పకుండా ఉపయోగించాలని ప్లాన్ చేస్తే, మీ అవసరాలకు అనుగుణంగా క్రాలర్ లాంచ్ షెడ్యూల్ను కాన్ఫిగర్ చేయండి. మేము అన్ని టేబుల్ల కోసం ఒక క్రాలర్ని ఉపయోగిస్తాము, ఇది ప్రతి గంటకు నడుస్తుంది.
విభజించబడిన పట్టికలు
క్రాలర్ యొక్క మొదటి లాంచ్ తర్వాత, ప్రతి స్కాన్ చేయబడిన బకెట్ కోసం పట్టికలు సెట్టింగ్లలో పేర్కొన్న డేటాబేస్లో కనిపించాలి. ఎథీనా కన్సోల్ను తెరిచి, Nginx లాగ్లతో పట్టికను కనుగొనండి. ఏదైనా చదవడానికి ప్రయత్నిద్దాం:
SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
partition_0 = '2019' AND
partition_1 = '04' AND
partition_2 = '08' AND
partition_3 = '06'
);
ఈ ప్రశ్న ఏప్రిల్ 6, 7న ఉదయం 8 గంటల నుండి ఉదయం 2019 గంటల వరకు అందుకున్న అన్ని రికార్డులను ఎంపిక చేస్తుంది. కానీ విభజించబడని పట్టిక నుండి చదవడం కంటే ఇది ఎంత సమర్థవంతంగా ఉంటుంది? టైమ్స్టాంప్ ద్వారా వాటిని ఫిల్టర్ చేస్తూ, అదే రికార్డ్లను కనుగొని ఎంచుకుందాం:
ఒక వారం లాగ్లు మాత్రమే ఉన్న డేటాసెట్లో 3.59 సెకన్లు మరియు 244.34 మెగాబైట్ల డేటా. విభజన ద్వారా ఫిల్టర్ని ప్రయత్నిద్దాం:
కొంచెం వేగంగా, కానీ ముఖ్యంగా - 1.23 మెగాబైట్ల డేటా మాత్రమే! ధరలో ఒక అభ్యర్థనకు కనీసం 10 మెగాబైట్లు లేకపోతే ఇది చాలా చౌకగా ఉంటుంది. కానీ ఇది ఇంకా మెరుగ్గా ఉంది మరియు పెద్ద డేటాసెట్లలో వ్యత్యాసం మరింత ఆకట్టుకుంటుంది.
Cube.jsని ఉపయోగించి డాష్బోర్డ్ను రూపొందించడం
డాష్బోర్డ్ను అసెంబుల్ చేయడానికి, మేము Cube.js విశ్లేషణాత్మక ఫ్రేమ్వర్క్ని ఉపయోగిస్తాము. ఇది చాలా ఫంక్షన్లను కలిగి ఉంది, కానీ మేము రెండింటిపై ఆసక్తి కలిగి ఉన్నాము: స్వయంచాలకంగా విభజన ఫిల్టర్లు మరియు డేటా ప్రీ-అగ్రిగేషన్ను ఉపయోగించగల సామర్థ్యం. ఇది డేటా స్కీమాను ఉపయోగిస్తుంది
కొత్త Cube.js అప్లికేషన్ని క్రియేట్ చేద్దాం. మేము ఇప్పటికే AWS స్టాక్ని ఉపయోగిస్తున్నందున, విస్తరణ కోసం లాంబ్డాను ఉపయోగించడం లాజికల్. మీరు Heroku లేదా Dockerలో Cube.js బ్యాకెండ్ని హోస్ట్ చేయాలని ప్లాన్ చేస్తే, మీరు ఎక్స్ప్రెస్ టెంప్లేట్ను తరం కోసం ఉపయోగించవచ్చు. డాక్యుమెంటేషన్ ఇతరులను వివరిస్తుంది
$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena
cube.jsలో డేటాబేస్ యాక్సెస్ను కాన్ఫిగర్ చేయడానికి ఎన్విరాన్మెంట్ వేరియబుల్స్ ఉపయోగించబడతాయి. జనరేటర్ .env ఫైల్ను సృష్టిస్తుంది, దాని కోసం మీరు మీ కీలను పేర్కొనవచ్చు
ఇప్పుడు మనకు కావాలి
డైరెక్టరీలో schema
, ఫైల్ను సృష్టించండి Logs.js
. nginx కోసం ఇక్కడ ఒక ఉదాహరణ డేటా మోడల్ ఉంది:
మోడల్ కోడ్
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`
}
}
});
ఇక్కడ మనం వేరియబుల్ని ఉపయోగిస్తున్నాము
మేము డాష్బోర్డ్లో ప్రదర్శించాలనుకుంటున్న కొలమానాలు మరియు పారామితులను కూడా సెట్ చేసాము మరియు ప్రీ-అగ్రిగేషన్లను పేర్కొనండి. Cube.js ముందుగా సమగ్ర డేటాతో అదనపు పట్టికలను సృష్టిస్తుంది మరియు డేటా వచ్చినప్పుడు స్వయంచాలకంగా నవీకరించబడుతుంది. ఇది ప్రశ్నలను వేగవంతం చేయడమే కాకుండా, ఎథీనాను ఉపయోగించే ఖర్చును కూడా తగ్గిస్తుంది.
ఈ సమాచారాన్ని డేటా స్కీమా ఫైల్కి జోడిద్దాం:
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`
)
}
}
}
మేము ఈ మోడల్లో ఉపయోగించిన అన్ని కొలమానాల కోసం డేటాను ముందుగా సమగ్రపరచడం మరియు విభజనను నెలవారీగా ఉపయోగించడం అవసరమని పేర్కొంటాము.
ఇప్పుడు మనం డ్యాష్బోర్డ్ను సమీకరించవచ్చు!
Cube.js బ్యాకెండ్ అందిస్తుంది
Cube.js సర్వర్ అభ్యర్థనను అంగీకరిస్తుంది
{
"measures": ["Logs.errorCount"],
"timeDimensions": [
{
"dimension": "Logs.createdAt",
"dateRange": ["2019-01-01", "2019-01-07"],
"granularity": "day"
}
]
}
NPM ద్వారా Cube.js క్లయింట్ మరియు రియాక్ట్ కాంపోనెంట్ లైబ్రరీని ఇన్స్టాల్ చేద్దాం:
$ npm i --save @cubejs-client/core @cubejs-client/react
మేము భాగాలను దిగుమతి చేస్తాము cubejs
и QueryRenderer
డేటాను డౌన్లోడ్ చేయడానికి మరియు డాష్బోర్డ్ను సేకరించడానికి:
డాష్బోర్డ్ కోడ్
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>
);
}}
/>
)
}
డాష్బోర్డ్ మూలాలు ఇక్కడ అందుబాటులో ఉన్నాయి
మూలం: www.habr.com