خانه/مقالات/اسکریپینگ: لاگ و هشدار با ELK
برنامه نویسی
داده‌کاوی
برگشت به مقاله‌ها

اسکریپینگ: لاگ و هشدار با ELK

اسکریپینگ: لاگ و هشدار با ELK
این مقاله یک راهنمای عملی برای مرکزی‌سازی لاگ‌های وب اسکریپر پایتون با ELK ارائه می‌دهد: ثبت لاگ به‌صورت JSON، پیکربندی Logstash برای خواندن فایل لاگ، ایجاد ایندکس و مصورسازی در Kibana و ساخت قوانین هشدار. با دنبال‌کردن این مراحل می‌توانید خطاها را به‌صورت بلادرنگ تشخیص دهید، از مصرف منابع آگاه باشید و سیستم را برای مقیاس‌پذیری آماده کنید.
آسان اسکریپ آسان اسکریپ
1405-06-26

آسان اسکریپ را در گوگل منبع ترجیحی کن تا مطالب ما زودتر و پررنگ‌تر برایت نمایش داده شود. افزودن از تنظیمات گوگل

مقدمه

در این راهنما عملی و فنی، به نحوه طراحی یک سیستم لاگ مرکزی برای پروژه‌های وب اسکریپینگ می‌پردازیم. هدف این است که بعد از خواندن این مقاله بتوانید لاگ‌های اسکریپرهای پایتون خود را به ELK منتقل کنید، در Kibana آن‌ها را فیلتر و مصورسازی کنید و برای خطاهای بحرانی هشدار اتوماتیک بسازید. فرض می‌کنیم خواننده آشنایی متوسط با Python و مفاهیم پایه لاگینگ دارد.

چرا لاگ متمرکز برای اسکریپینگ مهم است

یک وب اسکریپر در طول اجرا انواع پیام‌ها تولید می‌کند: دیباگ، اطلاعات، هشدار و خطا. اگر این پیام‌ها در فایل‌های متنی پراکنده بمانند، پیدا کردن علت یک شکست می‌تواند ساعت‌ها طول بکشد. با مرکزی‌سازی لاگ‌ها در Elasticsearch و استفاده از Kibana برای جستجو و مصورسازی، زمان تشخیص و حل مشکل به طور چشمگیری کاهش می‌یابد.

  • قابلیت جستجوی سریع: پیدا کردن رخدادها بر اساس فیلدها (مثلاً level، url) فوری است.
  • مصورسازی: نمودارها و داشبوردها برای روند خطاها یا تاخیرها مفیدند.
  • هشدارها: با قاعده‌گذاری، به محض وقوع خطا ایمیل یا اکشن‌های دیگر دریافت می‌کنید.

نقشه راه کلی

مراحل عملی که پوشش می‌دهیم:

  • نصب و راه‌اندازی محلی Elasticsearch، Logstash و Kibana
  • نوشتن لاگ JSON از اسکریپر پایتون
  • پیکربندی Logstash برای خواندن فایل لاگ و ارسال به Elasticsearch
  • ایجاد index و Data View در Kibana و ساخت ویژوالیزیشن
  • ساخت قواعد و هشدارهای اتوماتیک
  • ملاحظات مقیاس‌پذیری، امنیت و خطا‎یابی

راه‌اندازی محلی ELK — دستورات پایه

در سیستم‌های مبتنی بر اوبونتو یا WSL می‌توانید با دستورات زیر به سرعت سرویس‌ها را نصب و اجرا کنید. نکته مهم: همیشه از مخازن رسمی و کلیدهای امضای معتبر استفاده کنید و در محیط تولید (production) از تنظیمات امنیتی قوی‌تر بهره ببرید.

sudo apt update
sudo apt-get install elasticsearch
sudo systemctl start elasticsearch
sudo systemctl enable elasticsearch
# ایجاد یا بازنشانی پسورد برای کاربر 'elastic'
sudo /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic

توضیح بخش‌ها:

  • ورودی: دستورات بالا را در شِل اجرا می‌کنید.
  • خروجی: سرویس Elasticsearch نصب و در حالت اجرا قرار می‌گیرد؛ دستور بازنشانی پسورد، پسورد جدید را می‌سازد.
  • نکته امنیتی: پسورد تولیدشده را در فایل‌های کانفیگ متن‌باز نگذارید؛ از Secrets Manager یا متغیرهای محیطی استفاده کنید.

نصب و راه‌اندازی Logstash و Kibana

مراحل نصب Logstash مشابه Elasticsearch است؛ پس از نصب، Logstash را به عنوان سرویس اجرا کنید. برای Kibana نیز پس از نصب باید enrollment token یا رمز ورود مناسب ایجاد و در دیالوگ‌های راه‌اندازی وارد کنید.

sudo apt-get install logstash
sudo systemctl start logstash
sudo systemctl enable logstash

sudo apt-get install kibana
sudo systemctl start kibana
sudo systemctl enable kibana
# تولید enrollment token برای اتصال Kibana به Elasticsearch
sudo /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token --scope kibana

توضیح: اجرای این دستورات Kibana را روی پورت پیش‌فرض 5601 قرار می‌دهد. برای دسترسی از راه دور، پیکربندی‌های شبکه و TLS را بررسی کنید.

نوشتن لاگ ساختارمند در اسکریپر پایتون

برای اینکه Logstash بتواند لاگ‌ها را به‌راحتی پارس کند، لاگ‌های JSON بهترین انتخاب هستند. در ادامه یک نمونه ساده از یک اسکریپر با JsonFormatter و ذخیره در فایل را می‌بینید.

import logging
import json
import os
import requests
from bs4 import BeautifulSoup

os.makedirs('logs', exist_ok=True)

class JsonFormatter(logging.Formatter):
    def format(self, record):
        entry = {
            'timestamp': self.formatTime(record, self.datefmt),
            'level': record.levelname,
            'message': record.getMessage(),
            'module': record.module,
            'function': record.funcName,
            'line': record.lineno,
        }
        return json.dumps(entry)

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
file_handler = logging.FileHandler('logs/scraper.log', mode='a', encoding='utf-8')
file_handler.setFormatter(JsonFormatter())
logger.addHandler(file_handler)

logger.info(json.dumps({'message': 'Web scraper initialized.'}))

def scrape_page(url):
    response = requests.get(url, timeout=10)
    try:
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')
        quotes = soup.find_all(class_='quote')
        for q in quotes:
            log_data = {'quote': q.text.strip(), 'url': url}
            logger.info(json.dumps(log_data))
    except Exception as e:
        logger.error(json.dumps({'error': str(e), 'url': url}))
    finally:
        logger.info(json.dumps({'message': f'Finished Scraping {url}'}))

if __name__ == '__main__':
    url = 'https://quotes.toscrape.com'
    # برای شبیه‌سازی خطا می‌توانید URL را به یک آدرس با خطا تغییر دهید
    scrape_page(url)

توضیحات کد (ورودی/خروجی و نقش توابع):

  • ورودی: آدرس صفحه که به تابع scrape_page ارسال می‌شود.
  • خروجی: فایل لاگ logs/scraper.log شامل رشته‌های JSON که هر رکورد یک رویداد است.
  • JsonFormatter: ساختار لاگ را به JSON تبدیل می‌کند تا Logstash بتواند codec=json را روی آن اعمال کند.
  • در try/except/finally ما وضعیت موفق، خطا و پایان کار را با لاگ ثبت می‌کنیم.

پیکربندی Logstash برای خواندن فایل لاگ

یک فایل پیکربندی ساده Logstash که فایل لاگ JSON را می‌خواند و به Elasticsearch می‌فرستد به شکل زیر است. مسیر فایل و نام ایندکس را با مقادیر محیطی خود جایگزین کنید. هرگز پسورد یا توکن را در کد متن‌باز ذخیره نکنید؛ از متغیر محیطی یا مکانیزم امن استفاده کنید.

input {
  file {
    path => '/path/to/your/project/logs/scraper.log'
    start_position => 'beginning'
    sincedb_path => '/dev/null'
    codec => 'json'
  }
}

filter {
  mutate { add_field => { '[@metadata][index]' => 'scraper_logs' } }
}

output {
  elasticsearch {
    hosts => ['https://localhost:9200']
    user => 'elastic'
    password => 'YOUR_ELASTIC_PASSWORD'
    index => '%{[@metadata][index]}'
    ssl_certificate_verification => false
  }
  stdout { codec => rubydebug }
}

نکات عملی:

  • path: آدرسی که اسکریپر لاگ می‌نویسد.
  • codec => 'json': به Logstash می‌گوید که هر خط فایل یک شیء JSON است.
  • برای تولید در مقیاس بالا از TLS و اعتبارسنجی گواهی‌نامه استفاده کنید (در مثال بالا ssl_certificate_verification خاموش است فقط برای محیط محلی).

تحلیل و فیلتر در Kibana

بعد از اینکه Logstash داده را به Elasticsearch فرستاد، در Kibana باید یک Index Pattern ایجاد کنید (مثلاً scraper_logs*). از بخش Discover می‌توانید روی فیلد level فیلتر بگذارید، یا با ایجاد Visualization روند خطاها را رصد کنید.

نکته فنی: اگر لاگ‌ها نمایش داده نمی‌شوند، زمان بازه (time range) را روی "All time" یا بازه مناسب قرار دهید و بررسی کنید که mapping فیلدها به درستی (مثلاً رشته یا keyword) تنظیم شده باشد.

ساخت هشدار اتوماتیک برای خطاها

در Kibana می‌توانید با استفاده از Rules یک قاعده بسازید که تعداد رخدادهای با level:ERROR را در بازه‌ای مثل 5 دقیقه چک کند. اگر بالای صفر بود، اقدام مورد نظر اجرا می‌شود (مثلاً ارسال ایمیل یا نوشتن در یک ایندکس هشدار).

پیش‌نیاز: برای ارسال امن هشدارها بعضی اکشن‌ها نیاز به ایجاد encryption keys و ثبت connector دارند. مسیر کلی:

  • تولید کلیدها با ابزار kibana-encryption-keys (با دسترسی sudo)
  • افزودن کلید به فایل /etc/kibana/kibana.yml
  • ریستارت Kibana و ایجاد Rule در Stack Management

مسائل عملی، مجوزها و منابع

مواردی که در هنگام راه‌اندازی باید به آن‌ها توجه کنید:

  • محدودیت منابع: Elasticsearch و Logstash از RAM و CPU سنگینی استفاده می‌کنند. در لپ‌تاپ محلی مقادیر حافظه را با systemctl و تنظیمات سرویس محدود کنید.
  • دسترسی فایل: Logstash باید حق خواندن فایل لاگ را داشته باشد. اگر اسکریپر با کاربر دیگری می‌نویسد، مالکیت و گروه فایل را طوری تنظیم کنید که Logstash به آن دسترسی داشته باشد.
  • امنیت: پسوردها و توکن‌ها در متغیرهای محیطی یا vault نگهداری شوند؛ ارتباطات بین سرویس‌ها TLS داشته باشند.
  • نویز لاگ: فقط پیام‌های ضروری را لاگ کنید تا حجم داده در ES و هزینه ذخیره کاهش یابد؛ برای پیام‌های دیباگ از سطح DEBUG استفاده کنید و در پروفایل تولید غیرفعالش کنید.

افزایش مقیاس و بهترین شیوه‌ها

برای رشد سیستم به موارد زیر توجه کنید:

  • کانتینری شدن: با Docker می‌توانید پشته ELK را بسته‌بندی و به راحتی در سرور یا کلاستر مستقر کنید.
  • تفکیک ایندکس: لاگ‌ها را بر اساس پروژه یا نوع لاگ به ایندکس‌های جداگانه ارسال کنید تا جستجو و نگهداری ساده‌تر شود.
  • سازمان‌دهی فیلدها: از فیلدهای ساخت‌یافته (timestamp, level, url, error_code) استفاده کنید تا کوئری‌ها سریع‌تر و مؤثرتر باشند.
  • یکپارچه‌سازی با مانیتورینگ متریک: در کنار لاگ‌ها از ابزارهایی مثل Prometheus/Grafana برای متریک‌های عملکرد استفاده کنید تا تصویر کامل‌تری از سلامت اسکریپرها داشته باشید.

رفع اشکال رایج

چند مشکل متداول و راه‌حل آنها:

  • Logstash فایل را نمی‌خواند: بررسی کنید sincedb_path و permission فایل صحیح باشد. همچنین از شروع موقعیت به 'beginning' استفاده کنید اگر می‌خواهید تمام لاگ‌ها را دوباره بخوانید.
  • Mapping اشتباه در Elasticsearch: اگر فیلدها به عنوان رشته بلند ذخیره شدند و قصد aggregation دارید، از فیلدهای keyword یا mapping صریح استفاده کنید.
  • مصرف منابع بالا: تعداد shards، حافظه JVM و محدودیت systemd را بررسی و تنظیم کنید.

جمع‌بندی

با پیاده‌سازی لاگ JSON در اسکریپر پایتون، ارسال آن‌ها از طریق Logstash و مصورسازی در Kibana، می‌توانید از رخدادهای خطا در اسکریپینگ باخبر شوید و واکنش سریع داشته باشید. نکات کلیدی: لاگ ساختارمند بنویسید، از امنیت و رمزنگاری غافل نشوید، و برای تولید از پیکربندی‌های بهینه منابع و مدیریت ایندکس بهره ببرید.

پیشنهاد عملی: ابتدا این جریان را روی یک پروژه کوچک محلی تست کنید، سپس با Docker و تنظیمات منابع به محیط تولید ارتقا دهید. همچنین در صورت استفاده از سرویس‌های ثالث یا proxy، لاگ‌های مربوط را هم به همین پشته متمرکز کنید تا دید کامل‌تری به عملکرد اسکریپرها داشته باشید.

آسان اسکریپ را در گوگل به‌عنوان منبع ترجیحی انتخاب کن

مقاله‌های جدید ما زودتر و پررنگ‌تر در نتایج گوگل و Discover برایت نمایش داده می‌شود. افزودن از تنظیمات گوگل