Summary
Using WithOtlpExporter() on a container resource that also uses WithLifetime(ContainerLifetime.Persistent) causes the container to be recreated on every run instead of being reused. DCP logs the following warning:
Found existing Container, but calculated lifecycle key doesn't match: ContainerName = sqlserver-d5c7bda0, ContainerId = aaaeb586071b
Reproduction
builder.AddSqlServer("sqlserver")
.WithLifetime(ContainerLifetime.Persistent)
.WithOtlpExporter();
Root Cause
WithOtlpExporter() injects an OTEL_RESOURCE_ATTRIBUTES environment variable containing a Go template that resolves to a per-run random value:
service.instance.id={{- index .Annotations "otel-service-instance-id" -}}
The annotation value (OtelServiceInstanceIdAnnotation) is set to a new random suffix on every Aspire startup. DCP computes the lifecycle key from the resolved container spec (including env vars). Since the resolved service.instance.id changes every run, the lifecycle key never matches the existing persistent container, so DCP tears it down and recreates it.
Expected Behavior
WithOtlpExporter() and ContainerLifetime.Persistent should be compatible. A persistent container should be reused across runs even when OTLP export is configured.
Actual Behavior
The persistent container is recreated on every run when WithOtlpExporter() is used.
Workaround
Remove WithOtlpExporter() from persistent containers. This loses OTLP telemetry from the container in the dashboard but restores correct persistence behavior.
Summary
Using
WithOtlpExporter()on a container resource that also usesWithLifetime(ContainerLifetime.Persistent)causes the container to be recreated on every run instead of being reused. DCP logs the following warning:Reproduction
Root Cause
WithOtlpExporter()injects anOTEL_RESOURCE_ATTRIBUTESenvironment variable containing a Go template that resolves to a per-run random value:The annotation value (
OtelServiceInstanceIdAnnotation) is set to a new random suffix on every Aspire startup. DCP computes the lifecycle key from the resolved container spec (including env vars). Since the resolvedservice.instance.idchanges every run, the lifecycle key never matches the existing persistent container, so DCP tears it down and recreates it.Expected Behavior
WithOtlpExporter()andContainerLifetime.Persistentshould be compatible. A persistent container should be reused across runs even when OTLP export is configured.Actual Behavior
The persistent container is recreated on every run when
WithOtlpExporter()is used.Workaround
Remove
WithOtlpExporter()from persistent containers. This loses OTLP telemetry from the container in the dashboard but restores correct persistence behavior.