@@ -54,6 +54,7 @@ import (
54
54
logtypepb "google.golang.org/genproto/googleapis/logging/type"
55
55
"google.golang.org/grpc/codes"
56
56
"google.golang.org/grpc/status"
57
+ "google.golang.org/protobuf/encoding/protojson"
57
58
"google.golang.org/protobuf/types/known/anypb"
58
59
"google.golang.org/protobuf/types/known/timestamppb"
59
60
)
@@ -967,65 +968,70 @@ func toLogEntryInternalImpl(e Entry, l *Logger, parent string, skipLevels int) (
967
968
// entry represents the fields of a logging.Entry that can be parsed by Logging agent.
968
969
// See the mappings at https://cloud.google.com/logging/docs/structured-logging#special-payload-fields
969
970
type structuredLogEntry struct {
970
- // JsonMessage map[string]interface{} `json:"message,omitempty"`
971
- // TextMessage string `json:"message,omitempty"`
972
- Message json.RawMessage `json:"message"`
973
- Severity string `json:"severity,omitempty"`
974
- HTTPRequest * logtypepb.HttpRequest `json:"httpRequest,omitempty"`
975
- Timestamp string `json:"timestamp,omitempty"`
976
- Labels map [string ]string `json:"logging.googleapis.com/labels,omitempty"`
977
- InsertID string `json:"logging.googleapis.com/insertId,omitempty"`
978
- Operation * logpb.LogEntryOperation `json:"logging.googleapis.com/operation,omitempty"`
979
- SourceLocation * logpb.LogEntrySourceLocation `json:"logging.googleapis.com/sourceLocation,omitempty"`
980
- SpanID string `json:"logging.googleapis.com/spanId,omitempty"`
981
- Trace string `json:"logging.googleapis.com/trace,omitempty"`
982
- TraceSampled bool `json:"logging.googleapis.com/trace_sampled,omitempty"`
971
+ Message json.RawMessage `json:"message"`
972
+ Severity string `json:"severity,omitempty"`
973
+ HTTPRequest * structuredLogEntryHTTPRequest `json:"httpRequest,omitempty"`
974
+ Timestamp string `json:"timestamp,omitempty"`
975
+ Labels map [string ]string `json:"logging.googleapis.com/labels,omitempty"`
976
+ InsertID string `json:"logging.googleapis.com/insertId,omitempty"`
977
+ Operation * structuredLogEntryOperation `json:"logging.googleapis.com/operation,omitempty"`
978
+ SourceLocation * structuredLogEntrySourceLocation `json:"logging.googleapis.com/sourceLocation,omitempty"`
979
+ SpanID string `json:"logging.googleapis.com/spanId,omitempty"`
980
+ Trace string `json:"logging.googleapis.com/trace,omitempty"`
981
+ TraceSampled bool `json:"logging.googleapis.com/trace_sampled,omitempty"`
983
982
}
984
983
985
- func convertSnakeToMixedCase (snakeStr string ) string {
986
- words := strings .Split (snakeStr , "_" )
987
- mixedStr := words [0 ]
988
- for _ , word := range words [1 :] {
989
- mixedStr += strings .Title (word )
990
- }
991
- return mixedStr
984
+ // structuredLogEntryHTTPRequest wraps the HTTPRequest proto field in structuredLogEntry for easier JSON marshalling.
985
+ type structuredLogEntryHTTPRequest struct {
986
+ request * logtypepb.HttpRequest
992
987
}
993
988
994
- func (s structuredLogEntry ) MarshalJSON () ([]byte , error ) {
995
- // extract structuredLogEntry into json map
996
- type Alias structuredLogEntry
997
- var mapData map [string ]interface {}
998
- data , err := json .Marshal (Alias (s ))
999
- if err == nil {
1000
- err = json .Unmarshal (data , & mapData )
1001
- }
1002
- if err == nil {
1003
- // ensure all inner dicts use mixed case instead of snake case
1004
- innerDicts := [3 ]string {"httpRequest" , "logging.googleapis.com/operation" , "logging.googleapis.com/sourceLocation" }
1005
- for _ , field := range innerDicts {
1006
- if fieldData , ok := mapData [field ]; ok {
1007
- formattedFieldData := make (map [string ]interface {})
1008
- for k , v := range fieldData .(map [string ]interface {}) {
1009
- formattedFieldData [convertSnakeToMixedCase (k )] = v
1010
- }
1011
- mapData [field ] = formattedFieldData
1012
- }
1013
- }
1014
- // serialize json map into raw bytes
1015
- return json .Marshal (mapData )
1016
- }
1017
- return data , err
989
+ func (s structuredLogEntryHTTPRequest ) MarshalJSON () ([]byte , error ) {
990
+ return protojson .Marshal (s .request )
991
+ }
992
+
993
+ // structuredLogEntryOperation wraps the Operation proto field in structuredLogEntry for easier JSON marshalling.
994
+ type structuredLogEntryOperation struct {
995
+ operation * logpb.LogEntryOperation
996
+ }
997
+
998
+ func (s structuredLogEntryOperation ) MarshalJSON () ([]byte , error ) {
999
+ return protojson .Marshal (s .operation )
1000
+ }
1001
+
1002
+ // structuredLogEntrySourceLocation wraps the SourceLocation proto field in structuredLogEntry for easier JSON marshalling.
1003
+ type structuredLogEntrySourceLocation struct {
1004
+ sourceLocation * logpb.LogEntrySourceLocation
1005
+ }
1006
+
1007
+ func (s structuredLogEntrySourceLocation ) MarshalJSON () ([]byte , error ) {
1008
+ return protojson .Marshal (s .sourceLocation )
1018
1009
}
1019
1010
1020
1011
func serializeEntryToWriter (entry * logpb.LogEntry , w io.Writer ) error {
1012
+ var httpRequest * structuredLogEntryHTTPRequest
1013
+ if entry .HttpRequest != nil {
1014
+ httpRequest = & structuredLogEntryHTTPRequest {entry .HttpRequest }
1015
+ }
1016
+
1017
+ var operation * structuredLogEntryOperation
1018
+ if entry .Operation != nil {
1019
+ operation = & structuredLogEntryOperation {entry .Operation }
1020
+ }
1021
+
1022
+ var sourceLocation * structuredLogEntrySourceLocation
1023
+ if entry .SourceLocation != nil {
1024
+ sourceLocation = & structuredLogEntrySourceLocation {entry .SourceLocation }
1025
+ }
1026
+
1021
1027
jsonifiedEntry := structuredLogEntry {
1022
1028
Severity : entry .Severity .String (),
1023
- HTTPRequest : entry . HttpRequest ,
1029
+ HTTPRequest : httpRequest ,
1024
1030
Timestamp : entry .Timestamp .String (),
1025
1031
Labels : entry .Labels ,
1026
1032
InsertID : entry .InsertId ,
1027
- Operation : entry . Operation ,
1028
- SourceLocation : entry . SourceLocation ,
1033
+ Operation : operation ,
1034
+ SourceLocation : sourceLocation ,
1029
1035
SpanID : entry .SpanId ,
1030
1036
Trace : entry .Trace ,
1031
1037
TraceSampled : entry .TraceSampled ,
0 commit comments