in receiver/googlecloudpubsubreceiver/internal/log_entry.go [114:262]
func TranslateLogEntry(data []byte) (pcommon.Resource, plog.LogRecord, error) {
lr := plog.NewLogRecord()
res := pcommon.NewResource()
var src map[string]stdjson.RawMessage
err := json.Unmarshal(data, &src)
if err != nil {
return res, lr, err
}
resAttrs := res.Attributes()
attrs := lr.Attributes()
for k, v := range src {
// Pick out some keys for special handling, and let the rest
// pass through to be translated according to the schema.
switch k {
// Unpack as suggested in the logs data model appendix
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model-appendix.md#google-cloud-logging
case "insertId":
// timestamp -> Attributes[“log.record.uid”]
// see: https://github.com/open-telemetry/semantic-conventions/blob/main/model/logs/general.yaml
var insertID string
err = json.Unmarshal(v, &insertID)
if err != nil {
return res, lr, err
}
attrs.PutStr("log.record.uid", insertID)
delete(src, k)
case "timestamp":
// timestamp -> Timestamp
var t time.Time
err = json.Unmarshal(v, &t)
if err != nil {
return res, lr, err
}
lr.SetTimestamp(pcommon.NewTimestampFromTime(t))
delete(src, k)
case "receiveTimestamp":
// timestamp -> Timestamp
var t time.Time
err = json.Unmarshal(v, &t)
if err != nil {
return res, lr, err
}
lr.SetObservedTimestamp(pcommon.NewTimestampFromTime(t))
delete(src, k)
case "resource":
// resource -> Resource
// mapping type -> gcp.resource_type
// labels -> gcp.<label>
var protoRes monitoredres.MonitoredResource
err = protojson.Unmarshal(v, &protoRes)
if err != nil {
return res, lr, err
}
resAttrs.EnsureCapacity(len(protoRes.GetLabels()) + 1)
resAttrs.PutStr("gcp.resource_type", protoRes.GetType())
for k, v := range protoRes.GetLabels() {
resAttrs.PutStr(strcase.ToSnakeWithIgnore(fmt.Sprintf("gcp.%v", k), "."), v)
}
delete(src, k)
case "logName":
var logName string
err = json.Unmarshal(v, &logName)
if err != nil {
return res, lr, err
}
// log_name -> Attributes[“gcp.log_name”]
attrs.PutStr("gcp.log_name", logName)
delete(src, k)
case "jsonPayload", "textPayload":
// {json,proto,text}_payload -> Body
var payload any
err = json.Unmarshal(v, &payload)
if err != nil {
return res, lr, err
}
// Note: json.Unmarshal will turn a bare string into a
// go string, so this call will correctly set the body
// to a string Value.
_ = lr.Body().FromRaw(payload)
delete(src, k)
case "protoPayload":
// {json,proto,text}_payload -> Body
err = translateInto(lr.Body().SetEmptyMap(), (&anypb.Any{}).ProtoReflect().Descriptor(), v)
if err != nil {
return res, lr, err
}
delete(src, k)
case "severity":
var severity string
err = json.Unmarshal(v, &severity)
if err != nil {
return res, lr, err
}
// severity -> Severity
// According to the spec, this is the original string representation of
// the severity as it is known at the source:
// https://opentelemetry.io/docs/reference/specification/logs/data-model/#field-severitytext
lr.SetSeverityText(severity)
lr.SetSeverityNumber(cloudLoggingSeverityToNumber(severity))
delete(src, k)
case "trace":
var trace string
err = json.Unmarshal(v, &trace)
if err != nil {
return res, lr, err
}
lr.SetTraceID(cloudLoggingTraceToTraceIDBytes(trace))
delete(src, k)
case "spanId":
var spanID string
err = json.Unmarshal(v, &spanID)
if err != nil {
return res, lr, err
}
lr.SetSpanID(spanIDStrToSpanIDBytes(spanID))
delete(src, k)
case "labels":
var labels map[string]string
err = json.Unmarshal(v, &labels)
if err != nil {
return res, lr, err
}
// labels -> Attributes
for k, v := range labels {
attrs.PutStr(k, v)
}
delete(src, k)
case "httpRequest":
httpRequestAttrs := attrs.PutEmptyMap("gcp.http_request")
err = translateInto(httpRequestAttrs, getLogEntryDescriptor().Fields().ByJSONName(k).Message(), v, snakeifyKeys)
if err != nil {
return res, lr, err
}
delete(src, k)
default:
}
}
// All other fields -> Attributes["gcp.*"]
// At this point we cleared all the fields that have special handling;
// translate the rest into the attributes map.
_ = translateInto(attrs, getLogEntryDescriptor(), src, preserveDst, prefixKeys("gcp."), snakeifyKeys)
return res, lr, nil
}