Instruction file imported from kritikos-io/templates-dotnet (
.github/instructions/observability.instructions.md). Copyright stays with the author.
Observability & Feature Flags
OpenTelemetry
- One
ActivitySourceper logical component, namedKritikos.<Project>.<Component>. Declare asstatic readonlyon a dedicatedTelemetrystatic class within the component (avoid scattering sources across every type). - One
Meterper component, alongside itsActivitySource. The names may match when both belong to the same component. - Always wrap
StartActivity(...)in ausing— leaked activities skew downstream timings. - Activity names:
- When OpenTelemetry semantic conventions cover the operation (HTTP, DB, messaging, RPC), follow semconv exactly (
HTTP GET,db.query,messaging.process). - For custom operations not covered by semconv:
<Verb><Object>in PascalCase (ProcessOrder,LoadConfiguration). Avoid generic verbs likeHandleorExecute.
- When OpenTelemetry semantic conventions cover the operation (HTTP, DB, messaging, RPC), follow semconv exactly (
- Tags / attributes: lowercase dotted, follow semantic conventions where they exist (
http.request.method,db.system,messaging.destination.name). Project-specific tags use thekritikos.<area>.<name>namespace. - Metric instruments: snake_case names with units in the suffix (
orders_processed_total,request_duration_seconds). Always setunitanddescriptionat creation. - Resource attributes: when a shared registration helper is added, it should populate
service.namefromAssemblyNameandservice.versionfrom the GitVersion-computedInformationalVersion. Do not set them manually at call sites. - Exporter: OTLP over gRPC, endpoint via
OTEL_EXPORTER_OTLP_ENDPOINT. Do not register console exporters inReleasebuilds. - Sampling: parent-based with
TraceIdRatioBased(1.0 in dev, configurable in prod). Do not set custom samplers without justification.
OpenFeature
- Resolve flags through the configured OpenFeature client (obtained via DI, or
Api.Instance.GetClient()if no DI integration is wired). Never call provider SDKs directly. - Flag keys:
kebab-case, prefixed by domain (orders-allow-partial-fulfilment,auth-require-mfa). Keys are stable contracts — treat renames like API breaking changes. - Always pass
defaultValue:—client.GetBooleanValue("flag", defaultValue: false, context). - Evaluation context is built once per request via the configured context provider — do not assemble ad-hoc contexts inline.
- Long-lived flags (kill switches, licensing) live in code; short-lived flags (rollouts, experiments) must have a removal date in their description and a tracking issue.