اتصال ASP.NET Core با OpenTelemetry
در این آموزش
این آموزش برای برنامههای ASP.NET Core و هر برنامهٔ .NET 8 به بعد است که از ILogger استفاده میکند. لاگها را با OpenTelemetry، استاندارد باز و مستقل از فروشنده، مستقیم به LogMug میفرستیم. هیچ پکیج اختصاصی LogMug لازم نیست و همین تنظیمات اگر روزی مقصد را عوض کنید هم به کار میآید.
اگر برنامه همین حالا Serilog دارد، راه سادهتر اتصال از طریق Serilog است.
گام ۱: نصب پکیجها
در پوشهٔ پروژه دو پکیج رسمی OpenTelemetry را نصب کنید:
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
پکیج اول OpenTelemetry را به سیستم لاگگیری .NET وصل میکند و دومی exporter پروتکل OTLP است؛ exporter بخشی است که داده را به مقصد میفرستد.
گام ۲: پیکربندی در Program.cs
این کد را پس از WebApplication.CreateBuilder و پیش از builder.Build() بگذارید. نام سرویس و کلید را عوض کنید:
using OpenTelemetry.Exporter;
using OpenTelemetry.Logs;
using OpenTelemetry.Resources;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddOpenTelemetry(o =>
{
o.IncludeFormattedMessage = true;
o.IncludeScopes = true;
o.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService("orders-api")
.AddAttributes(new Dictionary<string, object>
{
["deployment.environment.name"] = builder.Environment.EnvironmentName
}));
o.AddOtlpExporter(e =>
{
e.Endpoint = new Uri("https://ingest.logmug.ir/v1/logs");
e.Protocol = OtlpExportProtocol.HttpProtobuf;
e.Headers = "x-logmug-key=lm_ingest_...";
});
});
var app = builder.Build();
سه نکته که بیشترین اشتباه را دارند:
- پروتکل باید
HttpProtobufباشد. پیشفرض exporter پروتکل gRPC است و LogMug فقط OTLP روی HTTP را میپذیرد. - وقتی
Endpointرا در کد میدهید، مسیر/v1/logsباید در نشانی باشد. exporter در این حالت چیزی به نشانی اضافه نمیکند. - هدر به شکل
نام=مقداراست:x-logmug-key=lm_ingest_...، بدون فاصله و بدون دو نقطه.
IncludeFormattedMessage باعث میشود متن رندرشدهٔ پیام (با مقادیر جاگذاریشده) فرستاده شود. پارامترهای قالب پیام، مثل {OrderId}، جداگانه بهعنوان ویژگی قابلفیلتر ذخیره میشوند. deployment.environment.name در داشبورد ستون «محیط» را پر میکند و service.name ستون «سرویس» را.
کلید را در کد ننویسید
کلید ingest یک راز است. در پروداکشن آن را از پیکربندی یا متغیر محیطی بخوانید:
e.Headers = "x-logmug-key=" + builder.Configuration["LogMug:Key"];
و مقدار را با متغیر محیطی LogMug__Key یا User Secrets در محیط توسعه تنظیم کنید. راه دیگر این است که کل تنظیمات exporter را به متغیرهای محیطی استاندارد OpenTelemetry بسپارید و در کد فقط o.AddOtlpExporter(); بنویسید:
OTEL_SERVICE_NAME=orders-api
OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://ingest.logmug.ir/v1/logs
OTEL_EXPORTER_OTLP_LOGS_HEADERS=x-logmug-key=lm_ingest_...
در این حالت AddService را از کد بردارید تا OTEL_SERVICE_NAME اعمال شود.
نوشتن لاگ و خطا
از همان ILogger همیشگی استفاده کنید. استثنا را همیشه بهعنوان آرگومان اول بدهید تا نوع، پیام و stack trace آن جدا ذخیره شوند:
app.MapPost("/orders/{id:int}/pay", (int id, ILogger<Program> logger) =>
{
try
{
// ...
logger.LogInformation("Order {OrderId} paid", id);
return Results.Ok();
}
catch (Exception ex)
{
logger.LogError(ex, "Payment failed for order {OrderId}", id);
return Results.Problem();
}
});
ASP.NET Core برای هر درخواست HTTP یک Activity میسازد، پس هر لاگی که در طول درخواست نوشته شود خودکار trace_id و span_id میگیرد. در داشبورد با دکمهٔ «همهٔ لاگهای این درخواست» همهٔ آن خطوط را کنار هم میبینید؛ توضیح بیشتر در دنبال کردن یک درخواست و گروهبندی خطاها.
کنترل حجم با سطح لاگ
فیلتر سطحها همان فیلتر معمول appsettings.json است. با نام فراهمکنندهٔ OpenTelemetry میتوانید فقط برای LogMug سطح جدا بگذارید و مثلاً خروجی کنسول را پرحرفتر نگه دارید:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
},
"OpenTelemetry": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"System.Net.Http": "Warning"
}
}
}
}
سطحهای .NET خودکار نگاشت میشوند: Trace و Debug هماناند، Information به info، Warning به warn، Error به error و Critical به fatal. برای انتخاب سطح درست، مقالهٔ سطحهای لاگ را ببینید.
فقط لاگ، نه trace و metric
LogMug فقط سیگنال لاگ را میپذیرد. اگر در برنامه WithTracing یا WithMetrics هم دارید، exporter آنها را به LogMug اشاره ندهید؛ یا به ابزار دیگری بفرستید یا خاموش بگذارید. برای ساختن trace_id روی لاگها نیازی به فرستادن trace نیست.
عیبیابی
exporter خطاهایش را در لاگ داخلی OpenTelemetry مینویسد، نه در لاگ برنامه. اگر لاگی نمیرسد، اینها را به ترتیب بررسی کنید:
- هیچ درخواستی نمیرسد: معمولاً
Protocolروی پیشفرض gRPC مانده یا/v1/logsاز انتهایEndpointافتاده است. 401: کلید نادرست یا باطلشده است، یا قالب هدر اشتباه است (مثلاًx-logmug-key: ...بهجایx-logmug-key=...).400: بدنه قابل خواندن نبود؛ معمولاً یعنی exporter تنظیم پروتکل دیگری دارد یا یک پراکسی میانی بدنه را تغییر داده است.403: سهمیهٔ ماهانهٔ پلن رایگان تمام شده و تا دورهٔ بعد لاگ پذیرفته نمیشود؛ سهمیهها را ببینید.429و503: نرخ مجاز رد شده یا سرویس موقتاً شلوغ است. پاسخ هدرRetry-Afterدارد و exporter دوباره تلاش میکند؛ کاری لازم نیست مگر اینکه مداوم تکرار شود.- لاگ میرسد ولی سرویس
unknown_serviceاست:AddServiceیاOTEL_SERVICE_NAMEاعمال نشده است. - لاگهای آخر پیش از خاموش شدن برنامه گم میشوند: exporter دستهای میفرستد؛ برنامه را با خاموشی عادی (نه kill) ببندید تا صف خالی شود.
برای آشنایی عمیقتر با گزینههای لاگ در ASP.NET Core، مقالهٔ راهنمای جامع لاگ در ASP.NET Core را بخوانید.
منابع و مطالعهٔ بیشتر
- مستندات OpenTelemetry برای .NET — مرجع رسمی SDK و نمونههای پیکربندی لاگ.
- متغیرهای محیطی OTLP exporter — معنی دقیق هر متغیر
OTEL_EXPORTER_OTLP_*.
کلید پروژهتان را هنوز ندارید؟
در پلن رایگان یک پروژه بسازید؛ راهنمای اتصال با نشانی و کلید واقعی خودتان همانجا آماده است.
شروع رایگان