Plan telemetry instrumentation points and context propagation
Plans telemetry instrumentation points and context propagation for applications. Use when working on instrumentation planning tasks or designing observability strategies.
/plugin marketplace add melodic-software/claude-code-plugins/plugin install observability-planning@melodic-softwareThis skill is limited to using the following tools:
Use this skill when:
Plan and implement telemetry instrumentation for applications.
Before planning instrumentation:
docs-management skill for instrumentation patternsINSTRUMENTATION HIERARCHY:
┌─────────────────────────────────────────────────────────────────┐
│ INSTRUMENTATION TYPES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ AUTO-INSTRUMENTATION (Preferred) │
│ ├── HTTP server (ASP.NET Core) │
│ ├── HTTP client (HttpClient) │
│ ├── Database (EF Core, Npgsql) │
│ ├── Message brokers (RabbitMQ, Kafka) │
│ └── Cache (Redis, MemoryCache) │
│ │
│ MANUAL INSTRUMENTATION │
│ ├── Business operations │
│ ├── Custom workflows │
│ ├── Domain events │
│ └── Complex algorithms │
│ │
│ SEMANTIC CONVENTIONS │
│ ├── Standard attribute names │
│ ├── Standard metric names │
│ └── Standard span names │
│ │
└─────────────────────────────────────────────────────────────────┘
// Comprehensive auto-instrumentation setup
// Infrastructure/Telemetry/InstrumentationConfiguration.cs
public static class InstrumentationConfiguration
{
public static TracerProviderBuilder AddStandardInstrumentation(
this TracerProviderBuilder builder)
{
return builder
// HTTP Server
.AddAspNetCoreInstrumentation(options =>
{
options.RecordException = true;
options.EnrichWithHttpRequest = EnrichRequest;
options.EnrichWithHttpResponse = EnrichResponse;
options.Filter = FilterHealthChecks;
})
// HTTP Client
.AddHttpClientInstrumentation(options =>
{
options.RecordException = true;
options.EnrichWithHttpRequestMessage = EnrichOutgoingRequest;
options.EnrichWithHttpResponseMessage = EnrichOutgoingResponse;
options.FilterHttpRequestMessage = FilterInternalCalls;
})
// Database
.AddEntityFrameworkCoreInstrumentation(options =>
{
options.SetDbStatementForText = true;
options.SetDbStatementForStoredProcedure = true;
options.EnrichWithIDbCommand = EnrichDbCommand;
})
.AddNpgsql()
.AddSqlClientInstrumentation(options =>
{
options.SetDbStatementForText = true;
options.RecordException = true;
})
// Cache
.AddRedisInstrumentation(options =>
{
options.SetVerboseDatabaseStatements = true;
})
// Messaging
.AddMassTransitInstrumentation()
// gRPC
.AddGrpcClientInstrumentation()
.AddGrpcCoreInstrumentation();
}
private static bool FilterHealthChecks(HttpContext context)
{
return !context.Request.Path.StartsWithSegments("/health") &&
!context.Request.Path.StartsWithSegments("/ready") &&
!context.Request.Path.StartsWithSegments("/live");
}
private static void EnrichRequest(Activity activity, HttpRequest request)
{
activity.SetTag("http.request.header.x_correlation_id",
request.Headers["X-Correlation-Id"].FirstOrDefault());
if (request.RouteValues.TryGetValue("id", out var id))
{
activity.SetTag("resource.id", id?.ToString());
}
}
private static void EnrichResponse(Activity activity, HttpResponse response)
{
activity.SetTag("http.response.header.x_request_id",
response.Headers["X-Request-Id"].FirstOrDefault());
}
}
// Manual span creation for business operations
// Domain/Orders/OrderProcessor.cs
using System.Diagnostics;
public class OrderProcessor
{
private static readonly ActivitySource ActivitySource =
new("OrdersApi.Domain", "1.0.0");
private readonly ILogger<OrderProcessor> _logger;
private readonly IPaymentGateway _paymentGateway;
private readonly IInventoryService _inventory;
public async Task<Order> ProcessOrderAsync(CreateOrderCommand command)
{
// Create parent span for entire operation
using var activity = ActivitySource.StartActivity(
"order.process",
ActivityKind.Internal);
activity?.SetTag("order.customer_id", command.CustomerId);
activity?.SetTag("order.item_count", command.Items.Count);
try
{
// Child span: Validate order
var order = await ValidateOrderAsync(command);
// Child span: Reserve inventory
await ReserveInventoryAsync(order);
// Child span: Process payment
await ProcessPaymentAsync(order);
// Child span: Confirm order
await ConfirmOrderAsync(order);
activity?.SetTag("order.id", order.Id);
activity?.SetTag("order.total", order.Total);
activity?.SetStatus(ActivityStatusCode.Ok);
return order;
}
catch (Exception ex)
{
activity?.SetStatus(ActivityStatusCode.Error, ex.Message);
activity?.RecordException(ex);
throw;
}
}
private async Task<Order> ValidateOrderAsync(CreateOrderCommand command)
{
using var activity = ActivitySource.StartActivity(
"order.validate",
ActivityKind.Internal);
activity?.SetTag("validation.type", "business_rules");
// Validation logic...
activity?.AddEvent(new ActivityEvent("validation.completed",
tags: new ActivityTagsCollection
{
{ "validation.rules_checked", 5 },
{ "validation.passed", true }
}));
return new Order(command);
}
private async Task ReserveInventoryAsync(Order order)
{
using var activity = ActivitySource.StartActivity(
"inventory.reserve",
ActivityKind.Client);
activity?.SetTag("inventory.sku_count", order.Items.Count);
foreach (var item in order.Items)
{
activity?.AddEvent(new ActivityEvent("item.reserved",
tags: new ActivityTagsCollection
{
{ "item.sku", item.Sku },
{ "item.quantity", item.Quantity }
}));
}
await _inventory.ReserveAsync(order.Items);
}
private async Task ProcessPaymentAsync(Order order)
{
using var activity = ActivitySource.StartActivity(
"payment.process",
ActivityKind.Client);
activity?.SetTag("payment.amount", order.Total);
activity?.SetTag("payment.currency", "USD");
// Link to external payment trace if available
var externalTraceId = await _paymentGateway.ChargeAsync(order);
if (externalTraceId != null)
{
activity?.AddLink(new ActivityLink(
new ActivityContext(
ActivityTraceId.CreateFromString(externalTraceId),
ActivitySpanId.CreateRandom(),
ActivityTraceFlags.Recorded)));
}
}
}
OPENTELEMETRY SEMANTIC CONVENTIONS:
HTTP Attributes:
┌─────────────────────────┬──────────────────────────────────────┐
│ Attribute │ Example │
├─────────────────────────┼──────────────────────────────────────┤
│ http.request.method │ GET, POST, PUT │
│ http.response.status_code│ 200, 404, 500 │
│ url.path │ /api/orders/123 │
│ url.scheme │ https │
│ server.address │ api.example.com │
│ server.port │ 443 │
│ http.route │ /api/orders/{id} │
└─────────────────────────┴──────────────────────────────────────┘
Database Attributes:
┌─────────────────────────┬──────────────────────────────────────┐
│ Attribute │ Example │
├─────────────────────────┼──────────────────────────────────────┤
│ db.system │ postgresql, sqlserver │
│ db.name │ orders_db │
│ db.operation │ SELECT, INSERT │
│ db.statement │ SELECT * FROM orders WHERE... │
│ server.address │ db.example.com │
│ server.port │ 5432 │
└─────────────────────────┴──────────────────────────────────────┘
Messaging Attributes:
┌─────────────────────────┬──────────────────────────────────────┐
│ Attribute │ Example │
├─────────────────────────┼──────────────────────────────────────┤
│ messaging.system │ rabbitmq, kafka │
│ messaging.destination.name│ orders.created │
│ messaging.operation │ publish, receive │
│ messaging.message.id │ msg-123-abc │
└─────────────────────────┴──────────────────────────────────────┘
Custom Business Attributes (prefix with app.*):
┌─────────────────────────┬──────────────────────────────────────┐
│ Attribute │ Example │
├─────────────────────────┼──────────────────────────────────────┤
│ app.order.id │ ord-123 │
│ app.customer.tier │ premium, standard │
│ app.feature.flag │ new_checkout_enabled │
│ app.workflow.step │ validation, payment │
└─────────────────────────┴──────────────────────────────────────┘
// Context propagation across service boundaries
// Infrastructure/Telemetry/ContextPropagation.cs
public static class ContextPropagation
{
// HTTP context propagation (automatic with instrumentation)
// W3C Trace Context headers:
// - traceparent: 00-{trace-id}-{span-id}-{flags}
// - tracestate: vendor-specific data
// Manual propagation for custom protocols
public static void InjectContext(
Activity? activity,
IDictionary<string, string> carrier)
{
if (activity == null) return;
var propagator = Propagators.DefaultTextMapPropagator;
propagator.Inject(
new PropagationContext(activity.Context, Baggage.Current),
carrier,
(c, key, value) => c[key] = value);
}
public static PropagationContext ExtractContext(
IDictionary<string, string> carrier)
{
var propagator = Propagators.DefaultTextMapPropagator;
return propagator.Extract(
default,
carrier,
(c, key) => c.TryGetValue(key, out var value)
? new[] { value }
: Enumerable.Empty<string>());
}
}
// Message handler with context extraction
public class OrderCreatedHandler : IConsumer<OrderCreated>
{
private static readonly ActivitySource ActivitySource =
new("OrdersApi.Messaging");
public async Task Consume(ConsumeContext<OrderCreated> context)
{
// Extract trace context from message headers
var propagationContext = ContextPropagation.ExtractContext(
context.Headers.ToDictionary());
// Create span linked to original trace
using var activity = ActivitySource.StartActivity(
"order.created.handle",
ActivityKind.Consumer,
propagationContext.ActivityContext);
activity?.SetTag("messaging.message.id", context.MessageId);
activity?.SetTag("app.order.id", context.Message.OrderId);
// Process message...
}
}
# Instrumentation Planning Checklist
## Auto-Instrumentation Setup
- [ ] OpenTelemetry SDK installed
- [ ] ASP.NET Core instrumentation enabled
- [ ] HttpClient instrumentation enabled
- [ ] Database instrumentation enabled (EF Core, ADO.NET)
- [ ] Cache instrumentation enabled (if applicable)
- [ ] Messaging instrumentation enabled (if applicable)
## HTTP Instrumentation
- [ ] Health/ready endpoints filtered
- [ ] Sensitive data excluded
- [ ] Request enrichment configured
- [ ] Response enrichment configured
- [ ] Error recording enabled
## Database Instrumentation
- [ ] SQL statements captured
- [ ] Connection strings sanitized
- [ ] Query parameters excluded (sensitive)
- [ ] Stored procedures captured
## Custom Instrumentation
- [ ] Activity source created with service name
- [ ] Business operations wrapped in spans
- [ ] Appropriate span kinds used
- [ ] Semantic conventions followed
- [ ] Events added for significant points
- [ ] Exceptions recorded
## Context Propagation
- [ ] W3C Trace Context enabled
- [ ] Baggage propagation configured
- [ ] Cross-service correlation verified
- [ ] Message queue context propagation
- [ ] Background job context propagation
## Sampling Configuration
- [ ] Head-based sampling configured
- [ ] Error sampling set to 100%
- [ ] Production rate appropriate
- [ ] Non-production at 100%
INSTRUMENTATION POINTS:
WEB API SERVICE:
┌─────────────────────────────────────────────────────────────────┐
│ REQUEST FLOW │
│ │
│ HTTP Request ──────────────────────────────────────────────┐ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ Middleware │ ← Auth, Logging, Correlation ID │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ Controller │ ← Request validation, routing │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌─────────────┐ │ │
│ │ Service │ ← Business logic, orchestration [MANUAL]│ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ┌────┴────┬─────────────┬─────────────┐ │ │
│ ▼ ▼ ▼ ▼ │ │
│ ┌─────┐ ┌──────┐ ┌────────┐ ┌─────────┐ │ │
│ │ DB │ │ HTTP │ │ Cache │ │ Message │ [AUTO] │ │
│ │ │ │Client│ │ │ │ Queue │ │ │
│ └─────┘ └──────┘ └────────┘ └─────────┘ │ │
│ │ │ │
│ HTTP Response ◄────────────────────────────────────┘ │ │
│ │ │
└─────────────────────────────────────────────────────────────────┘
BACKGROUND WORKER:
┌─────────────────────────────────────────────────────────────────┐
│ MESSAGE FLOW │
│ │
│ Message Received ───────────────────────────────────────┐ │
│ │ │ │
│ ▼ │ │
│ ┌────────────────┐ │ │
│ │ Message Handler│ ← Extract trace context [AUTO] │ │
│ └───────┬────────┘ │ │
│ │ │ │
│ ▼ │ │
│ ┌────────────────┐ │ │
│ │ Business Logic │ ← Process message [MANUAL] │ │
│ └───────┬────────┘ │ │
│ │ │ │
│ ┌────┴────┬─────────────┐ │ │
│ ▼ ▼ ▼ │ │
│ ┌─────┐ ┌──────┐ ┌─────────┐ │ │
│ │ DB │ │ HTTP │ │ Publish │ [AUTO] │ │
│ │ │ │Client│ │ Message │ │ │
│ └─────┘ └──────┘ └─────────┘ │ │
│ │ │ │
│ Acknowledge ◄───────────────┴───────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
When planning instrumentation:
For detailed guidance:
Last Updated: 2025-12-26
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.