This document describes how Google Cloud Observability determines the fields of a
LogEntry from the OTLP log record, when that record is sent
to Google Cloud by using the Telemetry API.
General structure of OTLP-formatted log data
When log data is sent to Google Cloud by using the Telemetry API, this data must be in a format that is consistent with OTLP. The general structure for this data is as shown:
"resourceLogs": [
{
"resource": {
"attributes": [...]
},
"scopeLogs": [
{
"logRecords": [...]
}
]
}
]
Notice that OpenTelemetry batches individual logs, each of which is represented by
a logRecord structure, with information about the source of those logs,
which is represented by the resource structure.
When Google Cloud Observability receives a resourceLogs object, it constructs one
LogEntry for each logRecord. Unlike OTLP which batches source
information with a collection of individual logs, each LogEntry structure
contains information about the source of the log and the log itself.
To learn more about the structure of OTLP-formatted log data,
see the OpenTelemetry logs.proto.
How LogEntry fields are set
Google Cloud Observability uses the following rules to determine the values for
LogEntry fields:
LogEntry field(Names from HTTP reference) |
How the system determines the field value |
|---|---|
logName |
The system uses the following prioritized list of OpenTelemetry log record attributes to determine the log name:
Log names must be URL-safe or they are URL-encoded during ingestion. |
resource |
The system uses the information set in the resource
field or it infers the resource. For details, see
OTLP attributes to resource type mapping. |
timestamp |
The system uses the following prioritized list of OpenTelemetry
log record fields to determine the
The retention period for the log bucket that stores the data determines the oldest timestamp that can be ingested. For more information, see Cloud Logging quotas. |
receiveTimestamp |
Set to the time the LogEntry is ingested. |
severity |
The system maps the OpenTelemetry severity in the log record to a Cloud Logging severity. For details, see Severity field. |
httpRequest |
The system maps the FIXME. There are other fields that get mapped to this field. |
labels |
The system sets this field by using the log record attributes values. For more information, see Labels field. |
trace |
The system sets this field to the value from the log record's
traceId field. The value must be a
valid 32 char hex string, or the entry is rejected. |
spanId |
The system sets this field to the value from the log record's
spanId field. The value must be a
valid 16 char hex string, or the entry is rejected. |
traceSampled |
Not set. |
sourceLocation |
The system sets this field to the values from the log record's Code attributes. For more information, see SourceLocation field. |
split |
Not set. |
apphubapphubDestinationapphubSource |
Not set. |
otel |
For fields in OTLP log data that don't have an equivalent field in a
LogEntry, the system converts data types and then adds
the converted data to the otel field. For more information,
see Otel field. |
| Payload | The system sets the payload by converting the body of a log record to an appropriate payload type. For more information, see Payload field. |
HttpRequest field
Google Cloud Observability maps OTLP attributes that apply to HTTP requests to
LogEntry fields. The following sections describe how the system maps
flat and nested attributes.
Flat attributes
The following table describes how Google Cloud Observability maps flat attributes that apply
to HTTP requests to LogEntry fields.
For example, the value from the attribute http.request.method: "GET", is set
as the value of the httpRequest.requestMethod field in a log entry:
OpenTelemetryLogRecord.attributekey-value pair. |
Value stored in the followingLogEntry field(Names from HTTP reference) |
Accepted Type |
|---|---|---|
http.request.method
|
httpRequest.requestMethod |
string |
url.fullhttp.url
|
httpRequest.requestUrl |
string |
http.request.body.size |
httpRequest.requestSize |
string, int |
http.response.status_code |
httpRequest.status |
string, int |
http.response.body.size |
httpRequest.responseSize |
string, int |
user_agent.originalhttp.user_agent
|
httpRequest.userAgent |
string |
client.address |
remoteIp |
string |
server.address |
serverIp |
string |
referrer |
httpRequest.referer |
string |
latency |
httpRequest.latency |
string, int |
cacheLookup |
httpRequest.cacheLookup |
bool |
cacheHit |
httpRequest.cacheHit |
bool |
cacheValidatedWithOriginServer |
httpRequest.cacheValidatedWithOriginServer |
bool |
cacheFillBytes |
httpRequest.cacheFillBytes |
string, int |
network.protocol.versionprotocol
|
httpRequest.protocol |
string |
Nested attributes
This section describes how Google Cloud Observability maps nested OTLP attributes that
apply to HTTP requests to fields in a LogEntry. The following example
illustrates a log record that contains two attributes, each of which contains
at least one other attribute:
log_record {
attributes: {
gcp.http_request {
"requestMethod": "GET",
"requestUrl": "some-URL",
}
http_request {
"requestMethod": "GET",
}
}
}
In the table, the nested attributes are shown by using braces. For example,
gcp.http_request {requestMethod} means that the attribute
gcp.http_request contains the attribute requestMethod. The value from the
innermost attribute is assigned to the value of the log entry field:
OpenTelemetryLogRecord.attributekey-value pair. |
Value stored in the followingLogEntry field(Names from HTTP reference) |
Accepted Type |
|---|---|---|
gcp.http_request {requestMethod}http_request {requestMethod}
|
httpRequest.requestMethod |
string |
gcp.http_request {requestUrl}http_request {requestUrl}
|
httpRequest.requestUrl |
string |
gcp.http_request {requestSize}http_request {requestSize}
|
httpRequest.requestSize |
string, int |
gcp.http_request {status}http_request {status}
|
httpRequest.status |
string, int |
gcp.http_request {responseSize}http_request {responseSize}
|
httpRequest.responseSize |
string, int |
gcp.http_request {userAgent}http_request {userAgent}
|
httpRequest.userAgent |
string |
gcp.http_request {remoteIp}http_request {remoteIp}
|
httpRequest.remoteIp |
string |
gcp.http_request {serverIp}http_request {serverIp}
|
httpRequest.serverIp |
string |
gcp.http_request {referer}http_request {referrer}
|
httpRequest.referer |
string |
gcp.http_request {latency}http_request {latency}
|
httpRequest.latency |
string, int |
gcp.http_request {cacheLookup}http_request {cacheLookup}
|
httpRequest.cacheLookup |
bool |
gcp.http_request {cacheHit}http_request {cacheHit}
|
httpRequest.cacheHit |
bool |
gcp.http_request {http_request {
|
httpRequest.cacheValidatedWithOriginServer |
bool |
gcp.http_request {cacheFillBytes}http_request {cacheFillBytes}
|
httpRequest.cacheFillBytes |
string, int |
gcp.http_request {protocol}http_request {protocol}
|
httpRequest.protocol |
string |
Labels field
To determine what labels to attach to the log entry, the system performs the following actions:
It removes from the OTLP log record any attributes that have been mapped to specific
LogEntryfields.For example, suppose there are the attributes attached to a log record:
attributes: { "log_array_attr: ["value1", "value2"], "log_json_attr": {"json_key": "json_value"} "log-string-attr": "string", "code.file.path": "my-file.cc", "code.function.name: "my-func", "code.line.number": 123, "gcp.http_request": { "requestMethod": "GET", "requestUrl": "my-URL", }, }After removing fields that are mapped to specific
LogEntryfields, the following fields remain:attributes: { "log_array_attr: ["value1", "value2"], "log_json_attr": {"json_key": "json_value"} "log-string-attr": "string", }If an attribute contains an array or JSON elements, then the system converts the value into a string.
For example, the following illustrates how the
LogEntryrepresents the previous attributes:labels: { "log_array_attr": "[\"value1\",\"value2\"]", "log_json_attr": "{\"json_key\":\"json_value\"}", "log-string-attr": "string", }The maximum nesting depth for attributes is five. Any content that has deeper nesting is truncated.
Otel field
For fields in OTLP log data that don't have an equivalent field in a
LogEntry, the system converts data types and then adds
the converted data to the otel field. For example, the otel field
stores attributes from the resource, scope, and entity fields.
The system uses the following rules to convert the
OpenTelemetry data types
to protobuf Value types:
| OpenTelemetry type | protobuf type |
|---|---|
string |
string |
boolean |
bool |
integer |
double |
float |
double |
Array |
ListValues |
KeyValueList |
Struct |
To avoid double precision errors, pass integers as strings.
Payload field
The data type of the OTLP logRecord.body field determines the structure
of the LogEntry payload:
string: The system copies the string into theLogEntry.textPayloadfield.Array: The system creates a string of the array elements while preserving new lines. It then copies the string into theLogEntry.textPayloadfield.KeyValueList: The system converts those pairs into JSON and then populates theLogEntry.jsonPayloadfield, with the following restrictions:- When an OTLP record contains duplicate attribute keys, the system retains the first key and discards attributes with duplicate keys.
- When the nesting depth for a JSON pair is larger than five, the system truncates the content to a depth of five.
Severity field
This section describes how Google Cloud Observability maps the OpenTelemetry severity fields
to Cloud Logging severity levels.
OpenTelemetry defines a severity number and severity text. The
logs.proto defines the severity numbers.
Google Cloud Observability determines the Logging severity from the
OpenTelemetry severity number, if set. Otherwise, it uses the severity text. If
neither are set, then the Logging severity is set to DEFAULT.
| OpenTelemetry severity number Enum (value) |
OpenTelemetry severity text (tests are case insensitive) |
Cloud Logging severity Enum (value) |
|---|---|---|
SEVERITY_NUMBER_UNSPECIFIED (0) |
"default" not set |
DEFAULT (0) |
SEVERITY_NUMBER_TRACE (1)SEVERITY_NUMBER_TRACE2 (2)SEVERITY_NUMBER_TRACE3 (3)SEVERITY_NUMBER_TRACE4 (4) |
"trace" "trace2" "trace3" "trace4" |
DEBUG (100) |
SEVERITY_NUMBER_DEBUG (5)SEVERITY_NUMBER_DEBUG2 (6)SEVERITY_NUMBER_DEBUG3 (7)SEVERITY_NUMBER_DEBUG4 (8) |
"debug" "debug2" "debug3" "debug4" |
DEBUG (100) |
SEVERITY_NUMBER_INFO (9)SEVERITY_NUMBER_INFO2 (10) |
"info" "info2" |
INFO (200) |
SEVERITY_NUMBER_INFO3 (11)SEVERITY_NUMBER_INFO4 (12) |
"notice" "info3" "info4" |
NOTICE (300) |
SEVERITY_NUMBER_WARN (13)SEVERITY_NUMBER_WARN2 (14)SEVERITY_NUMBER_WARN3 (15)SEVERITY_NUMBER_WARN4 (16) |
"warning" "warn" "warn2" "warn3" "warn4" |
WARNING (400) |
SEVERITY_NUMBER_ERROR (17)SEVERITY_NUMBER_ERROR2 (18)SEVERITY_NUMBER_ERROR3 (19)SEVERITY_NUMBER_ERROR4 (20) |
"error" "error2" "error3" "error4" |
ERROR (500) |
SEVERITY_NUMBER_FATAL (21)SEVERITY_NUMBER_FATAL2 (22) |
"critical" "fatal" "fatal2" |
CRITICAL (600) |
SEVERITY_NUMBER_FATAL3 (23) |
"alert" "fatal3" |
ALERT (700) |
SEVERITY_NUMBER_FATAL4 (24) |
"emergency" "fatal4" |
EMERGENCY (800) |
SourceLocation field
Google Cloud Observability maps the following OTLP Code
directly to LogEntry fields. This mapping is possible because these
OpenTelemetry attributes are semantically identical to Cloud Logging concepts.
OpenTelemetryLogRecord.attributekey-value pair. |
Value stored in the followingLogEntry field(Names from HTTP reference) |
Accepted Type |
|---|---|---|
code.file.path: Value |
sourceLocation.file |
string |
code.function.name: Value |
sourceLocation.function |
string |
code.function.number: Value |
sourceLocation.line |
string, int |
Limitations
This section describes limits. It also describes how Google Cloud Observability handles certain types of data.
Limits
| Description | Value | Notes |
|---|---|---|
| Maximum number of logs per OTLP request | 8192 | Refers to the maximum number of logRecords in an
OTLP resourceLogs structure. Limit. |
| Maximum size of each request | 5 MiB | Limit. |
Maximum size of a LogEntrythat is created from an OTLP log record |
256 KiB | Cloud Logging truncates or discards data from an OTLP log record when necessary. Limit. |
| Maximum length of an attribute key | 512 B | Oversized label keys are truncated when the OTLP log record is converted
into a LogEntry. Limit. |
| Maximum length of an attribute value | 64 KiB | Oversized label values when the OTLP log record is converted into a
LogEntry. Limit. |
| Maximum depth of attribute nesting | 5 | Attributes that exceed this limit are truncated when the OTLP log record is
converted into a LogEntry. |
| Maximum number of log-ingestion bytes per minute | 2.4 GB for the following regions: 300 MB for all other regions. |
Quota. |
Behavior
When both the OpenTelemetry severity number and severity text are set, the system uses the severity number to determine the Cloud Logging severity level. If the OTLP record doesn't contain severity information, then the Cloud Logging severity level is set to
DEFAULT.When an OTLP record contains duplicate attribute keys, the system retains the first key and discards the attributes with duplicate keys.
The system converts attributes attached to a log record into a string. For an example, see Labels field.
Log names must be URL-safe or they are URL-encoded during ingestion. For information about how log names are set, see How
LogEntryfields are set.