ข้ามไปยังเนื้อหา

6 · Observability

เนื้อหานี้ยังไม่ได้แปลเป็นภาษาไทย แสดงเป็นภาษาอังกฤษแทน

By the end of this step you’ll have logs, metrics, and traces flowing into a local OTLP collector, with dependency health for Postgres reflected on /health.

Directory.Packages.props:

<PackageVersion Include="Cephalon.Observability" Version="0.1.0-preview" />
<PackageVersion Include="Cephalon.Observability.OpenTelemetry" Version="0.1.0-preview" />
<PackageVersion Include="Cephalon.Observability.PostgresDependencies" Version="0.1.0-preview" />

Reference them from Acme.Store.Host.csproj:

<ItemGroup>
<PackageReference Include="Cephalon.Observability" />
<PackageReference Include="Cephalon.Observability.OpenTelemetry" />
<PackageReference Include="Cephalon.Observability.PostgresDependencies" />
</ItemGroup>

Program.cs:

var app = builder.Services
.AddCephalonAspNetCore()
.AddObservability(options =>
{
options.UseOpenTelemetry(otel =>
{
otel.ExporterEndpoint = builder.Configuration["Observability:Endpoint"] ?? "http://localhost:4317";
});
options.AddPostgresDependency("Products");
options.AddPostgresDependency("Orders");
})
.AddModulesFromAssemblies(/* ... */)
.Build(builder);

The observability module:

  • wires ILogger to emit OTLP logs with resource attributes for the engine id, host id, and module-level scopes.
  • enables the System.Diagnostics.Metrics meter and OTLP exporter.
  • enables ActivitySource tracing across modules + EF Core + HttpClient.
  • registers the dependency-health probes for both Postgres connection strings.

The scaffold already gave you otel-collector-config.yaml and a compose.yaml. Bring it up:

Terminal window
docker compose up -d otel-collector

This exposes:

  • :4317 — OTLP gRPC for the host to push to.
  • :13133 — health endpoint for the collector itself.

For a full Grafana / Tempo / Loki stack, follow Observability stack tutorial.

Run the app and place an order. Then:

Terminal window
curl http://localhost:5000/health

You should see a healthy response that includes the Postgres probes:

{
"status": "Healthy",
"totalDuration": "00:00:00.087",
"results": {
"cephalon.dependency.postgres.Products": { "status": "Healthy", "duration": "00:00:00.034" },
"cephalon.dependency.postgres.Orders": { "status": "Healthy", "duration": "00:00:00.041" }
}
}

In your OTLP backend (or docker logs otel-collector) you should see:

  • structured logs with cephalon.engine.id=acme-store, cephalon.module.name=Acme.Store.Modules.Orders.
  • a cephalon.engine.started log on boot.
  • traces for POST /orders that span the publisher → process manager → DB write.

Every Cephalon module emits telemetry with:

AttributeSource
cephalon.engine.idEngine:Id configuration
cephalon.engine.versionthe engine package version
cephalon.module.namethe module’s descriptor name
cephalon.module.versionthe module’s descriptor version
cephalon.host.kindhost adapter id (aspnetcore, worker, …)
cephalon.deployment.idEngine:Deployment:Id if set

You can pipe on these attributes to slice telemetry by module without touching code.

Once you have OTLP working locally, switching to a managed backend is a config change. The full provider list lives at Technology → Observability. A taste:

// Grafana Cloud
{
"Observability": {
"Endpoint": "https://otlp-gateway-prod-eu-west-2.grafana.net/otlp",
"Headers": "Authorization=Basic <BASE64>"
}
}
// Azure Monitor (via the AzureMonitor exporter companion)
{
"Observability": {
"Provider": "AzureMonitor",
"ConnectionString": "InstrumentationKey=..."
}
}
  • Logs, metrics, traces flowing to an OTLP collector.
  • Dependency-health probes for both Postgres connections.
  • Resource attributes that identify the engine, host, and module.
  • Traces correlated across publisher → process manager → DB writes.

Step 7 → Tests.