Observability#
BaSyx Go provides structured application logging, request correlation, optional
OpenTelemetry tracing, and PostgreSQL connection-pool metrics through shared
runtime infrastructure. Logging and tracing are available in BaSyx Go 1.0.4
or newer. The pool metrics require BaSyx Go 1.0.6 or newer.
The application remains independent of a particular observability backend:
BaSyx JSON stderr --> platform log collector --> Loki or another log store
BaSyx OTLP traces --> OpenTelemetry Collector --> Tempo, Jaeger, or another trace store
BaSyx OTLP metrics --> OpenTelemetry Collector --> Prometheus or another metric store
BaSyx does not contain direct clients for Grafana, Loki, Tempo, or Jaeger.
Structured Logging#
Every BaSyx command writes diagnostic logs to standard error. The default is
human-readable text at info level:
logging:
format: text
level: info
The equivalent environment variables are:
LOGGING_FORMAT=text
LOGGING_LEVEL=info
LOGGING_FORMAT accepts text or json. LOGGING_LEVEL accepts debug,
info, warn, or error. Environment variables override YAML values.
JSON output is recommended for container deployments:
{"time":"2026-07-25T10:00:01Z","level":"INFO","msg":"HTTP request completed","service.name":"aasenvironmentservice","request.id":"request-42","correlation.id":"workflow-7","http.request.method":"GET","url.path":"/shells","http.route":"/shells","http.response.status_code":200,"http.response.body.size":421,"duration_ms":3.725}
Configuration logs contain only curated, non-sensitive attributes. Passwords, DSNs, access tokens, object-store credentials, private-key material, request bodies, and response bodies are not logged.
Logs remain available through the platform’s normal process-log mechanism:
docker logs -f <container>
kubectl logs -f <pod> [-c <container>]
journalctl -f -u <unit>
BaSyx does not write application log files or provide log rotation, retention,
or a /logs endpoint. Collect standard error with the platform agent of your
choice, for example Grafana Alloy, Fluent Bit, or an OpenTelemetry Collector.
HTTP Request and Correlation IDs#
Every BaSyx Go HTTP service emits one HTTP request completed event for each
request. Normal requests are logged at info; GET health probes are logged at
debug to avoid filling the default log stream.
Clients and trusted ingress controllers may provide:
X-Request-IDX-Correlation-ID
The legacy Request-ID and Correlation-ID names are accepted as input
aliases. Accepted IDs contain 1 to 128 ASCII letters, digits, or ._:/-.
Missing or invalid request IDs are replaced with a generated req- identifier.
A missing or invalid correlation ID defaults to the request ID.
BaSyx returns the two canonical headers and automatically permits and exposes them through its CORS middleware. Request and correlation IDs are useful for searching logs, but they are not authenticated identity data and must not be used for authorization decisions.
Access records contain the method, path, resolved route, response status and size, and request duration. Query strings, arbitrary headers, request and response bodies, authorization values, tokens, user agents, and client IP addresses are not recorded.
OpenTelemetry Tracing and Metrics#
Tracing and metrics are optional and configured independently through standard OpenTelemetry environment variables. They are not BaSyx YAML configuration keys.
Tracing is disabled when
OTEL_TRACES_EXPORTERis unset, empty, ornone.Metrics are disabled when
OTEL_METRICS_EXPORTERis unset, empty, ornone.OTEL_SDK_DISABLED=truedisables both signals.
The typical Collector configuration is:
OTEL_TRACES_EXPORTER=otlp
OTEL_METRICS_EXPORTER=otlp
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.observability.svc:4318
OTEL_RESOURCE_ATTRIBUTES=deployment.environment.name=production
OTEL_TRACES_SAMPLER=parentbased_traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1
Either signal can be enabled without the other. The console exporter is
available for local diagnostics. Supported explicit exporter values are
otlp, console, and none.
The default trace sampler is parent-based and always-on, so high-volume deployments should configure an appropriate sampling ratio.
BaSyx supports the standard OpenTelemetry Go environment variables for:
the generic OTLP endpoint, protocol, headers, compression, and timeout:
OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL,OTEL_EXPORTER_OTLP_HEADERS,OTEL_EXPORTER_OTLP_COMPRESSION, andOTEL_EXPORTER_OTLP_TIMEOUTtrace-specific overrides:
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,OTEL_EXPORTER_OTLP_TRACES_PROTOCOL,OTEL_EXPORTER_OTLP_TRACES_HEADERS,OTEL_EXPORTER_OTLP_TRACES_COMPRESSION, andOTEL_EXPORTER_OTLP_TRACES_TIMEOUTmetric-specific overrides:
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,OTEL_EXPORTER_OTLP_METRICS_PROTOCOL,OTEL_EXPORTER_OTLP_METRICS_HEADERS,OTEL_EXPORTER_OTLP_METRICS_COMPRESSION, andOTEL_EXPORTER_OTLP_METRICS_TIMEOUTOTEL_SERVICE_NAMEandOTEL_RESOURCE_ATTRIBUTEStrace sampling and batch span processing (
OTEL_TRACES_*andOTEL_BSP_*)the metric export interval and timeout through
OTEL_METRIC_EXPORT_INTERVALandOTEL_METRIC_EXPORT_TIMEOUTW3C Trace Context and Baggage propagation through
OTEL_PROPAGATORS
The signal-specific endpoint, protocol, headers, compression, and timeout override their generic counterparts for that signal. The export interval and timeout are positive integer values in milliseconds. If no endpoint is specified, the OpenTelemetry SDK’s normal OTLP defaults apply.
The default telemetry resource service.name is the lowercase BaSyx command
name, for example aasenvironmentservice. An explicit OTEL_SERVICE_NAME
overrides it.
Each inbound HTTP request creates a server span. Valid W3C traceparent and
tracestate values are preserved, while requests without trace context start a
new trace. Delegated submodel-operation calls create client spans and propagate
the active W3C trace context. Other third-party clients, including OIDC
discovery, are not instrumented.
Export happens asynchronously in batches. An unavailable Collector does not prevent service startup or fail HTTP requests; telemetry can be dropped while the backend is unavailable. Shutdown uses a bounded flush period.
PostgreSQL Connection-Pool Metrics#
Each supported HTTP service registers its shared PostgreSQL writer pool once.
Metric collection reads Go’s in-process database/sql.DBStats() and does not
run additional database queries.
Metric |
Type |
Meaning |
|---|---|---|
|
Up/down counter |
Configured maximum number of open connections |
|
Up/down counter |
Connections currently in use |
|
Up/down counter |
Connections currently idle |
|
Cumulative counter |
Requests that waited for a connection |
|
Cumulative counter in seconds |
Total time spent waiting for connections |
|
Cumulative counter |
Connections closed because of the idle-count limit |
|
Cumulative counter |
Connections closed after their maximum idle time |
|
Cumulative counter |
Connections closed after their maximum lifetime |
Open connections are the sum of the used and idle points on
db.client.connection.count. Every point has
db.system.name=postgresql and
db.client.connection.pool.name=writer. The service.name resource attribute
identifies the BaSyx service, not an individual replica. For per-pod diagnosis
in a horizontally scaled deployment, configure the Collector to attach bounded
Kubernetes resource attributes such as k8s.pod.name or k8s.pod.uid.
Use rates rather than raw totals for the cumulative wait and closure counters.
A rising wait rate while the number of used connections approaches
db.client.connection.max indicates that the application pool is constraining
concurrency. Low utilization with slow requests points elsewhere, for example
to query execution, PostgreSQL capacity, or storage latency. Pool metrics show
client-side pressure; they do not measure query duration or increase database
capacity.
The metric attributes are intentionally bounded. Database names, hosts, users,
DSNs, SQL text, AAS identifiers, and request data are not recorded. Do not copy
such values into OTEL_RESOURCE_ATTRIBUTES, because resource attributes are
attached to every exported data point.
Pool metrics are available for these HTTP services:
AAS Environment
AAS Repository
AAS Registry
AASX File Server
Basic Discovery
Company Lookup
Concept Description Repository
Digital Product Passport API
Digital Twin Registry
Submodel Repository
Submodel Registry
The Configuration Service and History Evidence Verifier remain logging-only commands. They do not expose HTTP servers or long-running telemetry runtimes.
Correlating Logs and Traces#
Contextual logs produced inside an active span contain:
trace_idspan_idtrace_flags
The HTTP request completed record is written before its server span ends, so
its identifiers match the exported span. A log backend can use trace_id to
link to a trace backend, and a trace backend can query logs for the same
service, time range, and trace ID.
Trace spans do not capture query strings, bodies, authorization values, arbitrary headers, tokens, user agents, or client IP addresses. URL paths are recorded, so secrets and sensitive personal data should never be placed in URL path segments.
Examples and Helm#
The BaSyx Go observability example provides a local development stack with an AAS Environment, BaSyx Web UI, OpenTelemetry Collector, Tempo, Loki, Alloy, and Grafana. It verifies trace and metric export, structured-log ingestion, trace-to-log correlation, and continued service operation during a Collector outage.
For Kubernetes, the BaSyx Helm chart exposes common logging and telemetry values. Its observability values example connects BaSyx workloads to an existing Collector:
telemetry:
tracesExporter: otlp
metricsExporter: otlp
endpoint: http://opentelemetry-collector.observability.svc.cluster.local:4318
protocol: http/protobuf
metricsExportInterval: "60000"
metricsExportTimeout: "30000"
These metric values require BaSyx Helm chart 3.7.0 and BaSyx Go 1.0.6 or
newer. metricsExporter, metricsExportInterval, and
metricsExportTimeout render OTEL_METRICS_EXPORTER,
OTEL_METRIC_EXPORT_INTERVAL, and OTEL_METRIC_EXPORT_TIMEOUT respectively.
Their defaults are none, an empty interval, and an empty timeout. Empty
timing values use the OpenTelemetry SDK defaults; configured values must be
positive milliseconds.
The generic endpoint and protocol apply to both signals. Signal-specific OTLP
overrides and credentials can be supplied through environment.common, a
service’s environment map, or telemetry.existingSecret. Store OTLP
authorization headers in a Secret rather than a values file. Changes to
structured telemetry values update the backend pod template checksum. Changing
only the contents of an existing Secret does not, so restart the backend pods
after rotating those values.
The chart intentionally does not install the Collector, Grafana, Loki, Tempo, or Alloy because authentication, storage, retention, resource sizing, and tenancy should be designed for the target cluster.
The local Compose stack is a development example, not a production deployment reference. Production environments should use authenticated telemetry endpoints, TLS, secret-backed OTLP headers, bounded retention, resource limits, and least-privilege log collection.
Current Scope#
BaSyx Go currently provides traces, PostgreSQL pool metrics, structured logs, and log-to-trace correlation. It does not provide direct OTLP log export, database query spans, SQL statement capture, query-duration metrics, AAS-domain spans, arbitrary outbound HTTP propagation, runtime telemetry reconfiguration, or a built-in metrics endpoint.