Glossary · L

Log Level

A severity label such as DEBUG, INFO, WARN or ERROR that says how important a log entry is and controls which entries are emitted.

By Obseria Editorial TeamUpdated

Definition

A log level is a severity label attached to every log entry, typically TRACE, DEBUG, INFO, WARN, ERROR or FATAL. It tells readers and tools how important an event is and lets a logger filter output by a configured threshold, so verbose diagnostic entries can be switched off in production without changing code.

What is a log level?

A log level is the severity of a single log entry. Every mainstream logging framework, from Log4j and Logback in Java to Python's logging module, Go's slog and Node.js libraries such as pino, assigns each entry a level and compares it with a configured threshold. Entries below the threshold are discarded before they are formatted or shipped, which is why log levels are both a communication tool and a cost and performance control.

Levels answer two questions at once: how urgent is this event for a human, and should this entry exist at all in the current environment? A DEBUG entry is valuable on a developer laptop and mostly noise in production, while an ERROR entry should always be recorded and often counted.

Common log levels explained

Names vary slightly between frameworks, but most use the same six levels, ordered from most verbose to most severe:

LevelMeaningTypical example
TRACEVery fine-grained flow informationEntering and leaving a function, loop iterations
DEBUGDiagnostic detail for developersResolved config values, cache hit or miss
INFONormal, noteworthy eventsService started, job finished, order created
WARNUnexpected but handled situationRetry succeeded, deprecated API used, pool nearly full
ERRORAn operation failedPayment request failed, unhandled exception in a request
FATALThe process cannot continueMissing mandatory config, unrecoverable corruption

Some ecosystems differ: Python uses CRITICAL instead of FATAL and has no TRACE, Go's slog defines only Debug, Info, Warn and Error, and syslog (RFC 5424) uses eight numeric severities from 0 (Emergency) to 7 (Debug), where a lower number means more severe.

Log levels in OpenTelemetry

Because every framework names levels differently, the OpenTelemetry log data model normalizes them. Each log record carries a SeverityText (the original string, such as "warning") and a SeverityNumber from 1 to 24, grouped into six ranges: TRACE 1–4, DEBUG 5–8, INFO 9–12, WARN 13–16, ERROR 17–20 and FATAL 21–24. The value 0 means unspecified. Within a range, higher numbers are more severe, so a framework with extra levels can map them without losing order. This makes queries like "everything at WARN or above" work across Java, Python and Go services, and it travels unchanged over OTLP.

How to choose the right level

  • ERROR means someone may need to act. If nobody should ever look at it, it is not an error. Expected failures such as a 404 for an unknown ID are usually INFO or DEBUG.
  • WARN is for degraded but working. A retry that succeeded or a fallback that kicked in belongs here. Many WARNs with no follow-up become noise and feed alert fatigue.
  • INFO tells the story of the system. Lifecycle events and business milestones, not every function call.
  • DEBUG and TRACE are off by default in production and enabled temporarily, ideally per service or per package, without a redeploy.
  • Log once per failure. Logging the same exception at every layer of the call stack multiplies volume and confuses counts.

Example: a configurable threshold

An illustrative Python service sets its threshold from an environment variable and emits structured entries:

import logging, os
logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"))
log = logging.getLogger("payments")

log.debug("fx rate loaded", extra={"pair": "EURUSD"})   # dropped at INFO
log.warning("charge retried", extra={"attempt": 2})
log.error("charge failed", extra={"order_id": "A-1042"})

With LOG_LEVEL=INFO only the warning and the error are written. Setting LOG_LEVEL=DEBUG for one pod during an investigation adds the diagnostic entry without touching the rest of the fleet. Combined with structured logging, the level becomes a field you can filter, count and alert on.

Common mistakes

  • Leaving DEBUG enabled in production, which inflates ingest volume and can expose sensitive payloads.
  • Logging handled, expected conditions at ERROR, so error counts stop meaning anything.
  • Inconsistent level names across services (warn, warning, W) that break queries unless normalized.
  • Using levels as the only filter instead of also routing or sampling verbose logs in a telemetry pipeline.
  • Alerting on every single ERROR line rather than on error rates and their impact.

How Obseria helps

Obseria ingests logs over OpenTelemetry and maps severities to the OTel model, so you can filter consistently across languages, for example fetch logs | filter service == "payments" | summarize count(), by:{level} in OQL. Obseria Pipeline can drop or route DEBUG entries at ingest, and filtered data costs only ingestion. See Log Analytics for search and analysis of logs together with traces.

Frequently asked questions

INFO records normal events that are useful to understand what the system is doing, such as startups or completed jobs. DEBUG adds detailed diagnostic information for developers and is usually disabled in production.

Most teams run production at INFO, sometimes WARN for very chatty components, and enable DEBUG temporarily for a single service or package during an investigation.

It is a normalized severity from 1 to 24 in the OpenTelemetry log data model. Ranges map to TRACE (1–4), DEBUG (5–8), INFO (9–12), WARN (13–16), ERROR (17–20) and FATAL (21–24); 0 means unspecified.

Alerting on individual error lines tends to be noisy. It is usually better to alert on the rate of errors or on user-facing symptoms and use ERROR logs to investigate the cause.

Put these concepts into practice

Try Obseria free for 14 days, with OpenTelemetry and no proprietary agents.