Skip to content

πŸ₯•⭐ [Enhancement]: Custom DAB OTEL Traces & CountersΒ #2554

@JerryNixon

Description

@JerryNixon

Now that we have OTEL, add DAB info

The current OTEL implementation only has generic/basic ASPNET information.

Traces:

https://github.com/Azure/data-api-builder/blob/jerry-otel-design/docs/design/otel-trace.md

Trace: DAB Request
β”‚   β”œβ”€β”€ Tags:
β”‚   β”‚   β”œβ”€β”€ trace_id: <unique_trace_id>
β”‚   β”‚   β”œβ”€β”€ service.name: "Data API Builder"
β”‚   β”‚   β”œβ”€β”€ deployment.environment: "production" (or "development")
β”‚
β”œβ”€β”€ Activity: Request Setup
β”‚   β”œβ”€β”€ Tags:
β”‚   β”‚   β”œβ”€β”€ http.method: "GET" | "POST" | "PUT" | "DELETE"
β”‚   β”‚   β”œβ”€β”€ action.type: "CREATE" | "READ" | "UPDATE" | "DELETE" | "EXECUTE"
β”‚   β”‚   β”œβ”€β”€ http.status_code: "200" | "400" | "500"
β”‚   β”‚   β”œβ”€β”€ http.url: "/api/entity"
β”‚   β”‚   β”œβ”€β”€ http.querystring: "?xyz" {only when mode = development}
β”‚   β”‚   β”œβ”€β”€ user.role: "Anonymous"
β”‚   β”‚   β”œβ”€β”€ api.type: "REST" | "GRAPHQL"
β”‚   β”‚   β”œβ”€β”€ api.entity: "User"
β”‚   β”‚   β”‚
β”‚   β”œβ”€β”€ Span: Validate Request Context
β”‚   β”‚   β”œβ”€β”€ Tags:
β”‚   β”‚   β”‚   β”œβ”€β”€ validation.result: "Success" | "Failure"
β”‚   β”‚   β”œβ”€β”€ Event: Validation Error (if any)
β”‚   β”‚       β”œβ”€β”€ Tags: { error.message: "<error_details>", error.type: "<exception_type>" }
β”‚   β”‚
β”‚   β”œβ”€β”€ Span: Process Request
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ Event: Error (if any)
β”‚   β”‚       β”œβ”€β”€ Tags: { error.message: "<error_details>", error.type: "<exception_type>" }
β”‚   β”‚
β”‚   β”œβ”€β”€ Span: Format Response
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ Event: Response Sent
β”‚   β”‚       β”œβ”€β”€ Tags: { event.name: "Response Sent", timestamp: <time> }
β”‚
└── Activity: Database Query
    β”œβ”€β”€ Tags:
    β”‚   β”œβ”€β”€ data-source.name: {data-source.telemetry.name}
    β”‚   β”œβ”€β”€ data-source.type: "mssql" | "mysql" | "postgresql" | "cosmos" | "sqldw"
    β”‚   β”œβ”€β”€ db.operation: "SELECT" | "INSERT" | "UPDATE" | "DELETE" | "EXECUTE"
    β”‚   β”œβ”€β”€ db.statement: "<SQL_query_text>" {only when mode = development}
    β”‚
    β”œβ”€β”€ Span: Data Operation
    β”‚   β”‚   β”œβ”€β”€ query.rows_returned: <num_rows>
    β”‚   β”‚   β”œβ”€β”€ query.mb_returned: <double>
    β”‚   β”‚   β”œβ”€β”€ query.used_cache: true | false
    β”‚   β”‚
    β”‚   β”œβ”€β”€ Event: Cache Returned
    β”‚   β”‚
    β”‚   β”œβ”€β”€ Event: Connection Opened
    β”‚   β”‚
    β”‚   β”œβ”€β”€ Event: Query Executed
    β”‚   β”‚
    β”‚   β”œβ”€β”€ Event: Connection Opened
    β”‚   β”‚
    β”‚   β”œβ”€β”€ Event: Error (if any)
    β”‚       β”œβ”€β”€ Tags: { error.message: "<error_details>", error.type: "<exception_type>" }

Metrics:

TelemetryHelper.cs

using System;
using System.Diagnostics.Metrics;

public static class TelemetryHelper
{
    private static readonly Meter Meter = new("Dab.Metrics");
    private static readonly Counter<long> RequestsTotal = Meter.CreateCounter<long>("requests_total");
    private static readonly UpDownCounter<long> RequestsActive = Meter.CreateUpDownCounter<long>("requests_active");
    private static readonly Counter<long> RequestErrors = Meter.CreateCounter<long>("request_errors");

    public static void TrackRequest(string method, string statusCode, string endpoint, string apiType)
    {
        RequestsTotal.Add(1, 
            new("method", method), 
            new("status_code", statusCode), 
            new("endpoint", endpoint), 
            new("api_type", apiType));
    }

    public static void TrackError(string method, string statusCode, string endpoint, string apiType, Exception ex)
    {
        RequestErrors.Add(1, 
            new("method", method), 
            new("status_code", statusCode), 
            new("endpoint", endpoint), 
            new("api_type", apiType), 
            new("error_type", ex.GetType().Name));
    }

    public static void IncrementActiveRequests() => RequestsActive.Add(1);

    public static void DecrementActiveRequests() => RequestsActive.Add(-1);
}

Then use it like.

[HttpGet]
public IActionResult GetAsync(...)
{
    TelemetryHelper.IncrementActiveRequests(); 

   try
    {
        // Simulating success
        TelemetryHelper.TrackRequest("GET", "200", "User", "REST");
        return Ok(new { Message = "Hello, World!" });
    }
    catch (Exception ex)
    {
        TelemetryHelper.TrackError("GET", "500", "User", "REST", ex);
        return StatusCode(500, new { Error = "An error occurred" });
    }
    finally
    {
        TelemetryHelper.DecrementActiveRequests();
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions