Skip to content

Commit 3ade00c

Browse files
authored
adds custom durationFieldFunc to request/response log entries (#670)
the request and response log messages include a duration string, but does not make use of the `durationFieldFunc` like other parts of the request lifecycle. The `durationFieldFunc` function is useful when conducting log analysis with log aggregator tools out there, because it normalizes the value to a number that can be filtered by or compared to. For example, a GCP Log Explorer does not support converting log field types like a duration to an integer, so you cannot run queries like "give me all logs that took more than 50ms" because it would be interpreted as a string comparison. This makes very tedious to audit application logs that log API calls using this gRPC middleware. The perhaps controversial part of this change is that request/response logs have a different naming convention for the duration. I personally don't find use for a different field name - grpc.time and grpc.time_ms would seem expressive enough to support the 4 logged entries, but maybe I'm missing something here. I would suggest to rename those fields as well, but I understand that may be a "breaking change", if we consider the log fields a contract.
1 parent 9a90441 commit 3ade00c

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

interceptors/logging/interceptors.go

+4
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func (c *reporter) PostMsgSend(payload any, err error, duration time.Duration) {
7171
}
7272

7373
fields = fields.AppendUnique(Fields{"grpc.send.duration", duration.String(), "grpc.request.content", p})
74+
fields = fields.AppendUnique(c.opts.durationFieldFunc(duration))
7475
c.logger.Log(c.ctx, logLvl, "request sent", fields...)
7576
} else {
7677
p, ok := payload.(proto.Message)
@@ -85,6 +86,7 @@ func (c *reporter) PostMsgSend(payload any, err error, duration time.Duration) {
8586
}
8687

8788
fields = fields.AppendUnique(Fields{"grpc.send.duration", duration.String(), "grpc.response.content", p})
89+
fields = fields.AppendUnique(c.opts.durationFieldFunc(duration))
8890
c.logger.Log(c.ctx, logLvl, "response sent", fields...)
8991
}
9092
}
@@ -116,6 +118,7 @@ func (c *reporter) PostMsgReceive(payload any, err error, duration time.Duration
116118
}
117119

118120
fields = fields.AppendUnique(Fields{"grpc.recv.duration", duration.String(), "grpc.request.content", p})
121+
fields = fields.AppendUnique(c.opts.durationFieldFunc(duration))
119122
c.logger.Log(c.ctx, logLvl, "request received", fields...)
120123
} else {
121124
p, ok := payload.(proto.Message)
@@ -130,6 +133,7 @@ func (c *reporter) PostMsgReceive(payload any, err error, duration time.Duration
130133
}
131134

132135
fields = fields.AppendUnique(Fields{"grpc.recv.duration", duration.String(), "grpc.response.content", p})
136+
fields = fields.AppendUnique(c.opts.durationFieldFunc(duration))
133137
c.logger.Log(c.ctx, logLvl, "response received", fields...)
134138
}
135139
}

interceptors/logging/interceptors_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ func (s *loggingPayloadSuite) TestPingError_LogsOnlyRequestsOnError() {
537537

538538
clientRequestFields.AssertFieldNotEmpty(s.T(), "grpc.start_time").
539539
AssertFieldNotEmpty(s.T(), "grpc.send.duration").
540+
AssertFieldNotEmpty(s.T(), "grpc.time_ms").
540541
AssertField(s.T(), "grpc.request.content", `{"value":"something","errorCodeReturned":4}`).
541542
AssertFieldNotEmpty(s.T(), "grpc.request.deadline").AssertNoMoreTags(s.T())
542543
}
@@ -580,6 +581,7 @@ func (s *loggingPayloadSuite) assertPayloadLogLinesForMessage(lines LogLines, me
580581
clientRequestFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientRequestLogLine.fields, method, typ)
581582
clientRequestFields.AssertFieldNotEmpty(s.T(), "grpc.start_time").
582583
AssertFieldNotEmpty(s.T(), "grpc.send.duration").
584+
AssertFieldNotEmpty(s.T(), "grpc.time_ms").
583585
AssertField(s.T(), "grpc.request.content", `{"value":"something","sleepTimeMs":9999}`).
584586
AssertFieldNotEmpty(s.T(), "grpc.request.deadline").AssertNoMoreTags(s.T())
585587
}
@@ -591,6 +593,7 @@ func (s *loggingPayloadSuite) assertPayloadLogLinesForMessage(lines LogLines, me
591593
clientResponseFields := assertStandardFields(s.T(), logging.KindClientFieldValue, clientResponseLogLine.fields, method, typ)
592594
clientResponseFields = clientResponseFields.AssertFieldNotEmpty(s.T(), "grpc.start_time").
593595
AssertFieldNotEmpty(s.T(), "grpc.recv.duration").
596+
AssertFieldNotEmpty(s.T(), "grpc.time_ms").
594597
AssertFieldNotEmpty(s.T(), "grpc.request.deadline")
595598
if i-curr == 0 {
596599
clientResponseFields = clientResponseFields.AssertField(s.T(), "grpc.response.content", `{"value":"something"}`)
@@ -609,6 +612,7 @@ func (s *loggingPayloadSuite) assertPayloadLogLinesForMessage(lines LogLines, me
609612
AssertFieldNotEmpty(s.T(), "grpc.start_time").
610613
AssertFieldNotEmpty(s.T(), "grpc.recv.duration").
611614
AssertFieldNotEmpty(s.T(), "grpc.request.deadline").
615+
AssertFieldNotEmpty(s.T(), "grpc.time_ms").
612616
AssertField(s.T(), "grpc.request.content", `{"value":"something","sleepTimeMs":9999}`).AssertNoMoreTags(s.T())
613617
}
614618
curr += repetitions
@@ -620,6 +624,7 @@ func (s *loggingPayloadSuite) assertPayloadLogLinesForMessage(lines LogLines, me
620624
serverResponseFields = serverResponseFields.AssertFieldNotEmpty(s.T(), "peer.address").
621625
AssertFieldNotEmpty(s.T(), "grpc.start_time").
622626
AssertFieldNotEmpty(s.T(), "grpc.send.duration").
627+
AssertFieldNotEmpty(s.T(), "grpc.time_ms").
623628
AssertFieldNotEmpty(s.T(), "grpc.request.deadline")
624629
if i-curr == 0 {
625630
serverResponseFields = serverResponseFields.AssertField(s.T(), "grpc.response.content", `{"value":"something"}`)

0 commit comments

Comments
 (0)