﻿# راهنمای جامع نصب و راه‌اندازی پکیج‌های Basir Observability SDK
این سند راهنمای گام‌به‌گام و عملی برای توسعه‌دهندگانی است که می‌خواهند پکیج‌های سازمانی **Basir Observability SDK** را در پروژه‌های **کاملاً جدید و خام** (Clean / Fresh Projects) پیاده‌سازی کنند.

این راهنما بر این فرض استوار است که پروژه هدف هیچ‌گونه کد یا پیکربندی قبلی از OpenTelemetry ندارد.

---
## فهرست راهنماها
1. [مفاهیم کلیدی و معماری ارتباطی](#مفاهیم-کلیدی-و-معماری-ارتباطی)

2. [راهنمای ۱: پیاده‌سازی در ASP.NET Core (.NET 8+)](#راهنمای-۱-پیادهسازی-در-aspnet-core-net-8)

3. [راهنمای ۲: پیاده‌سازی در ASP.NET Framework 4.8 (Web API 2 و MVC 5)](#راهنمای-۲-پیادهسازی-در-aspnet-framework-48-web-api-2-و-mvc-5)

4. [راهنمای ۳: پیاده‌سازی در فرانت‌اند AngularJS 1.x](#راهنمای-۳-پیادهسازی-در-فرانتاند-angularjs-1x)

5. [راهنمای ۴: پیاده‌سازی در Blazor WebAssembly (.NET 8+)](#راهنمای-۴-پیادهسازی-در-blazor-webassembly-net-8)

6. [عیب‌یابی جامع و خطاهای پرتکرار (Troubleshooting)](#عیبیابی-جامع-و-خطاهای-پرتکرار-troubleshooting)

---
## مفاهیم کلیدی و معماری ارتباطی
### ۱. اصل ارسال محلی (Local Collector)
در معماری سازمانی بصیر، برنامه‌های بک‌اند **هرگز** به‌صورت مستقیم با SigNoz یا گیت‌وی لینوکسی ارتباط برقرار نمی‌کنند و هیچ اطلاعاتی از قبیل کلمه عبور، توکن احراز هویت یا گواهی‌های mTLS در برنامه قرار نمی‌گیرد.

همه برنامه‌ها تلمتری خود را با پروتکل OTLP/HTTP protobuf به آدرس محلی ارسال می‌کنند:

```text
http://127.0.0.1:4318
```

سرویس **Local OpenTelemetry Collector** (سرویس ویندوزی otelcol-contrib) وظیفه دریافت تلمتری در پورت 4318 و انتقال امن آن از طریق mTLS به گیت‌وی مرکزی و سپس SigNoz را بر عهده دارد.

```text
[Web App / API]
       │
       │ OTLP/HTTP
       ▼
[Local Collector]
[127.0.0.1:4318]
       │
       │ mTLS
       ▼
[Linux Gateway]
       │
       ▼
    [SigNoz]
```

### ۲. پل ارتباطی مرورگر (Browser Bridge)
برنامه‌های مرورگر (AngularJS و Blazor WASM) در دستگاه کلاینت/کاربر اجرا می‌شوند؛ بنابراین آدرس 127.0.0.1 در مرورگر به رایانه کاربر نهایی اشاره می‌کند، نه سرور.

برای حل این مشکل، کلاینت‌های تحت وب داده‌های خود را با استاندارد OTLP به اندپوینت هم‌مبدأ (Same-Origin) در سرور بک‌اند ارسال می‌کنند:

```text
/basir/otel/v1/traces
```

بک‌اند سرور از طریق قابلیت **Basir Browser Bridge** این داده‌ها را دریافت کرده و به http://127.0.0.1:4318 منتقل می‌نماید.

### ۳. عدم نیاز به نصب مستقیم پکیج Core
پکیج Basir.Observability.Core یک وابستگی زیرساختی و گذرا (Transitive Dependency) است. برنامه‌های کاربردی **نباید** این پکیج را به‌صورت مستقیم نصب کنند. نصب پکیج مختص استک مورد نظر (مانند Basir.Observability.AspNetCore یا Basir.Observability.AspNetFramework) به‌طور خودکار این وابستگی را فراهم می‌کند.

---
## راهنمای ۱: پیاده‌سازی در ASP.NET Core (.NET 8+)
پکیج مورد استفاده: **Basir.Observability.AspNetCore**

### مرحله ۱: ایجاد پروژه جدید
یک پروژه جدید Web API بسازید:

```bash
dotnet new webapi -n MyCompany.OrderApi
cd MyCompany.OrderApi
```

### مرحله ۲: تنظیم منبع پکیج و نصب
اگر از منبع محلی یا مخزن سازمانی NuGet استفاده می‌کنید، آن را در فایل `NuGet.config` تعریف نمایید:

```xml
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="BasirInternal" value="http://nuget.corp.local/v3/index.json" />
  </packageSources>
</configuration>
```

سپس پکیج را نصب کنید:

```bash
dotnet add package Basir.Observability.AspNetCore
```

> **توجه:** نیازی به نصب `Basir.Observability.Core` یا پکیج‌های OpenTelemetry به‌صورت دستی نیست.

### مرحله ۳: تنظیم فایل Appsettings.json
حداقل پیکربندی لازم برای راه‌اندازی:

```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "BasirObservability": {
    "ServiceName": "order-api",
    "ServiceNamespace": "commerce",
    "Environment": "Development"
  }
}
```

> **نکته**: مقدار CollectorEndpoint به‌صورت خودکار روی http://127.0.0.1:4318 تنظیم شده است و نیازی به بازنویسی آن در حالت عادی نیست.

### مرحله ۴: تغییرات فایل Program.cs
فایل Program.cs را به‌صورت زیر ویرایش نمایید:

```csharp
using Basir.Observability.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
// ۱. افزودن سیستم تلمتری بصیر با استفاده از کانفیگ
builder.Services.AddBasirObservability(builder.Configuration);
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
// ۲. فعال‌سازی پل ارتباطی مرورگر (تنها در صورتی که به فرانت‌اند تحت وب متصل است)
app.MapBasirObservabilityBridge();
app.MapControllers();
app.Run();
```

### مرحله ۵: قابلیت‌های فعال به‌صورت خودکار
پس از راه‌اندازی بالا، بدون نوشتن هیچ کد اضافه‌ای، موارد زیر خودکار فعال می‌شوند:

- ردیابی تمامی درخواست‌های HTTP ورودی (مدت زمان، مسیر، کد وضعیت)

- ردیابی تماس‌های خروجی با HttpClient و ارسال هدر W3C `traceparent`

- ردیابی پرس‌وجوهای پایگاه داده SQL (Microsoft.Data.SqlClient)

- متریک‌های پروسس (مصرف CPU، حافظه فیزیکی و مجازی)

- متریک‌های Runtime دات‌نت (GC، ThreadPool، استثناها)

- انتقال لاگ‌های ساختاریافته ILogger به همراه همبستگی TraceId/SpanId

### مرحله ۶: ایجاد اسپن سفارشی (Custom Span)
برای ردیابی لاجیک بیزینسی اختصاصی:

```csharp
using System.Diagnostics;
public class OrderProcessor
{
    // نام سورس را مطابق بخش کانفیگ تنظیم کنید
    private static readonly ActivitySource Source = new("MyCompany.OrderApi");
    public void ProcessOrder(int orderId, decimal total)
    {
        using var activity = Source.StartActivity("order.process");
        activity?.SetTag("order.id", orderId);
        activity?.SetTag("order.amount", total);
        try
        {
            // پردازش سفارش...
            activity?.SetStatus(ActivityStatusCode.Ok);
        }
        catch (Exception ex)
        {
            activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
            activity?.RecordException(ex);
            throw;
        }
    }
}
```

### مرحله ۷: ایجاد متریک سفارشی (Custom Metric)
برای جمع‌آوری آمارهای بیزینسی اختصاصی:

```csharp
using System.Diagnostics.Metrics;
public class OrderMetrics
{
    private static readonly Meter Meter = new("MyCompany.OrderApi");
    private static readonly Counter<long> OrdersCreated = Meter.CreateCounter<long>(
        "orders.created.count",
        description: "تعداد سفارشات ایجاد شده");
    public static void IncrementOrders(string orderType)
    {
        OrdersCreated.Add(1, new KeyValuePair<string, object>("order.type", orderType));
    }
}
```

### مرحله ۸: معرفی منابع سفارشی در کانفیگ
در Appsettings.json نام ActivitySource و Meter اختصاصی خود را اضافه کنید تا پکیج آن‌ها را مانیتور کند:

```json
{
  "BasirObservability": {
    "ServiceName": "order-api",
    "Tracing": {
      "AdditionalActivitySources": [ "MyCompany.OrderApi" ]
    },
    "Metrics": {
      "AdditionalMeters": [ "MyCompany.OrderApi" ]
    }
  }
}
```

### مرحله ۹: اجرا و بررسی
برنامه را اجرا کنید:

```bash
dotnet run
```

یک درخواست تستی به برنامه ارسال کرده و بررسی نمایید پورت 4318 روی سیستم فعال باشد:

```powershell
Test-NetConnection -ComputerName 127.0.0.1 -Port 4318
```

### چک‌لیست نصب ASP.NET Core
- [ ] پکیج Basir.Observability.AspNetCore نصب شد.

- [ ] متد Builder.Services.AddBasirObservability صدا زده شد.

- [ ] بخش BasirObservability:ServiceName در کانفیگ مشخص شد.

- [ ] سرویس لوکال کالکتور روی پورت 4318 گوش می‌دهد.

- [ ] اسپن‌های درخواست‌ها در SigNoz با نام سرویس مربوطه ظاهر می‌شوند.

---
## راهنمای ۲: پیاده‌سازی در ASP.NET Framework 4.8 (Web API 2 و MVC 5)
پکیج مورد استفاده: **Basir.Observability.AspNetFramework**

### مرحله ۱: نصب پکیج در پروژه .NET Framework 4.8
در Visual Studio پنجره **Package Manager Console** را باز کرده و دستور زیر را اجرا نمایید:

```powershell
Install-Package Basir.Observability.AspNetFramework
```

### مرحله ۲: راه‌اندازی در Global.asax.cs
در فایل Global.asax.cs پکیج بصیر را در زمان شروع و توقف برنامه صدا بزنید:

```csharp
using System;
using System.Web;
using System.Web.Http;
using System.Web.Routing;
using Basir.Observability.AspNetFramework;
using Basir.Observability.AspNetFramework.BrowserBridge;
namespace MyFrameworkApp
{
    public class Global : HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            // ۱. شروع زیرساخت مانیتورینگ بصیر
            BasirObservability.Start();
            // ۲. ثبت پل ارتباطی مرورگر (اختیاری: اگر برنامه دارای کلاینت AngularJS/Blazor است)
            RouteTable.Routes.MapBasirObservabilityBridge();
            // سایر تنظیمات روتینگ پروژه
            GlobalConfiguration.Configure(WebApiConfig.Register);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
        protected void Application_End(object sender, EventArgs e)
        {
            // بستن اصولی لاگرها و پرووایدرهای تلمتری
            BasirObservability.Stop();
        }
    }
}
```

> **توجه برای پروژه‌های MVC 5**: متد BasirObservability.Start() و Stop() دقیقاً در Global.asax.cs پروژه‌های MVC 5 نیز به همین شکل قرار می‌گیرند.

### مرحله ۳: تنظیمات Web.config (بسیار مهم)
فایل Web.config را باز کرده و دو بخش زیر را تنظیم نمایید:

#### ۱. تنظیمات AppSettings:
```xml
<configuration>
  <appSettings>
    <add key="basir:ServiceName" value="customer-api" />
    <add key="basir:Environment" value="Development" />
    <add key="basir:Tracing:AdditionalActivitySources" value="CustomerServiceSource" />
    <add key="basir:Metrics:AdditionalMeters" value="CustomerServiceMeter" />
  </appSettings>
```

#### ۲. رجیستر کردن ماژول TelemetryHttpModule (حیاتی):
در تگ `<system.webServer>` ماژول زیر را ثبت کنید. **بدون این ماژول، درخواست‌های HTTP ورودی در ASP.NET Classic ردیابی نخواهند شد**:

```xml
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="TelemetryHttpModule" />
      <add name="TelemetryHttpModule"
           type="OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule, OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule"
           preCondition="integratedMode,managedHandler" />
    </modules>
  </system.webServer>
</configuration>
```

### مرحله ۴: ارسال اسپن و لاگ سفارشی
```csharp
using System.Diagnostics;
using Basir.Observability.AspNetFramework;
using Microsoft.Extensions.Logging;
public class CustomerService
{
    private static readonly ActivitySource Source = new ActivitySource("CustomerServiceSource");
    private readonly ILogger _logger = BasirObservability.LoggerFactory.CreateLogger<CustomerService>();
    public void RegisterCustomer(string name)
    {
        using (var activity = Source.StartActivity("customer.register"))
        {
            if (activity != null)
            {
                activity.SetTag("customer.name", name);
            }
            _logger.LogInformation("در حال ثبت مشتری جدید: {CustomerName}", name);
            // عملیات دیتابیس یا سرویس...
        }
    }
}
```

### چک‌لیست نصب ASP.NET Framework 4.8
- [ ] پکیج Basir.Observability.AspNetFramework نصب شد.

- [ ] دستور BasirObservability.Start() در `Application_Start` قرار دارد.

- [ ] ماژول TelemetryHttpModule در `<system.webServer>`/`<modules>` ثبت شده است.

- [ ] کلید Basir:ServiceName در AppSettings درج شده است.

- [ ] درخواست‌های ورودی، SQL و HttpClient در لاگ یا SigNoz ثبت می‌شوند.

---
## راهنمای ۳: پیاده‌سازی در فرانت‌اند AngularJS 1.x
پکیج مورد استفاده: **@basir/observability-angularjs**

پروژه‌های سنتی AngularJS فاقد سیستم‌های بیلد مدرن مانند Webpack یا Vite هستند. این پکیج دارای یک نسخه کامپایل‌شده آماده به‌صورت UMD است که مستقیماً با تگ `<script>` لود می‌شود.

### مرحله ۱: دریافت فایل توزیع پکیج (Dist File)
فایل باندل آماده:

```text
basir-observability-angularjs.min.js
```

را در پوشه اسکریپت‌های پروژه (مثلاً Scripts/vendor/) قرار دهید.

### مرحله ۲: افزودن اسکریپت به index.html
فایل اسکریپت را بعد از کتابخانه اصلی Angular.min.js و قبل از کدهای برنامه خود لود کنید:

```html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta charset="utf-8">
    <title>سامانه تحت وب</title>
</head>
<body>
    <div ng-view></div>
    <!-- ۱. فریم‌ورک اصلی آنگولار -->
    <script src="Scripts/vendor/angular.min.js"></script>
    <script src="Scripts/vendor/angular-route.min.js"></script>
    <!-- ۲. پکیج مانیتورینگ بصیر -->
    <script src="Scripts/vendor/basir-observability-angularjs.min.js"></script>
    <!-- ۳. اسکریپت‌های برنامه -->
    <script src="Scripts/app.js"></script>
    <script src="Scripts/controllers/main.controller.js"></script>
</body>
</html>
```

### مرحله ۳: ثبت ماژول در App.js
ماژول Basir.observability را به وابستگی‌های برنامه بیفزایید و پرووایدر آن را کانفیگ کنید:

```javascript
(function () {
  'use strict';
  angular.module('myApp', ['ngRoute', 'basir.observability'])
    .config(['$routeProvider', 'basirObservabilityProvider', function ($routeProvider, basirObservabilityProvider) {
      // تنظیم پکیج مانیتورینگ بصیر
      basirObservabilityProvider.configure({
        serviceName: 'sales-portal',                  // هویت خروجی به sales-portal.web تبدیل می‌شود
        bridgeEndpoint: '/basir/otel/v1/traces',      // مسیر پل روی همین سرور
        instrumentRoutes: true,                       // ردیابی ناوبری صفحات
        instrumentHttp: true,                         // ردیابی خودکار تماس‌های $http
        captureExceptions: true                       // ثبت خطاهای گزارش‌نشده
      });
      $routeProvider
        .when('/orders', {
          templateUrl: 'views/orders.html',
          controller: 'OrdersController',
          controllerAs: 'vm'
        })
        .otherwise({ redirectTo: '/orders' });
    }]);
})();
```

### مرحله ۴: فعال‌سازی پل ارتباطی در بک‌اند سرور
همانطور که در راهنماهای ۱ و ۲ توضیح داده شد، در سرور میزبانی‌کننده (ASP.NET Core یا ASP.NET 4.8) پل ارتباطی مرورگر را فعال کنید:

- در ASP.NET Core: دستور App.MapBasirObservabilityBridge();

- در ASP.NET 4.8: دستور RouteTable.Routes.MapBasirObservabilityBridge(); و کلید `<add key="basir:BrowserBridge:Enabled" value="true" />`

### مرحله ۵: ثبت اسپن سفارشی در کنترلر آنگولار
اگر مایلید یک عملیات کاربری خاص را دستی ردیابی کنید:

```javascript
angular.module('myApp').controller('OrdersController', ['basirObservability', '$http', function (basirObservability, $http) {
  var vm = this;
  vm.submitOrder = function () {
    var span = basirObservability.startSpan('order.checkout_click');
    $http.post('/api/orders', { amount: 150000 }).then(function (res) {
      if (span) {
        span.setAttribute('order.id', res.data.id);
        span.setStatus({ code: 1 }); // OK
        span.end();
      }
    }).catch(function (err) {
      if (span) {
        span.recordException(err);
        span.setStatus({ code: 2, message: err.statusText }); // ERROR
        span.end();
      }
    });
  };
}]);
```

### چک‌لیست نصب AngularJS
- [ ] فایل Basir-observability-angularjs.min.js در صفحه HTML لود شده است.

- [ ] ماژول Basir.observability در تعریف اپلیکیشن ثبت شده است.

- [ ] متد BasirObservabilityProvider.configure صدا زده شد.

- [ ] درخواست‌های شبکه به اندپوینت /basir/otel/v1/traces ارسال می‌شوند (نه localhost یا پورت 4318).

- [ ] هدر `traceparent` در ریکوئست‌های ارسالی به API درج شده است.

---
## راهنمای ۴: پیاده‌سازی در Blazor WebAssembly (.NET 8+)
پکیج مورد استفاده: **Basir.Observability.BlazorWasm**

این پکیج یک **Razor Class Library** است. تمام اسکریپت‌های جاوااسکریپت مورد نیاز در قالب Static Web Assets در داخل پکیج قرار دارند و پروژه مصرف‌کننده نیازی به ابزارهای npm، node یا باندلرها ندارد.

### مرحله ۱: ایجاد پروژه Blazor WebAssembly جدید
```bash
dotnet new blazorwasm -n MyCompany.PortalApp
cd MyCompany.PortalApp
```

### مرحله ۲: نصب پکیج در پروژه کلاینت
```bash
dotnet add package Basir.Observability.BlazorWasm
```

### مرحله ۳: تنظیمات فایل Program.cs در کلاینت Blazor
فایل Program.cs پروژه Blazor WASM را باز کرده و سرویس مانیتورینگ و هندلر تلمتری را تنظیم کنید:

```csharp
using Basir.Observability.BlazorWasm;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MyCompany.PortalApp;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
// ۱. ثبت سرویس مانیتورینگ بصیر
builder.Services.AddBasirBlazorObservability(options =>
{
    options.ServiceName = "portal-client";            // هویت خروجی به portal-client.web تبدیل می‌شود
    options.BridgeEndpoint = "/basir/otel/v1/traces"; // مسیر پل هم‌مبدأ روی سرور
});
// ۲. تنظیم HttpClient همراه با هندلر تزریق کانتکست W3C traceparent
builder.Services.AddScoped(sp =>
{
    var handler = sp.GetRequiredService<BasirTraceparentHandler>();
    handler.InnerHandler = new HttpClientHandler();
    return new HttpClient(handler)
    {
        BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
    };
});
var host = builder.Build();
// ۳. آغاز به کار موتور تلمتری مرورگر
await host.Services.StartBasirBlazorObservabilityAsync();
await host.RunAsync();
```

### مرحله ۴: ثبت اسپن‌های بیزینسی و مدیریت خطا در کامپوننت رِیزر
در کامپوننت‌های Blazor می‌توانید اینترفیس IBasirBlazorObservability را تزریق نمایید:

```razor
@page "/checkout"
@inject IBasirBlazorObservability Observability
@inject HttpClient Http
<h3>تکمیل خرید</h3>
<button class="btn btn-primary" @onclick="SubmitPayment">پرداخت</button>
@code {
    private async Task SubmitPayment()
    {
        // آغاز اسپن با نوع Internal
        await using var span = await Observability.StartSpanAsync("payment.submit", BasirSpanKind.Internal);
        try
        {
            await span.SetAttributeAsync("cart.items_count", 3);
            // ارسال درخواست HTTP - کانتکست اسپن و هدر traceparent خودکار منتقل می‌شود
            var response = await Http.PostAsJsonAsync("api/payments", new { Amount = 50000 });
            response.EnsureSuccessStatusCode();
            await span.SetStatusAsync(BasirSpanStatusCode.Ok);
        }
        catch (Exception ex)
        {
            await span.RecordExceptionAsync(ex);
            await span.SetStatusAsync(BasirSpanStatusCode.Error, ex.Message);
            throw;
        }
    }
}
```

### مرحله ۵: ثبت خطاهای رندرینگ کامپوننت با `<BasirErrorBoundary>`
برای اینکه خطاهای رندر کامپوننت‌های بلیزر ثبت شوند بدون اینکه رفتار پیش‌فرض خطای بلیزر خراب شود، کامپوننت‌ها را در تگ `<BasirErrorBoundary>` بپوشانید:

```razor
<BasirErrorBoundary>
    <ChildContent>
        <MyComplexComponent />
    </ChildContent>
    <ErrorContent Context="exception">
        <div class="alert alert-danger">خطایی در بارگذاری این بخش رخ داد: @exception.Message</div>
    </ErrorContent>
</BasirErrorBoundary>
```

### چک‌لیست نصب Blazor WASM
- [ ] پکیج Basir.Observability.BlazorWasm در پروژه Client نصب شد.

- [ ] دستور AddBasirBlazorObservability در Program.cs کلاینت فراخوانی شد.

- [ ] هدر BasirTraceparentHandler روی HttpClient ست شد.

- [ ] دستور StartBasirBlazorObservabilityAsync قبل از host.RunAsync فراخوانی شد.

- [ ] تماس به سرور بک‌اند تنها ۱ اسپن CLIENT ثبت می‌کند (تکثیر اسپن رخ نمی‌دهد).

- [ ] پل ارتباطی در سرور میزبان با App.MapBasirObservabilityBridge() فعال است.

---
## عیب‌یابی جامع و خطاهای پرتکرار (Troubleshooting)
### ۱. سرویس در SigNoz دیده نمی‌شود
- **علت احتمالی**: سرویس Local OpenTelemetry Collector اجرا نیست یا خروجی برنامه به پورت 4318 ارسال نمی‌شود.

- **بررسی**: در خط فرمان ویندوز وضعیت پورت را بسنجید:

```powershell
  Get-NetTCPConnection -LocalPort 4318 -ErrorAction SilentlyContinue
```

- **راه حل**: سرویس otelcol-contrib را روی سرور اجرا کنید (Start-Service otelcol-contrib).

### ۲. درخواست‌های ورودی ASP.NET Framework 4.8 ثبت نمی‌شوند
- **علت احتمالی**: عدم ثبت TelemetryHttpModule در فایل Web.config.

- **بررسی**: تگ `<modules>` در Web.config را بررسی کنید.

- **راه حل**: خط زیر را در تگ `<modules runAllManagedModulesForAllRequests="true">` قرار دهید:

```xml
  <remove name="TelemetryHttpModule" />
  <add name="TelemetryHttpModule" type="OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule, OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule" preCondition="integratedMode,managedHandler" />
```

### ۳. پاسخ خطای ۵۰۳ در Browser Bridge (/basir/otel/v1/traces)
- **علت احتمالی**: سرور بک‌اند نمی‌تواند محموله دریافتی از مرورگر را به http://127.0.0.1:4318 بفرستد چون لوکال کالکتور قطع است.

- **بررسی**: در سرور دستور curl http://127.0.0.1:4318 یا تست پورت بزنید.

- **راه حل**: لوکال کالکتور را روشن کنید. توجه داشته باشید در صورت خاموش بودن کالکتور، برنامه متوقف نمی‌شود و فقط خطای ۵۰۳ روی اندپوینت تلمتری مرورگر بازگردانده می‌شود.

### ۴. پاسخ خطای ۴۰۴ در مسیر /basir/otel/v1/traces
- **علت احتمالی**: پل ارتباطی روی سرور فعال نشده است.

- **راه حل**:

  - در ASP.NET Core: اطمینان حاصل کنید App.MapBasirObservabilityBridge(); فراخوانی شده و `BrowserBridge:Enabled` برابر با true است.

  - در ASP.NET 4.8: اطمینان حاصل کنید RouteTable.Routes.MapBasirObservabilityBridge(); در Global.asax.cs فراخوانی شده و کلید `<add key="basir:BrowserBridge:Enabled" value="true" />` در Web.config وجود دارد.

### ۵. پاسخ خطای ۴۱۳ (Payload Too Large)
- **علت احتمالی**: اندازه بسته تلمتری ارسالی فرانت‌اند از سقف ۵۱۲ کیلوبایت (524288 bytes) تجاوز کرده است.

- **راه حل**: بررسی لاگ‌ها یا اسپن‌هایی با تگ‌های بسیار بزرگ یا استک‌ترِیس‌های طولانی. در صورت ضرورت، مقدار MaxRequestBodyBytes را در تنظیمات افزایش دهید.

### ۶. اسپن‌های تکراری در درخواست‌های خروجی HTTP در Blazor
- **علت احتمالی**: همزمان با BasirTraceparentHandler از ابزارهای fetch monkey-patching جاوااسکریپت استفاده شده است.

- **راه حل**: کتابخانه‌های متفرقه instrumentation اوپن‌تلمتری برای fetch/xhr را حذف کنید و اجازه دهید تنها BasirTraceparentHandler اسپن CLIENT را تولید کند.

### ۷. عدم تطابق Trace ID بین فرانت‌اند و بک‌اند
- **علت احتمالی**: ارسال نشدن هدر W3C `traceparent` در درخواست‌های HTTP.

- **راه حل**:

  - در AngularJS: مطمئن شوید ماژول Basir.observability لود شده تا اینترسپتور $http به‌صورت خودکار هدر را تزریق کند.

  - در Blazor WASM: مطمئن شوید HttpClient با BasirTraceparentHandler ایجاد شده است.
