Skip to content

Commit 76c9844

Browse files
authored
feature: remove labels and traceId - put them in payload (#224)
Added new constants Improved (fixed) HTTP logging logic More doc cleanup
1 parent 462075d commit 76c9844

File tree

10 files changed

+314
-145
lines changed

10 files changed

+314
-145
lines changed

pkgs/google_cloud/CHANGELOG.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
1-
## 0.4.0-wip
1+
## 0.4.0
22

3-
### BREAKING CHANGES
3+
### `constants.dart`
44

5-
- Renamed `RequestLogger` to `CloudLogger` and moved it to
6-
`package:google_cloud/general.dart`.
5+
- Added `logSpanIdKey`, `logTraceKey`, and `logTraceSampledKey`.
76

8-
### New Features
7+
### `general.dart`
98

10-
- `CloudLogger` is no longer abstract and has a default implementation that
11-
prints to stdout.
12-
- Added `payload`, `labels`, and `stackTrace` named parameters to
13-
`CloudLogger` functions as well as `structuredLogEntry`.
9+
- **BREAKING** `structuredLogEntry` removed `traceId` parameter. Use the *new*
10+
`payload` parameter with the `logTraceKey` constant as a key.
1411
- Hardened structured log JSON serialization with automatic fallback mechanisms
1512
to safely handle native `toJson()` implementations and circular references
1613
without failing.
1714

15+
- Added `CloudLogger` (renamed from `RequestLogger`).
16+
- Added optional `payload` and `stackTrace` named parameters to
17+
`CloudLogger` functions.
18+
- `CloudLogger` is no longer abstract and has a default implementation that
19+
prints to stdout.
20+
21+
### `http_serving.dart`
22+
23+
- **BREAKING** Renamed `RequestLogger` to `CloudLogger` and moved it to
24+
`package:google_cloud/general.dart`.
25+
- Refactored HTTP logging logic to handle `spanId` and `traceSampled`.
26+
1827
## 0.3.1
1928

2029
- Fix a bug where `projectIdFromGcloudConfig()` used the incorrect gcloud shell

pkgs/google_cloud/lib/constants.dart

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,4 @@
1515
/// Constants for Google Cloud Platform integration.
1616
library;
1717

18-
export 'src/constants.dart'
19-
show
20-
cloudTraceContextHeader,
21-
configurationEnvironmentVariable,
22-
credentialsPathEnvironmentVariable,
23-
defaultListenPort,
24-
metadataFlavorHeaders,
25-
portEnvironmentVariable,
26-
projectIdEnvironmentVariable,
27-
projectIdEnvironmentVariableOptions,
28-
revisionEnvironmentVariable,
29-
serviceEnvironmentVariable;
18+
export 'src/constants.dart';

pkgs/google_cloud/lib/http_serving.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ export 'src/serving/http_logging.dart'
6161
currentLogger;
6262
export 'src/serving/serve.dart' show listenPortFromEnvironment, serveHandler;
6363
export 'src/serving/terminate.dart' show waitForTerminate;
64+
export 'src/serving/trace_context_data.dart' show TraceContextData;

pkgs/google_cloud/lib/src/constants.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,32 @@ const cloudTraceContextHeader = 'x-cloud-trace-context';
5555
const metadataFlavorHeaders = {'Metadata-Flavor': 'Google'};
5656

5757
/// The name of the Cloud Run service being run.
58+
///
59+
/// See https://docs.cloud.google.com/run/docs/container-contract#services-env-vars
5860
const serviceEnvironmentVariable = 'K_SERVICE';
5961

6062
/// The name of the Cloud Run revision being run.
63+
///
64+
/// See https://docs.cloud.google.com/run/docs/container-contract#services-env-vars
6165
const revisionEnvironmentVariable = 'K_REVISION';
6266

6367
/// The name of the Cloud Run configuration being run.
68+
///
69+
/// See https://docs.cloud.google.com/run/docs/container-contract#services-env-vars
6470
const configurationEnvironmentVariable = 'K_CONFIGURATION';
71+
72+
/// The `payload` key used to correlate log entries with Cloud Trace.
73+
///
74+
/// See https://docs.cloud.google.com/logging/docs/agent/logging/configuration#special-fields
75+
const logTraceKey = 'logging.googleapis.com/trace';
76+
77+
/// The `payload` key used to correlate log entries with a specific span within
78+
/// a Cloud Trace.
79+
///
80+
/// See https://docs.cloud.google.com/logging/docs/agent/logging/configuration#special-fields
81+
const logSpanIdKey = 'logging.googleapis.com/spanId';
82+
83+
/// The `payload` key used to indicate whether a trace is sampled.
84+
///
85+
/// See https://docs.cloud.google.com/logging/docs/agent/logging/configuration#special-fields
86+
const logTraceSampledKey = 'logging.googleapis.com/trace_sampled';

pkgs/google_cloud/lib/src/logger.dart

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ abstract base class CloudLogger {
6666
/// This logger prints messages to the console.
6767
///
6868
/// The output format is:
69-
/// `[SEVERITY_NAME: ]<message>[ payload][ labels][\nstack_trace]`
69+
/// `[SEVERITY_NAME: ]<message>[ payload][\nstack_trace]`
7070
///
7171
/// The `SEVERITY_NAME: ` prefix is omitted when the severity is
7272
/// [LogSeverity.defaultSeverity].
@@ -85,7 +85,6 @@ abstract base class CloudLogger {
8585
Object message,
8686
LogSeverity severity, {
8787
Map<String, Object?>? payload,
88-
Map<String, String>? labels,
8988
StackTrace? stackTrace,
9089
});
9190

@@ -95,45 +94,31 @@ abstract base class CloudLogger {
9594
void debug(
9695
Object message, {
9796
Map<String, Object?>? payload,
98-
Map<String, String>? labels,
9997
StackTrace? stackTrace,
100-
}) => log(
101-
message,
102-
LogSeverity.debug,
103-
payload: payload,
104-
labels: labels,
105-
stackTrace: stackTrace,
106-
);
98+
}) =>
99+
log(message, LogSeverity.debug, payload: payload, stackTrace: stackTrace);
107100

108101
/// Logs [message] at [LogSeverity.info] severity.
109102
///
110103
/// {@macro google_cloud.CloudLogger.log_params}
111104
void info(
112105
Object message, {
113106
Map<String, Object?>? payload,
114-
Map<String, String>? labels,
115107
StackTrace? stackTrace,
116-
}) => log(
117-
message,
118-
LogSeverity.info,
119-
payload: payload,
120-
labels: labels,
121-
stackTrace: stackTrace,
122-
);
108+
}) =>
109+
log(message, LogSeverity.info, payload: payload, stackTrace: stackTrace);
123110

124111
/// Logs [message] at [LogSeverity.notice] severity.
125112
///
126113
/// {@macro google_cloud.CloudLogger.log_params}
127114
void notice(
128115
Object message, {
129116
Map<String, Object?>? payload,
130-
Map<String, String>? labels,
131117
StackTrace? stackTrace,
132118
}) => log(
133119
message,
134120
LogSeverity.notice,
135121
payload: payload,
136-
labels: labels,
137122
stackTrace: stackTrace,
138123
);
139124

@@ -143,13 +128,11 @@ abstract base class CloudLogger {
143128
void warning(
144129
Object message, {
145130
Map<String, Object?>? payload,
146-
Map<String, String>? labels,
147131
StackTrace? stackTrace,
148132
}) => log(
149133
message,
150134
LogSeverity.warning,
151135
payload: payload,
152-
labels: labels,
153136
stackTrace: stackTrace,
154137
);
155138

@@ -159,29 +142,21 @@ abstract base class CloudLogger {
159142
void error(
160143
Object message, {
161144
Map<String, Object?>? payload,
162-
Map<String, String>? labels,
163145
StackTrace? stackTrace,
164-
}) => log(
165-
message,
166-
LogSeverity.error,
167-
payload: payload,
168-
labels: labels,
169-
stackTrace: stackTrace,
170-
);
146+
}) =>
147+
log(message, LogSeverity.error, payload: payload, stackTrace: stackTrace);
171148

172149
/// Logs [message] at [LogSeverity.critical] severity.
173150
///
174151
/// {@macro google_cloud.CloudLogger.log_params}
175152
void critical(
176153
Object message, {
177154
Map<String, Object?>? payload,
178-
Map<String, String>? labels,
179155
StackTrace? stackTrace,
180156
}) => log(
181157
message,
182158
LogSeverity.critical,
183159
payload: payload,
184-
labels: labels,
185160
stackTrace: stackTrace,
186161
);
187162

@@ -191,29 +166,21 @@ abstract base class CloudLogger {
191166
void alert(
192167
Object message, {
193168
Map<String, Object?>? payload,
194-
Map<String, String>? labels,
195169
StackTrace? stackTrace,
196-
}) => log(
197-
message,
198-
LogSeverity.alert,
199-
payload: payload,
200-
labels: labels,
201-
stackTrace: stackTrace,
202-
);
170+
}) =>
171+
log(message, LogSeverity.alert, payload: payload, stackTrace: stackTrace);
203172

204173
/// Logs [message] at [LogSeverity.emergency] severity.
205174
///
206175
/// {@macro google_cloud.CloudLogger.log_params}
207176
void emergency(
208177
Object message, {
209178
Map<String, Object?>? payload,
210-
Map<String, String>? labels,
211179
StackTrace? stackTrace,
212180
}) => log(
213181
message,
214182
LogSeverity.emergency,
215183
payload: payload,
216-
labels: labels,
217184
stackTrace: stackTrace,
218185
);
219186
}
@@ -228,18 +195,16 @@ final class _DefaultLogger extends CloudLogger {
228195
Object message,
229196
LogSeverity severity, {
230197
Map<String, Object?>? payload,
231-
Map<String, String>? labels,
232198
StackTrace? stackTrace,
233199
}) {
234200
final payloadStr = payload != null && payload.isNotEmpty ? ' $payload' : '';
235-
final labelsStr = labels != null && labels.isNotEmpty ? ' $labels' : '';
236201
final traceStr = stackTrace != null
237202
? '\n${formatStackTrace(stackTrace)}'
238203
: '';
239204
if (severity == LogSeverity.defaultSeverity) {
240-
print('$message$payloadStr$labelsStr$traceStr');
205+
print('$message$payloadStr$traceStr');
241206
} else {
242-
print('${severity.name}: $message$payloadStr$labelsStr$traceStr');
207+
print('${severity.name}: $message$payloadStr$traceStr');
243208
}
244209
}
245210
}
@@ -249,6 +214,5 @@ bool frameFolder(Frame frame) =>
249214
frame.isCore || frame.package == 'google_cloud';
250215

251216
@internal
252-
Chain formatStackTrace(StackTrace? stackTrace) =>
253-
(stackTrace == null ? Chain.current() : Chain.forTrace(stackTrace))
254-
.foldFrames(frameFolder, terse: true);
217+
Chain formatStackTrace(StackTrace stackTrace) =>
218+
Chain.forTrace(stackTrace).foldFrames(frameFolder, terse: true);

pkgs/google_cloud/lib/src/serving/http_logging.dart

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import '../constants.dart';
2323
import '../logger.dart';
2424
import '../structured_logging.dart';
2525
import 'bad_request_exception.dart';
26+
import 'trace_context_data.dart';
2627

2728
export '../structured_logging.dart';
2829

@@ -67,7 +68,7 @@ Handler _errorWriter(Handler innerHandler) => (request) async {
6768
error,
6869
if (error.innerError != null)
6970
'${error.innerError} (${error.innerError.runtimeType})',
70-
formatStackTrace(error.innerStack ?? stack),
71+
if (error.innerStack ?? stack case final s?) formatStackTrace(s),
7172
];
7273

7374
final bob = output
@@ -101,12 +102,13 @@ Middleware cloudLoggingMiddleware(String projectId) {
101102
// Add log correlation to nest all log messages beneath request log in
102103
// Log Viewer.
103104

104-
String? traceValue;
105-
106105
final traceHeader = request.headers[cloudTraceContextHeader];
107-
if (traceHeader != null) {
108-
traceValue = 'projects/$projectId/traces/${traceHeader.split('/')[0]}';
109-
}
106+
final traceContext = traceHeader != null
107+
? TraceContextData.tryParse(
108+
projectId: projectId,
109+
traceHeader: traceHeader,
110+
)
111+
: null;
110112

111113
String createErrorLogEntryFromRequest(
112114
Object error,
@@ -115,7 +117,7 @@ Middleware cloudLoggingMiddleware(String projectId) {
115117
) => structuredLogEntry(
116118
'$error'.trim(),
117119
logSeverity,
118-
traceId: traceValue,
120+
payload: traceContext?.asPayloadMap(),
119121
stackTrace: stackTrace,
120122
);
121123

@@ -126,7 +128,10 @@ Middleware cloudLoggingMiddleware(String projectId) {
126128
Zone.current
127129
.fork(
128130
zoneValues: {
129-
_loggerKey: _CloudLogger(zone: currentZone, traceId: traceValue),
131+
_loggerKey: _CloudLogger(
132+
zone: currentZone,
133+
traceContext: traceContext,
134+
),
130135
},
131136
specification: ZoneSpecification(
132137
handleUncaughtError: (self, parent, zone, error, stackTrace) {
@@ -163,7 +168,7 @@ Middleware cloudLoggingMiddleware(String projectId) {
163168
final logContent = structuredLogEntry(
164169
line,
165170
LogSeverity.info,
166-
traceId: traceValue,
171+
payload: traceContext?.asPayloadMap(),
167172
);
168173

169174
// Serialize to a JSON string and output to parent zone.
@@ -203,12 +208,11 @@ final _loggerKey = Object();
203208
/// logging.
204209
final class _CloudLogger extends CloudLogger {
205210
final Zone zone;
206-
final String? _traceId;
211+
212+
final TraceContextData? traceContext;
207213

208214
/// Creates a new [_CloudLogger] that prints structured logs to [this.zone].
209-
///
210-
/// If [_traceId] is provided, it is included in the log entry.
211-
_CloudLogger({required this.zone, String? traceId}) : _traceId = traceId;
215+
_CloudLogger({required this.zone, this.traceContext});
212216

213217
/// If [message] is a [Map], it is used as the log entry payload. Otherwise,
214218
/// it is passed directly to [structuredLogEntry], which handles
@@ -218,15 +222,12 @@ final class _CloudLogger extends CloudLogger {
218222
Object message,
219223
LogSeverity severity, {
220224
Map<String, Object?>? payload,
221-
Map<String, String>? labels,
222225
StackTrace? stackTrace,
223226
}) => zone.print(
224227
structuredLogEntry(
225228
message,
226229
severity,
227-
payload: payload,
228-
labels: labels,
229-
traceId: _traceId,
230+
payload: traceContext?.asPayloadMap(payload) ?? payload,
230231
stackTrace: stackTrace,
231232
),
232233
);

0 commit comments

Comments
 (0)