Skip to main content

Sovdev Logger Field Definitions

Overview

This document defines every field that must appear in log entries across all three output destinations (OTLP, console, file). Field names, types, and formats must be identical across all language implementations.

Field Naming Convention

All field names use underscore notation (snake_case) for consistency across all outputs.

Rationale

  • Cross-language consistency: Python, Go, Rust, PHP all use snake_case
  • Code-to-log alignment: Variable names match log field names exactly
  • No transformations: Same field names in code, file logs, OTLP export, and backend storage
  • Future-proof: Easy to add new languages without naming conflicts

Standard Fields

Field NameTypeDescriptionRequired
service_namestringService identifierYes
service_versionstringService versionYes
session_idstringSession grouping ID (UUID for entire execution)OTLP Only
peer_servicestringTarget system identifierYes
function_namestringFunction/method nameYes
log_typestringLog classification (transaction, session, error, etc.)Yes
messagestringLog messageYes
trace_idstringTransaction correlation ID (UUID)Yes
event_idstringUnique log entry ID (UUID)Yes
timestampstringWhen log entry was created (ISO 8601)Yes
levelstringLog level (lowercase: info, error, etc.)Yes (file/console)
input_jsonobject/stringInput parametersOptional
response_jsonobject/stringOutput dataOptional
exceptionobjectException details (type, message, stack)Optional (ERROR/FATAL only)

Note: All fields use snake_case in code, file logs, OTLP export, and backend storage. No transformations applied.


Core Fields (All Log Types)

Service Identification

FieldTypeSourceExampleOTLPConsoleFileNotes
service_namestringSERVICE_NAME env var or init param"sovdev-test-app"Service identifier
service_versionstringSERVICE_VERSION env var or init param (default "1.0.0")"1.0.0"Service version
scope_namestringservice name (NOT module name)"sovdev-test-app"OpenTelemetry instrumentation scope
scope_versionstringhardcoded "1.0.0""1.0.0"Library version

Critical: scope_name MUST use service name, NOT module/class name (__name__ in Python, etc.)

Correlation IDs

FieldTypeSourceExampleOTLPConsoleFileNotes
trace_idstring32-char hex from OTEL span"a511b23170d1efb01d110191712cb439"OpenTelemetry trace identifier (links related operations in distributed system)
span_idstring16-char hex from OTEL span"7bf8a401f109ebe9"OpenTelemetry span identifier (links to specific operation within trace)
event_idstringUUID v4 (lowercase, 36 chars)"dca7f112-1c94-478f-88f2-ec9805574190"Unique log entry identifier
session_idstringUUID v4 generated at init"18df09dd-c321-43d8-aa24-19dd7c149a56"Execution correlation - OpenTelemetry Resource attribute (groups all logs/metrics/traces from same run)

Note:

  • trace_id and span_id: Extracted from OpenTelemetry span context (hex format, no dashes)
  • event_id and session_id: Generated as UUID v4 (lowercase with hyphens)

Timestamps

FieldTypeSourceExampleOTLPConsoleFileNotes
timestampstringISO 8601 format"2025-10-07T08:34:22.398784+00:00"When log entry was created
observed_timestampstringnanoseconds since Unix epoch"1759826062404246784"When log was observed by OpenTelemetry

Format Requirements:

  • ISO 8601: YYYY-MM-DDTHH:mm:ss.ffffff+00:00 (Python) or YYYY-MM-DDTHH:mm:ss.SSSZ (TypeScript)
  • Nanoseconds: 19-digit integer string representing nanoseconds since 1970-01-01 00:00:00 UTC

Log Metadata

FieldTypeSourceExampleOTLPConsoleFileNotes
levelstringlowercase log level"info", "error"Human-readable level (file/console)
severity_textstringuppercase log level"INFO", "ERROR"OpenTelemetry severity text
severity_numberintegerOpenTelemetry severity9 (INFO), 17 (ERROR)OpenTelemetry severity number

Severity Number Mapping:

  • TRACE: 1
  • DEBUG: 5
  • INFO: 9
  • WARN: 13
  • ERROR: 17
  • FATAL: 21

Business Context

FieldTypeSourceExampleOTLPConsoleFileNotes
function_namestringprovided by developer"lookupCompany"Function where logging occurs
messagestringprovided by developer"Looking up company 123456789"Human-readable log message
log_typestring"transaction", "job.status", "job.progress""transaction"Type of log entry
peer_servicestringpeer service ID or INTERNAL"SYS1234567"Target system identifier

Data Fields

FieldTypeSourceExampleOTLPConsoleFileNotes
input_jsonstringJSON.stringify(input) or "null"'{"organisasjonsnummer":"123456789"}'Request/input data (serialized)
response_jsonstringJSON.stringify(response) or "null"'{"name":"Company AS"}'Response/output data (serialized)

Critical: Both fields MUST ALWAYS be present, even when no data exists (value "null" as string).

OpenTelemetry Metadata

FieldTypeSourceExampleOTLPConsoleFileNotes
telemetry_sdk_languagestringOpenTelemetry SDK"python", "nodejs"Language runtime identifier
telemetry_sdk_versionstringOpenTelemetry SDK"1.37.0", "1.28.0"OpenTelemetry SDK version

Exception Fields (ERROR/FATAL logs only)

FieldTypeSourceExampleOTLPConsoleFileNotes
exception_typestringALWAYS "Error""Error"Standardized across languages
exception_messagestringexception message"HTTP 404:"Exception message
exception_stacktracestringstack trace (max 350 chars)"Traceback (most recent call last):\n File..."Stack trace with security cleanup

Critical Standardization:

  • exception_type: MUST be "Error" for ALL languages (not "Exception", "Throwable", etc.)
  • Security: Stack traces MUST have credentials removed (auth headers, passwords, tokens)
  • Limit: Stack traces MUST be truncated to 350 characters maximum

Job Status Fields (log_type: "job.status")

Additional fields present in input_json for job status logs:

FieldTypeExampleNotes
job_namestring"CompanyLookupBatch"Human-readable job name
job_statusstring"Started", "Completed", "Failed"Job status

Message Format: "Job {job_status}: {job_name}"

Example input_json:

{
"job_name": "CompanyLookupBatch",
"job_status": "Started",
"total_companies": 4
}

Job Progress Fields (log_type: "job.progress")

Additional fields present in input_json for job progress logs:

FieldTypeExampleNotes
item_idstring"971277882"Identifier for current item
current_iteminteger25Current item number (1-based)
total_itemsinteger100Total number of items
progress_percentageinteger25Math.round((current/total) * 100)

Message Format: "Processing {item_id} ({current_item}/{total_items})"

Example input_json:

{
"item_id": "971277882",
"current_item": 25,
"total_items": 100,
"progress_percentage": 25,
"organisasjonsnummer": "971277882"
}

Console Output Format

Development Mode (Colored, Human-Readable)

2025-10-07 08:34:22 [ERROR] sovdev-test-company-lookup-python
Function: lookupCompany
Trace ID: a511b23170d1efb01d110191712cb439
Span ID: 7bf8a401f109ebe9
Session ID: 18df09dd-c321-43d8-aa24-19dd7c149a56
Error: HTTP 404:
Stack: Traceback (most recent call last):
File "/workspace/python/test/e2e/company-lookup/company-lookup.py", line 42

Format Rules:

  • Timestamp: YYYY-MM-DD HH:mm:ss
  • Level: Uppercase in brackets [ERROR]
  • Service: On same line as timestamp and level
  • Indentation: 2 spaces for details
  • Colors: Use ANSI color codes (ERROR=red, WARN=yellow, INFO=green, etc.)

Production Mode (JSON)

{
"timestamp": "2025-10-07T08:34:22.398784+00:00",
"level": "error",
"service_name": "sovdev-test-company-lookup-python",
"service_version": "1.0.0",
"session_id": "18df09dd-c321-43d8-aa24-19dd7c149a56",
"function_name": "lookupCompany",
"message": "Failed to lookup company 974652846",
"trace_id": "a511b23170d1efb01d110191712cb439",
"span_id": "7bf8a401f109ebe9",
"exception_type": "Error",
"exception_message": "HTTP 404:",
"exception_stacktrace": "Traceback..."
}

File Output Format (JSON Lines)

Each log entry is a single line of JSON with snake_case field names:

{"timestamp":"2025-10-07T08:34:22.398784+00:00","level":"error","service_name":"sovdev-test-company-lookup-python","service_version":"1.0.0","session_id":"18df09dd-c321-43d8-aa24-19dd7c149a56","peer_service":"SYS1234567","function_name":"lookupCompany","log_type":"transaction","message":"Failed to lookup company 974652846","trace_id":"a511b23170d1efb01d110191712cb439","span_id":"7bf8a401f109ebe9","event_id":"cf115688-513e-48fe-8049-538a515f608d","input_json":{"organisasjonsnummer":"974652846"},"response_json":null,"exception_type":"Error","exception_message":"HTTP 404:","exception_stacktrace":"Traceback..."}

Format Rules:

  • JSON Lines: One log entry per line (newline-delimited JSON)
  • snake_case: All field names use underscores
  • No Pretty Printing: Compact JSON (no whitespace)

OTLP Output Format

Logs are sent to OpenTelemetry Collector via OTLP protocol using snake_case field names. Field structure in Loki:

{
"scope_name": "sovdev-test-company-lookup-python",
"scope_version": "1.0.0",
"observed_timestamp": "1759823543622190848",
"severity_number": 17,
"severity_text": "ERROR",
"service_name": "sovdev-test-company-lookup-python",
"service_version": "1.0.0",
"session_id": "18df09dd-c321-43d8-aa24-19dd7c149a56",
"peer_service": "SYS1234567",
"function_name": "lookupCompany",
"log_type": "transaction",
"trace_id": "a511b23170d1efb01d110191712cb439",
"span_id": "7bf8a401f109ebe9",
"event_id": "cf115688-513e-48fe-8049-538a515f608d",
"input_json": "{\"organisasjonsnummer\":\"974652846\"}",
"response_json": "null",
"exception_type": "Error",
"exception_message": "HTTP 404:",
"exception_stacktrace": "Traceback...",
"telemetry_sdk_language": "python",
"telemetry_sdk_version": "1.37.0"
}

Format Rules:

  • Flat Structure: All fields at root level (no nesting)
  • snake_case: All field names use underscores (service_name, peer_service, session_id, function_name, log_type, etc.)
  • No Transformations: OTLP Collector receives fields as-is and passes them through unchanged to Loki

Field Presence Matrix

Summary of which fields appear in which outputs:

FieldOTLPConsoleFileAlways Present
service_name
service_version
scope_name✅ (OTLP only)
scope_version✅ (OTLP only)
trace_id
span_id❌ (when span active)
event_id
session_id✅ (OTLP Resource only)
timestamp
observed_timestamp✅ (OTLP only)
level
severity_text✅ (OTLP only)
severity_number✅ (OTLP only)
function_name
message
log_type
peer_service
input_json✅ (even when "null")
response_json✅ (even when "null")
exception_type❌ (ERROR/FATAL only)
exception_message❌ (ERROR/FATAL only)
exception_stacktrace❌ (ERROR/FATAL only)

Validation Rules

Required Field Validation

All implementations MUST validate that these fields are present in every log entry:

  • service_name, service_version
  • trace_id, event_id, session_id
  • timestamp, observed_timestamp (OTLP)
  • level (console/file) OR severity_text + severity_number (OTLP)
  • function_name, message, log_type
  • peer_service
  • input_json (even if "null")
  • response_json (even if "null")

Format Validation

  • trace_id: Must match regex ^[0-9a-f]{32}$ (32-char hex from OTEL span context)
  • span_id: Must match regex ^[0-9a-f]{16}$ (16-char hex from OTEL span context, optional)
  • UUID Fields (event_id, session_id): Must match regex ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
  • Timestamps: Must be valid ISO 8601 or nanoseconds since epoch
  • Log Levels: Must be one of: trace, debug, info, warn, error, fatal (lowercase)
  • Severity Text: Must be uppercase version of log level
  • Severity Number: Must map correctly to log level

Naming Convention Validation

  • snake_case: All field names MUST use underscores (service_name, function_name, log_type, etc.)
  • No dots: Dot notation (service.name, peer.service) is NOT allowed
  • No camelCase: camelCase notation (functionName, logType, traceId) is NOT allowed

Document Status: ✅ v1.0.0 COMPLETE Last Updated: 2025-10-27 Part of: sovdev-logger specification v1.1.0