Skip to content

Commit 28f3e69

Browse files
committed
feat(gax): remove experimental logging flag and add logging sample
1 parent 25710ee commit 28f3e69

14 files changed

Lines changed: 162 additions & 135 deletions

File tree

‎core/packages/gax/samples/observability.js‎

Lines changed: 101 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,38 @@
1717
// [START gax_observability]
1818
'use strict';
1919

20-
// 1. IMPORT OPENTELEMETRY MODULES
21-
const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
22-
const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
23-
const {
24-
TraceExporter,
25-
} = require('@google-cloud/opentelemetry-cloud-trace-exporter');
26-
27-
// 2. CONFIGURE TRACING: SET UP A TRACER PROVIDER AND EXPORTER
28-
const cloudTraceExporter = new TraceExporter();
29-
const spanProcessor = new BatchSpanProcessor(cloudTraceExporter);
30-
31-
const provider = new NodeTracerProvider({
32-
spanProcessors: [spanProcessor],
33-
});
34-
provider.register();
35-
36-
// 3. ENABLE TRACING SPANS WITH ENV VARIABLE
37-
// Sets the flag before client libraries or RPC callers initialize
38-
process.env.GOOGLE_SDK_NODE_ENABLE_TRACING = 'true';
39-
40-
// 4. IMPORT CLIENT LIBRARIES AFTER OPENTELEMETRY SETUP
41-
// Replace with your Google Cloud client library, for example:
42-
// const { SecretManagerServiceClient } = require('@google-cloud/secret-manager');
20+
// Logging and tracing in Google Cloud Node.js client libraries are completely
21+
// orthogonal: you can enable logging without OpenTelemetry tracing
22+
// (`!tracingEnabled && loggingEnabled`), tracing without logging, or both
23+
// simultaneously. When both are active, failed RPC logs automatically include
24+
// `telemetryTraceId` and `telemetrySpanId` for trace-log correlation.
4325

44-
async function main() {
26+
// [START gax_observability_tracing]
27+
async function enableTracing() {
28+
// 1. IMPORT OPENTELEMETRY MODULES
29+
const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
30+
const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
31+
const {
32+
TraceExporter,
33+
} = require('@google-cloud/opentelemetry-cloud-trace-exporter');
34+
35+
// 2. CONFIGURE TRACING: SET UP A TRACER PROVIDER AND EXPORTER
36+
const cloudTraceExporter = new TraceExporter();
37+
const spanProcessor = new BatchSpanProcessor(cloudTraceExporter);
38+
39+
const provider = new NodeTracerProvider({
40+
spanProcessors: [spanProcessor],
41+
});
42+
provider.register();
43+
44+
// 3. ENABLE TRACING SPANS
45+
// Set the flag before client libraries or RPC callers initialize, or pass
46+
// `{enableTelemetryTracing: true}` to an individual client constructor.
47+
process.env.GOOGLE_SDK_NODE_ENABLE_TRACING = 'true';
48+
49+
// 4. IMPORT CLIENT LIBRARIES AFTER OPENTELEMETRY SETUP
50+
// Replace with your Google Cloud client library, for example:
51+
// const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');
4552
// const client = new SecretManagerServiceClient();
4653
// await client.listSecrets({parent: 'projects/my-project'});
4754

@@ -50,6 +57,76 @@ async function main() {
5057
await provider.forceFlush();
5158
console.log('Tracing initialized successfully.');
5259
}
60+
// [END gax_observability_tracing]
61+
62+
// [START gax_observability_logging]
63+
async function enableLogging() {
64+
// Telemetry logging does not require OpenTelemetry setup (`!tracingEnabled && loggingEnabled`).
65+
const util = require('util');
66+
const {loggingUtils} = require('google-gax');
67+
68+
// 1. ENABLE TELEMETRY LOGGING
69+
// In production, prefer `{enableTelemetryLogging: true}` on the client or a
70+
// service-scoped filter (e.g. `GOOGLE_SDK_NODE_LOGGING=secretmanager`) over
71+
// `*`, `true`, or `all` so `'auth'` debug logs remain disabled.
72+
process.env.GOOGLE_SDK_NODE_LOGGING = 'secretmanager';
73+
74+
// Or enable logging for a specific client without setting an env variable:
75+
// const {SecretManagerServiceClient} = require('@google-cloud/secret-manager');
76+
// const client = new SecretManagerServiceClient({enableTelemetryLogging: true});
77+
78+
// 2. CONFIGURE AN OUTPUT BACKEND (DEFAULT NODEBACKEND OR PLUGGABLE BACKEND)
79+
// Option A — Default `NodeBackend` (writes formatted log lines to `stderr`):
80+
// No configuration is needed to use the default backend (`undefined` resets to default).
81+
loggingUtils.setBackend(undefined);
82+
83+
// Option B — Built-in structured JSON backend (writes Cloud Logging JSON):
84+
// loggingUtils.setBackend(loggingUtils.getStructuredBackend());
85+
86+
// Option C — Pluggable custom backend (e.g. Pino, Winston, Bunyan, or custom filtering):
87+
const customBackend = {
88+
setFilters() {
89+
// Receives filters parsed from `GOOGLE_SDK_NODE_LOGGING`, if needed.
90+
},
91+
log(namespace, fields, ...args) {
92+
// Skip `'auth'` debug logs if only client RPC telemetry logs are desired.
93+
if (namespace === 'auth') {
94+
return;
95+
}
96+
const entry = {
97+
namespace,
98+
severity: fields.severity,
99+
message: util.format(...args),
100+
...(fields.telemetryTraceId
101+
? {telemetryTraceId: fields.telemetryTraceId}
102+
: {}),
103+
...(fields.telemetrySpanId
104+
? {telemetrySpanId: fields.telemetrySpanId}
105+
: {}),
106+
...(fields.other || {}),
107+
};
108+
// Forward `entry` to your preferred logger (Pino, Winston, stdout, etc.):
109+
console.log(JSON.stringify(entry));
110+
},
111+
};
112+
loggingUtils.setBackend(customBackend);
113+
114+
// 3. CALL CLIENT LIBRARIES AS USUAL
115+
// Failed API calls emit structured `WARNING` logs and failed transport
116+
// attempts emit `DEBUG` logs through the configured backend.
117+
// await client.listSecrets({parent: 'projects/my-project'});
118+
119+
console.log('Logging initialized successfully.');
120+
}
121+
// [END gax_observability_logging]
122+
123+
async function main() {
124+
// Enable logging independently (works with or without OpenTelemetry tracing):
125+
await enableLogging();
126+
127+
// Enable OpenTelemetry tracing independently (works with or without logging):
128+
await enableTracing();
129+
}
53130

54131
main().catch(console.error);
55132
// [END gax_observability]

‎core/packages/gax/samples/system-test/test.observability.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const cwd = path.join(__dirname, '..');
2929
describe('Observability', () => {
3030
it('should run observability sample', async () => {
3131
const stdout = execSync('node observability.js', {cwd});
32+
assert(/Logging initialized successfully/.test(stdout));
3233
assert(/Tracing initialized successfully/.test(stdout));
3334
});
3435
});

‎core/packages/gax/src/clientInterface.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ export interface ClientOptions
5353
/**
5454
* Whether to enable telemetry logging for the client.
5555
*
56-
* Logging is only enabled when `GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING` is enabled
57-
* AND either `enableTelemetryLogging: true` is passed here or, when unset, the
58-
* `GOOGLE_SDK_NODE_LOGGING` environment variable matches the client service
59-
* namespace. Explicitly setting `enableTelemetryLogging: false` disables logging
60-
* for this client even when `GOOGLE_SDK_NODE_LOGGING` matches.
56+
* Logging is only enabled when `enableTelemetryLogging: true` is passed here
57+
* or, when unset, the `GOOGLE_SDK_NODE_LOGGING` environment variable matches
58+
* the client service namespace. Explicitly setting
59+
* `enableTelemetryLogging: false` disables logging for this client even when
60+
* `GOOGLE_SDK_NODE_LOGGING` matches.
6161
*/
6262
enableTelemetryLogging?: boolean;
6363
}

‎core/packages/gax/src/gax.ts‎

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -921,12 +921,8 @@ export function constructSettings(
921921
? isEnvEnabled
922922
: Boolean(enableTelemetryTracing);
923923

924-
const experimentalLogging =
925-
env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING?.trim().toLowerCase();
926-
const isExperimentalLoggingEnabled =
927-
experimentalLogging === 'true' || experimentalLogging === '1';
928924
const isLoggingEnvEnabled =
929-
isExperimentalLoggingEnabled && enableTelemetryLogging === undefined
925+
enableTelemetryLogging === undefined
930926
? checkLoggingEnabled(new CallSettings({apiName: serviceName}))
931927
: false;
932928
const resolvedLogging =
@@ -935,8 +931,7 @@ export function constructSettings(
935931
: isLoggingEnvEnabled
936932
? true
937933
: undefined;
938-
const loggingRequested =
939-
isExperimentalLoggingEnabled && Boolean(resolvedLogging);
934+
const loggingRequested = Boolean(resolvedLogging);
940935

941936
otherArgs = otherArgs || {};
942937

@@ -1007,11 +1002,7 @@ export function constructSettings(
10071002
: otherArgs,
10081003
apiName,
10091004
enableTelemetryTracing: isEnvSet ? isEnvEnabled : enableTelemetryTracing,
1010-
enableTelemetryLogging: isExperimentalLoggingEnabled
1011-
? resolvedLogging
1012-
: enableTelemetryLogging !== undefined
1013-
? false
1014-
: undefined,
1005+
enableTelemetryLogging: resolvedLogging,
10151006
});
10161007
}
10171008

‎core/packages/gax/src/grpc.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ export interface GrpcClientOptions extends GoogleAuthOptions {
6767
/**
6868
* Whether to enable telemetry logging for the client.
6969
*
70-
* Logging is only enabled when `GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING` is enabled
71-
* AND either `enableTelemetryLogging: true` is passed here or, when unset, the
72-
* `GOOGLE_SDK_NODE_LOGGING` environment variable matches the client service
73-
* namespace. Explicitly setting `enableTelemetryLogging: false` disables logging
74-
* for this client even when `GOOGLE_SDK_NODE_LOGGING` matches.
70+
* Logging is only enabled when `enableTelemetryLogging: true` is passed here
71+
* or, when unset, the `GOOGLE_SDK_NODE_LOGGING` environment variable matches
72+
* the client service namespace. Explicitly setting
73+
* `enableTelemetryLogging: false` disables logging for this client even when
74+
* `GOOGLE_SDK_NODE_LOGGING` matches.
7575
*/
7676
enableTelemetryLogging?: boolean;
7777
}

‎core/packages/gax/src/observability/util.ts‎

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,30 @@ function matchesLoggingEnvFilter(envOptIn: string, namespace: string): boolean {
7171
/**
7272
* Checks if telemetry logging is enabled.
7373
*
74-
* Logging is only enabled when `GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING` is enabled
75-
* AND either a user explicitly passes `enableTelemetryLogging: true` in their
76-
* client/call options or, when `enableTelemetryLogging` is unset, the
77-
* `GOOGLE_SDK_NODE_LOGGING` environment variable matches the client service
78-
* namespace using `google-logging-utils` filter semantics (`'*'`, exact `'all'` /
79-
* `'true'`, or comma-separated wildcard patterns). Passing
80-
* `enableTelemetryLogging: false` suppresses logging for that client/call even
81-
* when `GOOGLE_SDK_NODE_LOGGING` matches.
74+
* Logging is only enabled when a user explicitly passes
75+
* `enableTelemetryLogging: true` in their client/call options or, when
76+
* `enableTelemetryLogging` is unset, the `GOOGLE_SDK_NODE_LOGGING` environment
77+
* variable matches the client service namespace using `google-logging-utils`
78+
* filter semantics (`'*'`, exact `'all'` / `'true'`, or comma-separated
79+
* wildcard patterns). Passing `enableTelemetryLogging: false` suppresses
80+
* logging for that client/call even when `GOOGLE_SDK_NODE_LOGGING` matches.
8281
*
8382
* @param settings
8483
* @returns true if telemetry logging is enabled, false otherwise
8584
*/
8685
export function checkLoggingEnabled(settings?: CallSettings): boolean {
87-
const env: Record<string, string | undefined> =
88-
typeof process === 'object' && typeof process.env === 'object'
89-
? process.env
90-
: {};
91-
const experimentalOptIn =
92-
env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING?.trim().toLowerCase();
93-
if (experimentalOptIn !== 'true' && experimentalOptIn !== '1') {
94-
return false;
95-
}
96-
9786
if (typeof settings?.enableTelemetryLogging === 'boolean') {
9887
return settings.enableTelemetryLogging;
9988
}
10089
if (settings?.otherArgs?.enableTelemetryLogging === true) {
10190
return true;
10291
}
10392

93+
const env: Record<string, string | undefined> =
94+
typeof process === 'object' && typeof process.env === 'object'
95+
? process.env
96+
: {};
97+
10498
const envOptIn = env.GOOGLE_SDK_NODE_LOGGING;
10599
if (!envOptIn) {
106100
return false;

‎core/packages/gax/test/unit/apiCallable.ts‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,14 +1876,12 @@ describe('createApiCall', () => {
18761876
loggingUtils.setBackend(sink);
18771877
harness = new OtelHarness();
18781878
harness.setup();
1879-
process.env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING = 'true';
18801879
});
18811880

18821881
afterEach(() => {
18831882
clearMetadataCache();
18841883
loggingUtils.setBackend(undefined);
18851884
harness.teardown();
1886-
delete process.env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING;
18871885
delete process.env.GOOGLE_SDK_NODE_LOGGING;
18881886
delete process.env.GOOGLE_SDK_NODE_ENABLE_TRACING;
18891887
});
@@ -2809,11 +2807,9 @@ describe('createApiCall', () => {
28092807

28102808
for (const childEnv of [
28112809
{
2812-
GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING: 'true',
28132810
CHILD_ENABLE_OPT: 'true',
28142811
},
28152812
{
2816-
GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING: 'true',
28172813
GOOGLE_SDK_NODE_LOGGING: 'storage,example',
28182814
},
28192815
]) {

‎core/packages/gax/test/unit/gax.ts‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ describe('gax construct settings', () => {
102102
afterEach(() => {
103103
delete process.env.GOOGLE_SDK_NODE_ENABLE_TRACING;
104104
delete process.env.GOOGLE_SDK_NODE_LOGGING;
105-
delete process.env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING;
106105
});
107106

108107
it('creates settings', () => {
@@ -280,8 +279,7 @@ describe('gax construct settings', () => {
280279
assert.strictEqual(settings.otherArgs.internalMethodName, undefined);
281280
});
282281

283-
it('creates settings with enableTelemetryLogging when GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING=true', () => {
284-
process.env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING = 'true';
282+
it('creates settings with enableTelemetryLogging', () => {
285283
const otherArgs = {key: 'value'};
286284
const defaults = gax.constructSettings(
287285
SERVICE_NAME,
@@ -301,7 +299,7 @@ describe('gax construct settings', () => {
301299
assert.strictEqual(settings.otherArgs.enableTelemetryLogging, true);
302300
});
303301

304-
it('disables logging when GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING is not set even if enableTelemetryLogging=true', () => {
302+
it('creates settings with enableTelemetryLogging set to false', () => {
305303
const defaults = gax.constructSettings(
306304
SERVICE_NAME,
307305
A_CONFIG,
@@ -310,15 +308,14 @@ describe('gax construct settings', () => {
310308
{},
311309
undefined,
312310
undefined,
313-
true,
311+
false,
314312
);
315313
const settings = defaults.bundlingMethod;
316314
assert.strictEqual(settings.enableTelemetryLogging, false);
317315
assert.strictEqual(settings.otherArgs.internalMethodName, undefined);
318316
});
319317

320318
it('enables logging when enableTelemetryLogging is unset and GOOGLE_SDK_NODE_LOGGING matches the service namespace or wildcard', () => {
321-
process.env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING = 'true';
322319
for (const envValue of ['true', '*', 'all', 'auth,interface']) {
323320
process.env.GOOGLE_SDK_NODE_LOGGING = envValue;
324321
const defaults = gax.constructSettings(
@@ -360,7 +357,6 @@ describe('gax construct settings', () => {
360357
});
361358

362359
it('preserves enableTelemetryLogging=true when GOOGLE_SDK_NODE_LOGGING targets another namespace or is false', () => {
363-
process.env.GOOGLE_SDK_NODE_EXPERIMENTAL_LOGGING = 'true';
364360
for (const envValue of ['auth,storage', 'false']) {
365361
process.env.GOOGLE_SDK_NODE_LOGGING = envValue;
366362
const enabledDefaults = gax.constructSettings(

0 commit comments

Comments
 (0)