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
54131main ( ) . catch ( console . error ) ;
55132// [END gax_observability]
0 commit comments