عام طور پر، تجارتی مصنوعات یا ریڈی میڈ اوپن سورس متبادلات، جیسے Prometheus + Grafana، 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 میں ایک صاف بالٹی کی ضرورت ہے، جس میں کچھ اور ذخیرہ نہیں کیا جائے گا۔ یہ پہلے سے غور کرنے کے قابل ہے کہ آپ کس علاقے میں اپنی بالٹی بنائیں گے، کیونکہ ایتھینا تمام علاقوں میں دستیاب نہیں ہے۔
ایتھینا کنسول میں سرکٹ بنانا
آئیے نوشتہ جات کے لیے ایتھینا میں ایک میز بنائیں۔ اگر آپ Kinesis Firehose استعمال کرنے کا ارادہ رکھتے ہیں تو یہ لکھنے اور پڑھنے دونوں کے لیے ضروری ہے۔ ایتھینا کنسول کھولیں اور ایک ٹیبل بنائیں:
ایس کیو ایل ٹیبل کی تخلیق
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 سٹریم بنانا
Kinesis Firehose Nginx سے S3 تک موصول ہونے والے ڈیٹا کو YYYY/MM/DD/HH فارمیٹ میں ڈائریکٹریز میں تقسیم کرتے ہوئے، منتخب کردہ فارمیٹ میں لکھے گا۔ ڈیٹا پڑھتے وقت یہ کام آئے گا۔ آپ یقیناً روانی سے S3 پر براہ راست لکھ سکتے ہیں، لیکن اس صورت میں آپ کو JSON لکھنا پڑے گا، اور یہ فائلوں کے بڑے سائز کی وجہ سے ناکارہ ہے۔ مزید برآں، PrestoDB یا Athena استعمال کرتے وقت، JSON سب سے سست ڈیٹا فارمیٹ ہے۔ تو Kinesis Firehose کنسول کھولیں، "Create Delivery سٹریم" پر کلک کریں، "Delivery" فیلڈ میں "direct 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 کو Docker کنٹینر میں چلاتے ہیں، ایسی صورت میں Docker کے پاس 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 کے پاس ہے۔
آئیے اوپر کنفیگر کردہ لاگ پارسنگ کو Fluent کنفیگریشن میں شامل کریں:
<filter YOUR-NGINX-TAG.*>
@type parser
key_name log
emit_invalid_record_to_error false
<parse>
@type json
</parse>
</filter>
اور استعمال کرتے ہوئے Kinesis کو لاگ بھیج رہا ہے۔
<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>
یتینا
اگر آپ نے ہر چیز کو صحیح طریقے سے ترتیب دیا ہے، تو تھوڑی دیر کے بعد (بطور ڈیفالٹ، Kinesis ریکارڈز کو ہر 10 منٹ میں ایک بار ڈیٹا موصول ہوتا ہے) آپ کو S3 میں لاگ فائلیں نظر آنی چاہئیں۔ Kinesis Firehose کے "مانیٹرنگ" مینو میں آپ دیکھ سکتے ہیں کہ S3 میں کتنا ڈیٹا ریکارڈ کیا گیا ہے، ساتھ ہی غلطیاں بھی۔ Kinesis کردار کو S3 بالٹی تک تحریری رسائی دینا نہ بھولیں۔ اگر Kinesis کسی چیز کی تجزیہ نہیں کر سکتا ہے، تو یہ اسی بالٹی میں غلطیاں شامل کر دے گا۔
اب آپ ایتھینا میں ڈیٹا دیکھ سکتے ہیں۔ آئیے ان تازہ ترین درخواستوں کو تلاش کریں جن کے لیے ہم نے غلطیاں واپس کی ہیں:
SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;
ہر درخواست کے لیے تمام ریکارڈز کو اسکین کرنا
اب ہمارے لاگز کو پروسیس کیا گیا ہے اور ORC میں S3 میں محفوظ کیا گیا ہے، کمپریسڈ اور تجزیہ کے لیے تیار ہے۔ Kinesis Firehose نے یہاں تک کہ انہیں ہر گھنٹے کے لیے ڈائریکٹریوں میں ترتیب دیا۔ تاہم، جب تک ٹیبل کو تقسیم نہیں کیا جاتا، ایتھینا غیر معمولی استثناء کے ساتھ، ہر درخواست پر ہمہ وقتی ڈیٹا لوڈ کرے گی۔ یہ دو وجوہات کی بنا پر ایک بڑا مسئلہ ہے:
- ڈیٹا کا حجم مسلسل بڑھ رہا ہے، سوالات کو سست کر رہا ہے۔
- ایتھینا کو اسکین کیے گئے ڈیٹا کے حجم کی بنیاد پر بل کیا جاتا ہے، فی درخواست کم از کم 10 MB کے ساتھ۔
اسے ٹھیک کرنے کے لیے، ہم AWS Glue Crawler استعمال کرتے ہیں، جو S3 میں ڈیٹا کو کرال کرے گا اور Glue Metastore پر تقسیم کی معلومات لکھے گا۔ یہ ہمیں ایتھینا سے استفسار کرتے وقت پارٹیشنز کو بطور فلٹر استعمال کرنے کی اجازت دے گا، اور یہ صرف استفسار میں بیان کردہ ڈائریکٹریوں کو ہی اسکین کرے گا۔
Amazon Glue Crawler ترتیب دینا
Amazon Glue Crawler S3 بالٹی میں موجود تمام ڈیٹا کو اسکین کرتا ہے اور پارٹیشنز کے ساتھ ٹیبل بناتا ہے۔ AWS Glue کنسول سے ایک Glue Crawler بنائیں اور ایک بالٹی شامل کریں جہاں آپ ڈیٹا محفوظ کرتے ہیں۔ آپ کئی بالٹیوں کے لیے ایک کرالر استعمال کر سکتے ہیں، اس صورت میں یہ مخصوص ڈیٹا بیس میں ایسے ناموں کے ساتھ ٹیبل بنائے گا جو بالٹی کے ناموں سے مماثل ہوں۔ اگر آپ اس ڈیٹا کو باقاعدگی سے استعمال کرنے کا ارادہ رکھتے ہیں، تو اپنی ضروریات کے مطابق کرالر کے لانچ شیڈول کو ترتیب دینا یقینی بنائیں۔ ہم تمام میزوں کے لیے ایک کرالر استعمال کرتے ہیں، جو ہر گھنٹے چلتا ہے۔
تقسیم شدہ میزیں۔
کرالر کے پہلے لانچ کے بعد، ہر اسکین شدہ بالٹی کے لیے میزیں سیٹنگز میں بیان کردہ ڈیٹا بیس میں ظاہر ہونی چاہئیں۔ ایتھینا کنسول کھولیں اور 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 اسٹیک استعمال کر رہے ہیں، اس لیے Lambda کو تعیناتی کے لیے استعمال کرنا منطقی ہے۔ اگر آپ ہیروکو یا ڈوکر میں 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 کلائنٹ اور React جزو لائبریری کو انسٹال کریں:
$ 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