ارسال لاگ با HTTP و JSON: مرجع کامل API

در این آموزش
  1. endpointها
  2. احراز هویت
  3. endpoint سادهٔ JSON
  4. نام فیلدها
  5. OTLP/HTTP با JSON
  6. فشرده‌سازی و محدودیت‌ها
  7. پاسخ‌ها
  8. عیب‌یابی

این برگه مرجع کامل دریافت لاگ در LogMug است: endpointها، احراز هویت، قالب بدنه، محدودیت‌ها و کدهای پاسخ. برای اسکریپت‌های shell، cron job، زبان‌هایی بدون OpenTelemetry، یا هر جایی که کتابخانه‌ای نمی‌خواهید، endpoint سادهٔ JSON کافی است.

endpointها

مسیر کاربرد پاسخ موفق
POST https://ingest.logmug.ir/api/ingest/json JSON ساده: آرایه، یک شیء، یا NDJSON 202
POST https://ingest.logmug.ir/v1/logs OpenTelemetry OTLP/HTTP، با application/x-protobuf یا application/json 200
POST https://ingest.logmug.ir/api/events/raw سازگار با Seq (قالب CLEF)؛ همان چیزی که Serilog.Sinks.Seq می‌فرستد 201

احراز هویت

کلید ingest پروژه (lm_ingest_...) را در یکی از این هدرها بفرستید؛ هر سه معادل‌اند:

Authorization: Bearer lm_ingest_...
x-logmug-key: lm_ingest_...
X-Seq-ApiKey: lm_ingest_...

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

endpoint سادهٔ JSON

بدنه می‌تواند یک آرایهٔ JSON، یک شیء تنها، یا NDJSON (هر خط یک شیء JSON) باشد. نام سرویس را با پارامتر service در نشانی، هدر x-logmug-service، یا فیلد service داخل هر رویداد بدهید؛ اگر هیچ‌کدام نباشد، default ثبت می‌شود.

curl -X POST "https://ingest.logmug.ir/api/ingest/json?service=backup-job" \
  -H "x-logmug-key: lm_ingest_..." \
  -H "Content-Type: application/json" \
  -d '{
    "level": "error",
    "message": "backup failed",
    "env": "production",
    "host": "db-02",
    "error": { "type": "IOException", "message": "No space left on device", "stack": "..." },
    "disk": { "mount": "/data", "free_mb": 0 }
  }'

NDJSON از یک فایل:

curl -X POST "https://ingest.logmug.ir/api/ingest/json?service=importer" \
  -H "Authorization: Bearer lm_ingest_..." \
  -H "Content-Type: application/x-ndjson" \
  --data-binary @events.ndjson

از --data-binary استفاده کنید نه -d؛ -d خط‌های جدید را حذف می‌کند و NDJSON خراب می‌شود.

نام فیلدها

این نام‌ها شناخته می‌شوند و به ستون‌های اصلی می‌روند:

ستون نام‌های پذیرفته توضیح
زمان timestamp، time، @timestamp، ts رشتهٔ ISO 8601 یا عدد epoch به ثانیه، میلی‌ثانیه، میکروثانیه یا نانوثانیه (از روی اندازهٔ عدد تشخیص داده می‌شود). اگر نباشد، زمان دریافت.
سطح level، severity، lvl trace، debug، info، warn، error، fatal؛ نام‌هایی مثل Information، Warning و Critical هم نگاشت می‌شوند.
متن message، msg، body متن اصلی لاگ.
سرویس service، app بر پارامتر نشانی مقدم است.
محیط environment، env مثلاً production یا staging.
میزبان host، hostname نام سرور یا کانتینر.
ردیابی trace_id، span_id، traceparent traceparent با قالب W3C (00-<trace>-<span>-01) هر دو شناسه را می‌دهد.
خطا exception، error رشته (متن کامل استثنا) یا شیء با type، message و stack.

هر فیلد دیگری ویژگی قابل‌فیلتر می‌شود. اشیای تودرتو با نقطه تخت می‌شوند؛ در مثال بالا {"disk":{"mount":"/data"}} به ویژگی disk.mount تبدیل می‌شود. اگر سطح داده نشود ولی خطا باشد، سطح error و در غیر این صورت info ثبت می‌شود.

OTLP/HTTP با JSON

اگر کتابخانهٔ OpenTelemetry دارید، از آن استفاده کنید (زبان‌های دیگر). برای آزمایش دستی، یک بدنهٔ کمینه:

curl -X POST "https://ingest.logmug.ir/v1/logs" \
  -H "x-logmug-key: lm_ingest_..." \
  -H "Content-Type: application/json" \
  -d '{"resourceLogs":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"billing"}}]},"scopeLogs":[{"logRecords":[{"severityNumber":17,"severityText":"ERROR","body":{"stringValue":"payment failed"}}]}]}]}'

از resource، مقدار service.name، deployment.environment.name (یا deployment.environment) و host.name به ستون‌های سرویس، محیط و میزبان می‌روند. ویژگی‌های exception.type، exception.message و exception.stacktrace جدا ذخیره می‌شوند. فقط سیگنال لاگ پذیرفته می‌شود؛ trace و metric نه.

فشرده‌سازی و محدودیت‌ها

  • بدنه را می‌توانید با gzip، deflate یا br فشرده کنید و هدر Content-Encoding را بفرستید:
    gzip -c events.ndjson | curl -X POST "https://ingest.logmug.ir/api/ingest/json?service=importer" \
      -H "x-logmug-key: lm_ingest_..." \
      -H "Content-Encoding: gzip" \
      --data-binary @-
  • سقف هر درخواست ۱۰ مگابایت است. دسته‌های بزرگ‌تر را تقسیم کنید.
  • هر خط (متن یا stack trace) بیش از ۶۴ کیلوبایت بریده و با …[truncated] علامت‌گذاری می‌شود.
  • زمانی که بیش از یک ساعت جلوتر از حال باشد، با زمان دریافت جایگزین می‌شود (ساعت سرور اشتباه است، نه رویداد از آینده).
  • لاگی که زمانش قدیمی‌تر از مدت نگه‌داری پلن باشد پذیرفته نمی‌شود و در شمارش rejected می‌آید.

سهمیه‌ها و مدت نگه‌داری هر پلن در سهمیه، مدت نگه‌داری و محدودیت‌ها آمده است.

پاسخ‌ها

endpoint سادهٔ JSON تعداد پذیرفته‌ها و ردشده‌ها را برمی‌گرداند. خطوطی که JSON معتبر نیستند (در NDJSON) یا خیلی قدیمی‌اند جزو rejected شمرده می‌شوند و بقیهٔ دسته ثبت می‌شود:

HTTP/1.1 202 Accepted
{"accepted":118,"rejected":2}

عیب‌یابی

کد معنی چه کنیم
401 کلید نیست، نادرست است یا باطل شده هدر و مقدار کلید را بررسی کنید؛ کلید باطل‌شده حداکثر ظرف یک دقیقه رد می‌شود.
400 بدنه خراب است یا از حالت فشرده باز نشد اعتبار JSON؛ یکی بودن Content-Encoding با فشرده‌سازی واقعی.
403 سهمیهٔ ماهانهٔ پلن رایگان تمام شده دوباره نفرستید؛ تا دورهٔ بعد پذیرفته نمی‌شود، مگر با ارتقای پلن.
413 بدنه بزرگ‌تر از سقف دسته را کوچک‌تر کنید.
429 عبور از نرخ مجاز به اندازهٔ Retry-After (ثانیه) صبر کنید و همان دسته را دوباره بفرستید.
503 شلوغی موقت پس از Retry-After دوباره تلاش کنید، ترجیحاً با فاصلهٔ رو به افزایش.

در کد خودتان فقط 429 و 503 (و خطاهای شبکه) را دوباره تلاش کنید؛ تکرار 400، 401 و 403 نتیجه را عوض نمی‌کند. بدنهٔ پاسخ خطا یک شیء {"error":"..."} با توضیح کوتاه است.

کلید پروژه‌تان را هنوز ندارید؟

در پلن رایگان یک پروژه بسازید؛ راهنمای اتصال با نشانی و کلید واقعی خودتان همان‌جا آماده است.

شروع رایگان