Berserk Docs

OTEL Field Mapping

How OpenTelemetry Protocol fields map to Berserk columns for traces, logs, and metrics

Berserk converts OTLP data into rows with the following conventions:

  • Field names use snake_case
  • Timestamps are stored as DateTime (nanoseconds since epoch)
  • Durations are stored as Timespan (100-nanosecond ticks)
  • IDs (trace, span) are hex-encoded strings
  • Attribute keys are stored as-is (e.g., "http.method" stays as a flat key under attributes). Dotted-path shortcuts let you also access them as attributes.http.method.
  • Flattened metadata: Scope, metric, and status metadata are top-level prefixed columns
  • Empty/default fields are omitted to save space

Common Structures

Resource

Resource IS the attributes map directly. dropped_resource_attributes_count is stored as a separate top-level field.

resource: {
  "service.name": "my-service",
  "host.name": "host-1"
}
dropped_resource_attributes_count: 5  // only if > 0

Scope

Scope metadata is flattened to top-level columns. The scope bag holds only scope attributes.

OTEL FieldBerserk FieldType
InstrumentationScope.namescope_nameString
InstrumentationScope.versionscope_versionString
InstrumentationScope.attributesscopePropertybag
scope_name: "opentelemetry-java",
scope_version: "1.25.0",
scope: {                   // only if non-empty, flat keys
  "custom.attr": "value"
}

Attributes

All attributes (span, log, event, link) store keys as flat strings:

attributes: {
  "http.method": "GET",
  "http.status_code": 200
}

Accessible via both attributes.['http.method'] (bracket notation) and attributes.http.method (dotted shortcut).

Traces (Spans)

Each OTLP span becomes one row.

OTEL FieldBerserk FieldTypeNotes
start_time_unix_nanostart_timeDateTimeSpan start timestamp
end_time_unix_nanoend_timeDateTimeSpan end timestamp
end_time_unix_nanotimestampDateTimePrimary timestamp (copy of end_time)
(computed)ingest_timeDateTimeIngestion timestamp
(computed)durationTimespan(end_time - start_time) / 100
trace_idtrace_idStringHex-encoded
span_idspan_idStringHex-encoded
parent_span_idparent_span_idStringHex-encoded, omitted if empty
namespan_nameStringSpan operation name
kindspan_kindStringINTERNAL, SERVER, CLIENT, PRODUCER, CONSUMER
trace_statetrace_stateStringW3C trace state
status.codestatus_codeString"UNSET", "OK", "ERROR"
status.descriptionstatus_descriptionStringOnly if non-empty
flags (bit 0)sampledBooleanOnly if sampled flag is set
flags (bits 1-31)flagsLongOnly if uninterpreted bits remain
attributesattributesPropertybagFlat keys
resourceresourcePropertybagIS the attributes map directly
scope.namescope_nameStringFlattened to top level
scope.versionscope_versionStringFlattened to top level
scope.attributesscopePropertybagScope attributes only
eventseventsArraySee Events structure
linkslinksArraySee Links structure
dropped_attributes_countdropped_attributes_countLongOnly if > 0
dropped_events_countdropped_events_countLongOnly if > 0
dropped_links_countdropped_links_countLongOnly if > 0
(from resource)dropped_resource_attributes_countLongOnly if > 0
(from scope)dropped_scope_attributes_countLongOnly if > 0

Events

Each event in the events array is a propertybag with timestamp, name, attributes, and optional dropped_attributes_count.

Each link in the links array is a propertybag with trace_id, span_id, optional trace_state, sampled, is_remote, flags, attributes, and optional dropped_attributes_count.

Example

{
  "timestamp": "2024-01-15T10:30:00.150000000Z",
  "start_time": "2024-01-15T10:30:00.000000000Z",
  "end_time": "2024-01-15T10:30:00.150000000Z",
  "ingest_time": "2024-01-15T10:31:00.000000000Z",
  "trace_id": "0af7651916cd43dd8448eb211c80319c",
  "span_id": "b7ad6b7169203331",
  "parent_span_id": "00f067aa0ba902b7",
  "span_name": "GET /api/users",
  "span_kind": "SERVER",
  "duration": "150ms",
  "status_code": "OK",
  "attributes": {
    "http.method": "GET",
    "http.status_code": 200
  },
  "resource": {
    "service.name": "user-service",
    "service.version": "1.0.0"
  },
  "scope_name": "opentelemetry-java",
  "scope_version": "1.25.0"
}

Logs

Each OTLP log record becomes one row.

OTEL FieldBerserk FieldTypeNotes
time_unix_nanotimestampDateTimeFalls back to current time if 0
observed_time_unix_nanoobserved_timeDateTime
(computed)ingest_timeDateTimeIngestion timestamp
trace_idtrace_idStringHex-encoded, for log-trace correlation
span_idspan_idStringHex-encoded
severity_numberseverity_numberLong1-24 per OTEL spec
severity_textseverity_textStringINFO, ERROR, etc.
bodybodyDynamicString, object, or array
flags (bit 0)sampledBooleanOnly if sampled flag is set
flags (bits 1-31)flagsLongOnly if uninterpreted bits remain
attributesattributesPropertybagFlat keys
resourceresourcePropertybagIS the attributes map directly
scope.namescope_nameStringFlattened to top level
scope.versionscope_versionStringFlattened to top level
scope.attributesscopePropertybagScope attributes only
dropped_attributes_countdropped_attributes_countLongOnly if > 0
(from resource)dropped_resource_attributes_countLongOnly if > 0
(from scope)dropped_scope_attributes_countLongOnly if > 0

Example

{
  "timestamp": "2024-01-15T10:30:00.000000000Z",
  "observed_time": "2024-01-15T10:30:00.001000000Z",
  "ingest_time": "2024-01-15T10:31:00.000000000Z",
  "trace_id": "0af7651916cd43dd8448eb211c80319c",
  "span_id": "b7ad6b7169203331",
  "severity_number": 9,
  "severity_text": "INFO",
  "body": "User login successful",
  "attributes": {
    "user.id": "12345"
  },
  "resource": {
    "service.name": "auth-service"
  },
  "scope_name": "com.example.auth",
  "scope_version": "2.0.0"
}

Metrics

Each OTLP metric data point becomes one row. The structure varies by metric type.

Common Fields

OTEL FieldBerserk FieldTypeNotes
time_unix_nanotimestampDateTimeData point timestamp
(computed)ingest_timeDateTimeIngestion timestamp
start_time_unix_nanostart_timeDateTimeAggregation window start
Metric.namemetric_nameStringFlattened from metric metadata
Metric.typemetric_typeString"gauge", "sum", "histogram", etc.
Metric.descriptionmetric_descriptionStringFlattened from metric metadata
Metric.unitmetric_unitStringFlattened from metric metadata
attributesattributesPropertybagFlat keys, data point attributes
resourceresourcePropertybagIS the attributes map directly
scope.namescope_nameStringFlattened to top level
scope.versionscope_versionStringFlattened to top level
flags (bit 0)no_recorded_valueBooleanOnly if no_recorded_value flag is set
flags (bits 1-31)flagsLongOnly if uninterpreted bits remain
(from resource)dropped_resource_attributes_countLongOnly if > 0
(from scope)dropped_scope_attributes_countLongOnly if > 0

Gauge / Sum

Single value field (int or double). Sum also includes aggregation_temporality and is_monotonic.

{
  "timestamp": "2024-01-15T10:30:00.000000000Z",
  "metric_name": "http.server.request.duration",
  "metric_type": "sum",
  "metric_unit": "ms",
  "value": 1234.5,
  "aggregation_temporality": "CUMULATIVE",
  "attributes": {
    "http.method": "GET",
    "http.status_code": 200
  },
  "resource": {
    "service.name": "api-gateway"
  },
  "scope_name": "opentelemetry-collector"
}

Histogram

Fields: count, sum, min, max, bucket_counts, explicit_bounds, aggregation_temporality, exemplars (see Exemplars).

{
  "timestamp": "2024-01-15T10:30:00.000000000Z",
  "metric_name": "http.server.request.duration",
  "metric_type": "histogram",
  "metric_unit": "ms",
  "count": 100,
  "sum": 5432.1,
  "min": 1.2,
  "max": 234.5,
  "bucket_counts": [10, 25, 40, 20, 5],
  "explicit_bounds": [10, 50, 100, 200],
  "aggregation_temporality": "DELTA",
  "attributes": {
    "http.method": "GET"
  },
  "resource": {
    "service.name": "api-gateway"
  },
  "exemplars": [
    {
      "timestamp": "2024-01-15T10:29:59.987000000Z",
      "value": 142.7,
      "trace_id": "0af7651916cd43dd8448eb211c80319c",
      "span_id": "b7ad6b7169203331",
      "filtered_attributes": {
        "http.route": "/api/users/:id"
      }
    }
  ]
}

Exponential Histogram

Fields: count, sum, min, max, scale, zero_count, positive (offset + bucket_counts), negative (offset + bucket_counts), aggregation_temporality, exemplars (see Exemplars).

{
  "timestamp": "2024-01-15T10:30:00.000000000Z",
  "metric_name": "http.server.request.duration",
  "metric_type": "exponential_histogram",
  "count": 100,
  "sum": 5432.1,
  "min": 1.2,
  "max": 234.5,
  "scale": 3,
  "zero_count": 2,
  "positive": {
    "offset": 5,
    "bucket_counts": [10, 25, 40, 20, 5]
  },
  "negative": {
    "offset": 0,
    "bucket_counts": [1, 2]
  },
  "aggregation_temporality": "CUMULATIVE"
}

Summary

Fields: count, sum, quantile_values (array of {quantile, value}).

{
  "timestamp": "2024-01-15T10:30:00.000000000Z",
  "metric_name": "http.server.request.duration",
  "metric_type": "summary",
  "count": 100,
  "sum": 5432.1,
  "quantile_values": [
    { "quantile": 0.5, "value": 45.2 },
    { "quantile": 0.9, "value": 123.4 },
    { "quantile": 0.99, "value": 198.7 }
  ]
}

Exemplars

Exemplars are stored as an exemplars array on gauge, sum, histogram, and exponential_histogram rows. The OTLP Summary data point has no exemplars in the protocol, so summary rows never emit the field. The array is omitted entirely when the data point carries no exemplars.

OTEL Exemplar FieldBZRK FieldTypeNotes
time_unix_nanotimestampDateTimeAlways present
as_double / as_int (oneof)valueDouble/LongMirrors the parent data point's value type
trace_idtrace_idStringHex-encoded; omitted if empty
span_idspan_idStringHex-encoded; omitted if empty
filtered_attributesfiltered_attributesPropertybagFlat keys; omitted if empty
"exemplars": [
  {
    "timestamp": "2024-01-15T10:29:59.987000000Z",
    "value": 142.7,
    "trace_id": "0af7651916cd43dd8448eb211c80319c",
    "span_id": "b7ad6b7169203331",
    "filtered_attributes": {
      "http.route": "/api/users/:id"
    }
  }
]

The shape mirrors events and links on traces — an array of propertybags with hex-encoded IDs and a nested filtered_attributes bag — so exemplars are queryable the same way events/links/positive/negative are.

Omitted Fields

The following OTEL fields are intentionally not stored:

  • Schema URLs at all levels (not needed for storage)
  • InstrumentationScope.dropped_attributes_count (low value)
  • Link.flags are decomposed into sampled, is_remote, and remaining flags

On this page