Skip to main content

OTel

OpenTelemetry defines a log record together with a set of semantic conventions: standard attribute names such as host.name, http.request.method and service.name.

DataStream converts to and from OTel with the Normalize processor, using otel as the source_format or target_format. This is separate from the OTLP transport: normalizing to otel changes a record's field names, and does not send it anywhere.

Record Shape​

A record normalized to otel is flat. Its fields are keyed by semantic-convention attribute names, and it carries four log-record fields beside them:

FieldSourceDescription
bodymessageThe log message
severity_textlog.levelThe severity as written by the source
severity_numberlog.syslog.severity.codeThe OTel severity number, 1-24. See below
time_unix_nano@timestampThe event time, in Unix nanoseconds

The record is not wrapped in an OTLP resourceLogs envelope and is not nested; every key sits at the top level, dots included.

Attribute Mapping​

ECS fields with a semantic-convention counterpart are renamed to it:

ECS FieldOTel Field
host.name, host.hostnamehost.name
host.id, cloud.instance.idhost.id
host.architecturehost.arch
host.type, cloud.machine.typehost.type
host.iphost.ip
host.machost.mac
host.os.nameos.name
host.os.versionos.version
host.os.typeos.type
host.os.fullos.description
cloud.providercloud.provider
cloud.regioncloud.region
cloud.availability_zonecloud.availability_zone
cloud.account.idcloud.account.id
cloud.service.namecloud.platform
service.nameservice.name
service.versionservice.version
service.environmentdeployment.environment.name
service.node.nameservice.instance.id
container.idcontainer.id
container.namecontainer.name
container.image.namecontainer.image.name
container.runtimecontainer.runtime
source.ip, source.addresssource.address
source.portsource.port
destination.ip, destination.addressdestination.address
destination.portdestination.port
client.ip, client.addressclient.address
client.portclient.port
server.ip, server.addressserver.address
server.portserver.port
network.transportnetwork.transport
network.typenetwork.type
network.protocolnetwork.protocol.name
http.versionnetwork.protocol.version
url.full, url.originalurl.full
url.pathurl.path
url.queryurl.query
url.schemeurl.scheme
url.domainurl.domain
url.porturl.port
url.fragmenturl.fragment
http.request.methodhttp.request.method
http.request.byteshttp.request.size
http.request.body.byteshttp.request.body.size
http.response.status_codehttp.response.status_code
http.response.byteshttp.response.size
http.response.body.byteshttp.response.body.size
user_agent.originaluser_agent.original
user_agent.nameuser_agent.name
user_agent.versionuser_agent.version
user.nameuser.name
user.iduser.id
user.emailuser.email
user.full_nameuser.full_name
user.hashuser.hash
user.rolesuser.roles
process.pidprocess.pid
process.parent.pidprocess.parent_pid
process.nameprocess.executable.name
process.executableprocess.executable.path
process.command_lineprocess.command_line
process.argsprocess.command_args
error.typeerror.type
error.messageexception.message
error.stack_traceexception.stacktrace
log.file.pathlog.file.path
event.originallog.record.original

Where two ECS fields share one OTel field, the one that sorts later alphabetically wins when both carry a value. For example, host.name wins over host.hostname, and url.original over url.full. An empty value never displaces a populated one.

The same attribute table is used by the OTLP target when it maps a record at egress, so a record normalized to otel and a record the target maps on the way out use the same semantic-convention names.

Unmapped Fields​

Fields with no entry in the table pass through unrenamed. OTel's key convention is ECS's own, lowercase and dot-separated, so there is no name-conversion fallback of the kind ASIM or CSL apply: event.action stays event.action.

Severity Levels​

severity_number uses the OTel ranges: TRACE 1-4, DEBUG 5-8, INFO 9-12, WARN 13-16, ERROR 17-20, FATAL 21-24.

It is derived from severity_text first. The value is matched case-insensitively against the words below:

NumberRecognized Values
1trace
5debug, verbose
9info, information, informational
10notice
13warn, warning
17err, error
19crit, critical
21alert, fatal
23emerg, emergency, panic

When severity_text is absent or not a recognized word, the syslog severity code carried over from log.syslog.severity.code is used instead:

Syslog CodeNameNumber
0Emergency23
1Alert21
2Critical19
3Error17
4Warning13
5Notice10
6Informational9
7Debug5

Timestamps​

time_unix_nano is converted from the @timestamp value it was renamed from. An RFC 3339 string, a zone-less date-time, or a numeric epoch are all accepted; the unit of an epoch is inferred from its magnitude.

A timestamp that cannot be parsed keeps its original value rather than becoming 0, so a bad input stays visible instead of silently zeroing.

The severity and timestamp conversions are the schema enforcement pass, which is skipped when the processor is run with ignore_rules set. Without it, the four log-record fields are renamed but keep their original values.

Converting from OTel​

With source_format: otel, the mapping runs in reverse. severity_number is converted back to a syslog code at log.syslog.severity.code, and time_unix_nano back to an RFC 3339 @timestamp. These conversions are also skipped when ignore_rules is set.

Format Detection​

OTel has no characteristic field, so it is never auto-detected. To normalize a record that is already OTel-shaped, set source_format: otel explicitly. It is inferred only when an earlier normalize step in the same pipeline already produced an otel record.

Example​

An ECS web access event converted to OTel:

{
"time_unix_nano": 1726671509000000000,
"severity_text": "info",
"severity_number": 9,
"body": "GET /index.html 200",
"host.name": "web-01",
"service.name": "nginx",
"source.address": "10.1.100.11",
"source.port": 54190,
"http.request.method": "GET",
"http.response.status_code": 200,
"url.path": "/index.html",
"event.action": "access"
}