SigNoz
Read-only error sweeps, plus trace and log evidence queries, from self-hosted SigNoz
Vendor ID: signoz · Maturity: preview · Categories: Observability, Tools
SigNoz — OTel-native observability. This extension queries your SigNoz instance through the v5 query_range API to find what is failing across your services.
Read-only by construction. The only endpoint any tool here can reach is POST /api/v5/query_range. There is deliberately no alert, dashboard, or settings surface: a workflow that can mutate your observability plane has a far larger blast radius than one that can only read it.
Auth
| Credential | Notes |
|---|---|
apiKey | A SigNoz API key (Settings → API Keys), sent as the SIGNOZ-API-KEY header. SigNoz does not use Authorization: Bearer for these keys. |
Configuration
| Field | Notes |
|---|---|
signozBaseUrl | Base URL of your SigNoz query API, no trailing slash — e.g. http://signoz-query.internal.scrydon.com:8080. Required. |
SigNoz is self-hosted, so there is no fixed public origin the way there is for a SaaS vendor. The reachable address is yours, which is why it is configuration rather than a constant.
If SigNoz sits behind a private endpoint, two things must both be true or every call is denied: the host must be on the organization's egress allowlist, and private-range egress must be enabled. The SSRF wall blocks RFC1918 destinations by default, and an empty allowlist means deny everything, not no policy.
Capabilities
| Tool | Returns |
|---|---|
| Query Error Spans | Error spans (has_error = true) grouped by service, operation, and status message, ranked by occurrence count. This is the "what is failing" query. Pass clusterName to sweep one cluster. |
| Query Error Logs | Raw ERROR and FATAL log records — for when the span status message is too terse to identify the cause. Pass clusterName to sweep one cluster. |
| Query Spans | Raw spans filtered by traceId, serviceName, clusterName, spanName, statusMessageContains and errorsOnly. Pass a traceId to get one request's whole call tree (spanId / parentSpanId, service, span name, duration, error status and HTTP status code), oldest first. Without a traceId the newest matches come first. |
| Query Logs | Raw log records filtered by traceId, serviceName, deploymentName, namespace, clusterName, bodyContains and errorsOnly. Pass a traceId to read the log lines one request wrote, oldest first. Without a traceId the newest matches come first. |
Every tool takes a bounded window (lookbackHours, default 24, or explicit start/end) and a limit (default 500, hard cap 5 000).
Every log record carries its correlation keys: traceId, spanId, deploymentName, namespace and clusterName, alongside body, serviceName and severityText. serviceName is exactly what the record says. A container log written to stdout may have no service.name, and then deploymentName tells you which workload wrote it. An absent or all-zero trace id is reported as "", never as an id you could join on.
Finding the request behind an error
- Query Error Spans names the failing service and span name.
- Query Spans with that
serviceName,spanNameanderrorsOnly: truereturns concrete spans, each with itstraceId. - Query Spans with one
traceIdshows the whole request. Query Logs with the sametraceIdshows what it logged. clusterNameon those spans and logs tells you which deployment ran the request. Check its release before you read the code.
Several clusters, one SigNoz
When more than one cluster ships to the same SigNoz, pass clusterName to every query so a sweep of one environment does not report another's errors. The filter matches the k8s.cluster.name resource attribute, and a record that does not carry it is excluded, never included.
Logs collected by the SigNoz k8s-infra agent carry the cluster name. Spans carry it only when they pass through that agent too. An application or Dapr sidecar that exports OTLP straight to the SigNoz collector sends only service.name. Point its OTLP endpoint at the agent's Service (gRPC 4317, HTTP 4318), or set k8s.cluster.name in its OTEL_RESOURCE_ATTRIBUTES. Every span's clusterName field shows which of the two you have: empty means the span arrived without one.
Filter values are validated, not escaped
A value that would change the meaning of the query is refused before any request is sent, with signoz_invalid_filter:
- a
traceIdmust be 32 lowercase hex characters; serviceName,deploymentName,namespaceandclusterName(on every tool that takes it) may use onlyA-Z a-z 0-9 . _ -;spanName,statusMessageContainsandbodyContainsmay not contain a single quote, a backslash or a control character, and are capped at 200 characters.
That matters because an agent writes these values. The span-name filter is called spanName, not operation. In a workflow, a block's operation field chooses which tool runs, and its value would otherwise be passed through as a filter.
Two behaviors worth knowing
Truncation is reported, never silent. Every tool returns a truncated flag when the result hits the limit. A truncated sweep that looks complete is worse than a small one that admits it.
An unrecognized response shape fails the call. SigNoz does not publish a response schema for v5 query_range, so a version bump could reshape it. Rather than degrade to an empty result — which would read as "no errors found" — the extension raises an error. A blind spot you can see beats a clean report you can't trust.
Grouping on status_message
Error spans are clustered on service.name + span name + status_message, not on response_status_code. For Dapr CallLocal and binding spans the status code is empty, and the human-readable failure — Code(403): Forbidden, or a verbatim access-control denial — lives in status_message.