Repository: googleapis/nodejs-spanner
Pull request #2249: chore: samples for opentelemetry tracing
Author: login: surbhigarg92
Labels: name: api: spanner
description: Issues related to the googleapis/nodejs-spanner API.
name: samples
description: Issues that are directly related to samples.
name: size: m
description: Pull request size is medium.
Created: 2025-03-12T09:40:55Z | Merged: 2025-03-12T12:26:26Z



Diff:
diff --git a/README.md b/README.md
index 1c033666a..abb13841a 100644
--- a/README.md
+++ b/README.md
@@ -157,6 +157,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/nodejs-spanner/tre
 | Numeric-add-column | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/numeric-add-column.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/numeric-add-column.js,samples/README.md) |
 | Numeric-query-parameter | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/numeric-query-parameter.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/numeric-query-parameter.js,samples/README.md) |
 | Numeric-update-data | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/numeric-update-data.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/numeric-update-data.js,samples/README.md) |
+| Observability (Tracing) with OpenTelemetry using OTLP | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/observability-traces-otlp.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/observability-traces-otlp.js,samples/README.md) |
 | Observability (Tracing) with OpenTelemetry | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/observability-traces.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/observability-traces.js,samples/README.md) |
 | Adds a column to an existing table in a Spanner PostgreSQL database. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/pg-add-column.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/pg-add-column.js,samples/README.md) |
 | Showcase the rules for case-sensitivity and case folding for a Spanner PostgreSQL database. | [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/pg-case-sensitivity.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/pg-case-sensitivity.js,samples/README.md) |
diff --git a/samples/README.md b/samples/README.md
index a97a24382..b10209dc9 100644
--- a/samples/README.md
+++ b/samples/README.md
@@ -82,6 +82,7 @@ and automatic, synchronous replication for high availability.
   * [Numeric-add-column](#numeric-add-column)
   * [Numeric-query-parameter](#numeric-query-parameter)
   * [Numeric-update-data](#numeric-update-data)
+  * [Observability (Tracing) with OpenTelemetry using OTLP](#observability-tracing-with-opentelemetry-using-otlp)
   * [Observability (Tracing) with OpenTelemetry](#observability-tracing-with-opentelemetry)
   * [Adds a column to an existing table in a Spanner PostgreSQL database.](#adds-a-column-to-an-existing-table-in-a-spanner-postgresql-database.)
   * [Showcase the rules for case-sensitivity and case folding for a Spanner PostgreSQL database.](#showcase-the-rules-for-case-sensitivity-and-case-folding-for-a-spanner-postgresql-database.)
@@ -1306,6 +1307,23 @@ __Usage:__
 
 
 
+### Observability (Tracing) with OpenTelemetry using OTLP
+
+View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/observability-traces-otlp.js).
+
+[![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-spanner&page=editor&open_in_editor=samples/observability-traces-otlp.js,samples/README.md)
+
+__Usage:__
+
+
+`node observability-traces-otlp.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID>`
+
+
+-----
+
+
+
+
 ### Observability (Tracing) with OpenTelemetry
 
 View the [source code](https://github.com/googleapis/nodejs-spanner/blob/main/samples/observability-traces.js).
diff --git a/samples/observability-traces-otlp.js b/samples/observability-traces-otlp.js
new file mode 100644
index 000000000..bc448f527
--- /dev/null
+++ b/samples/observability-traces-otlp.js
@@ -0,0 +1,103 @@
+/*!
+ * Copyright 2025 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// sample-metadata:
+//   title: Observability (Tracing) with OpenTelemetry using OTLP
+//   usage: node observability-traces-otlp.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID>
+
+'use strict';
+
+async function main(
+  projectId = 'my-project-id',
+  instanceId = 'my-instance-id',
+  databaseId = 'my-project-id'
+) {
+  // [START spanner_opentelemetry_traces_otlp_usage]
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    OTLPTraceExporter,
+  } = require('@opentelemetry/exporter-trace-otlp-grpc');
+  const {
+    BatchSpanProcessor,
+    TraceIdRatioBasedSampler,
+  } = require('@opentelemetry/sdk-trace-base');
+  const {Resource} = require('@opentelemetry/resources');
+  const {Spanner} = require('@google-cloud/spanner');
+
+  // Define a Resource with service metadata
+  const resource = new Resource({
+    'service.name': 'my-service',
+    'service.version': '1.0.0',
+  });
+
+  // Create an OTLP gRPC trace exporter
+  const traceExporter = new OTLPTraceExporter({
+    url: 'http://localhost:4317', // Default OTLP gRPC endpoint
+  });
+
+  // Create a provider with a custom sampler
+  const provider = new NodeTracerProvider({
+    sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
+    resource,
+    spanProcessors: [new BatchSpanProcessor(traceExporter)],
+  });
+
+  // Uncomment following line to register tracerProvider globally or pass it in Spanner object
+  // provider.register();
+
+  // Create the Cloud Spanner Client.
+  const spanner = new Spanner({
+    projectId: projectId,
+    observabilityOptions: {
+      tracerProvider: provider,
+      enableExtendedTracing: true,
+      enableEndToEndTracing: true,
+    },
+  });
+
+  // [END spanner_opentelemetry_traces_otlp_usage]
+
+  // Acquire the database handle.
+  const instance = spanner.instance(instanceId);
+  const database = instance.database(databaseId);
+
+  try {
+    const query = {
+      sql: 'SELECT 1',
+    };
+    const [rows] = await database.run(query);
+    console.log(`Query: ${rows.length} found.`);
+    rows.forEach(row => console.log(row));
+  } finally {
+    spanner.close();
+  }
+
+  provider.forceFlush();
+
+  // This sleep gives ample time for the trace
+  // spans to be exported to Google Cloud Trace.
+  await new Promise(resolve => {
+    setTimeout(() => {
+      resolve();
+    }, 8800);
+  });
+}
+
+process.on('unhandledRejection', err => {
+  console.error(err.message);
+  process.exitCode = 1;
+});
+main(...process.argv.slice(2));
diff --git a/samples/observability-traces.js b/samples/observability-traces.js
index 86b0b33a8..6f0c199da 100644
--- a/samples/observability-traces.js
+++ b/samples/observability-traces.js
@@ -1,5 +1,5 @@
 /*!
- * Copyright 2024 Google LLC. All Rights Reserved.
+ * Copyright 2025 Google LLC. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,71 +20,52 @@
 
 'use strict';
 
-// Setup OpenTelemetry and the trace exporter.
-const {
-  NodeTracerProvider,
-  TraceIdRatioBasedSampler,
-} = require('@opentelemetry/sdk-trace-node');
-const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
-
-// Create the Google Cloud Trace exporter for OpenTelemetry.
-const {
-  TraceExporter,
-} = require('@google-cloud/opentelemetry-cloud-trace-exporter');
-const exporter = new TraceExporter();
-
-// Create the OpenTelemetry tracerProvider that the exporter shall be attached to.
-const provider = new NodeTracerProvider({
-  // Modify the following line to adjust the sampling rate.
-  // It is currently set to 1.0, meaning all requests will be traced.
-  sampler: new TraceIdRatioBasedSampler(1.0),
-});
-provider.addSpanProcessor(new BatchSpanProcessor(exporter));
-
-// Set global propagator to propogate the trace context for end to end tracing.
-const {propagation} = require('@opentelemetry/api');
-const {W3CTraceContextPropagator} = require('@opentelemetry/core');
-propagation.setGlobalPropagator(new W3CTraceContextPropagator());
-
-// Uncomment following line to register global tracerProvider instead
-// of passing it into SpannerOptions.observabilityOptions.
-// provider.register();
-
-// Set `enableGrpcInstrumentation` to `true` to enable gRPC instrumentation.
-const enableGrpcInstrumentation = false;
-if (enableGrpcInstrumentation) {
-  const {registerInstrumentations} = require('@opentelemetry/instrumentation');
-  const {GrpcInstrumentation} = require('@opentelemetry/instrumentation-grpc');
-  registerInstrumentations({
-    tracerProvider: provider,
-    instrumentations: [new GrpcInstrumentation()],
-  });
-}
-
 async function main(
   projectId = 'my-project-id',
   instanceId = 'my-instance-id',
   databaseId = 'my-project-id'
 ) {
-  // Create the Cloud Spanner Client.
+  // [START spanner_opentelemetry_traces_cloudtrace_usage]
+
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    TraceExporter,
+  } = require('@google-cloud/opentelemetry-cloud-trace-exporter');
+  const {
+    BatchSpanProcessor,
+    TraceIdRatioBasedSampler,
+  } = require('@opentelemetry/sdk-trace-base');
   const {Spanner} = require('@google-cloud/spanner');
 
-  /**
-   * TODO(developer): Uncomment these variables before running the sample.
-   */
-  // const projectId = 'my-project-id';
-  // const instanceId = 'my-instance-id';
-  // const databaseId = 'my-database-id';
+  const traceExporter = new TraceExporter();
+
+  // Create a provider with a custom sampler
+  const provider = new NodeTracerProvider({
+    sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
+    spanProcessors: [new BatchSpanProcessor(traceExporter)],
+  });
+
+  // Uncomment following line to register tracerProvider globally or pass it in Spanner object
+  // provider.register();
+
+  // Set global propagator to propogate the trace context for end to end tracing.
+  const {propagation} = require('@opentelemetry/api');
+  const {W3CTraceContextPropagator} = require('@opentelemetry/core');
+  propagation.setGlobalPropagator(new W3CTraceContextPropagator());
 
   const spanner = new Spanner({
     projectId: projectId,
     observabilityOptions: {
       tracerProvider: provider,
+      // Enable extended tracing to allow your SQL statements to be annotated.
       enableExtendedTracing: true,
+      // Enable end to end tracing.
       enableEndToEndTracing: true,
     },
   });
 
+  // [END spanner_opentelemetry_traces_cloudtrace_usage]
+
   // Acquire the database handle.
   const instance = spanner.instance(instanceId);
   const database = instance.database(databaseId);
diff --git a/samples/package.json b/samples/package.json
index 322894b35..a6ad4dfe2 100644
--- a/samples/package.json
+++ b/samples/package.json
@@ -23,12 +23,14 @@
   },
   "devDependencies": {
     "@google-cloud/opentelemetry-cloud-trace-exporter": "^2.4.1",
+    "@opentelemetry/exporter-trace-otlp-grpc": "^0.57.0",
     "@opentelemetry/instrumentation": "^0.57.0",
     "@opentelemetry/instrumentation-grpc": "^0.57.0",
-    "@opentelemetry/sdk-trace-base": "^1.26.0",
-    "@opentelemetry/sdk-trace-node": "^1.26.0",
+    "@opentelemetry/resources": "1.30.1",
+    "@opentelemetry/sdk-trace-base":"~1.30.1",
+    "@opentelemetry/sdk-trace-node":"^1.30.1",
     "@opentelemetry/api": "^1.9.0",
-    "@opentelemetry/core": "^1.27.0",
+    "@opentelemetry/core":"^1.30.1",
     "chai": "^4.2.0",
     "mocha": "^9.0.0",
     "p-limit": "^3.0.1"


Reviews:
user: login: alkatrivedi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:09:33Z
user: login: alkatrivedi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:21:21Z
user: login: alkatrivedi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:21:33Z
user: login: alkatrivedi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:22:04Z
user: login: surbhigarg92
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:39:19Z
user: login: alkatrivedi
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T10:46:28Z

Review comments:
diff_hunk: @@ -20,71 +20,50 @@
 
 'use strict';
 
-// Setup OpenTelemetry and the trace exporter.
-const {
-  NodeTracerProvider,
-  TraceIdRatioBasedSampler,
-} = require('@opentelemetry/sdk-trace-node');
-const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
-
-// Create the Google Cloud Trace exporter for OpenTelemetry.
-const {
-  TraceExporter,
-} = require('@google-cloud/opentelemetry-cloud-trace-exporter');
-const exporter = new TraceExporter();
-
-// Create the OpenTelemetry tracerProvider that the exporter shall be attached to.
-const provider = new NodeTracerProvider({
-  // Modify the following line to adjust the sampling rate.
-  // It is currently set to 1.0, meaning all requests will be traced.
-  sampler: new TraceIdRatioBasedSampler(1.0),
-});
-provider.addSpanProcessor(new BatchSpanProcessor(exporter));
-
-// Set global propagator to propogate the trace context for end to end tracing.
-const {propagation} = require('@opentelemetry/api');
-const {W3CTraceContextPropagator} = require('@opentelemetry/core');
-propagation.setGlobalPropagator(new W3CTraceContextPropagator());
-
-// Uncomment following line to register global tracerProvider instead
-// of passing it into SpannerOptions.observabilityOptions.
-// provider.register();
-
-// Set `enableGrpcInstrumentation` to `true` to enable gRPC instrumentation.
-const enableGrpcInstrumentation = false;
-if (enableGrpcInstrumentation) {
-  const {registerInstrumentations} = require('@opentelemetry/instrumentation');
-  const {GrpcInstrumentation} = require('@opentelemetry/instrumentation-grpc');
-  registerInstrumentations({
-    tracerProvider: provider,
-    instrumentations: [new GrpcInstrumentation()],
-  });
-}
-
 async function main(
   projectId = 'my-project-id',
   instanceId = 'my-instance-id',
   databaseId = 'my-project-id'
 ) {
-  // Create the Cloud Spanner Client.
+  // [START spanner_opentelemetry_traces_cloudtrace_usage]
+
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    TraceExporter,
+  } = require('@google-cloud/opentelemetry-cloud-trace-exporter');
+  const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
+  const {TraceIdRatioBasedSampler} = require('@opentelemetry/sdk-trace-base');
path: samples/observability-traces.js
user: login: alkatrivedi
body: we can combine them
created_at: 2025-03-12T10:09:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+/*!
+ * Copyright 2025 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// sample-metadata:
+//   title: Observability (Tracing) with OpenTelemetry using OTLP
+//   usage: node observability-traces-otlp.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID>
+
+'use strict';
+
+async function main(
+  projectId = 'my-project-id',
+  instanceId = 'my-instance-id',
+  databaseId = 'my-project-id'
+) {
+  // [START spanner_opentelemetry_traces_otlp_usage]
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    OTLPTraceExporter,
+  } = require('@opentelemetry/exporter-trace-otlp-grpc');
+  const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
+  const {TraceIdRatioBasedSampler} = require('@opentelemetry/sdk-trace-base');
+  const {Resource} = require('@opentelemetry/resources');
+  const {Spanner} = require('@google-cloud/spanner');
+
+  // Define a Resource with service metadata
+  const resource = new Resource({
+    'service.name': 'my-service',
+    'service.version': '1.0.0',
+  });
+
+  // Create an OTLP gRPC trace exporter
+  const traceExporter = new OTLPTraceExporter({
+    url: 'http://localhost:4317', // Default OTLP gRPC endpoint
+  });
+
+  // Create a provider with a custom sampler
+  const provider = new NodeTracerProvider({
+    sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
+    resource,
+    spanProcessors: [new BatchSpanProcessor(traceExporter)],
+  });
+
+  // Uncomment following line to register tracerProvider globally
path: samples/observability-traces-otlp.js
user: login: alkatrivedi
body: ```suggestion
  // Uncomment following line to register tracerProvider globally instead of passing it into SpannerOptions.observabilityOptions.
```

can we update the comment as above to let the customers know that they don't need to pass the tracerProvider in the ObservabilityOptions if they are registering tracerProvider globally ?

created_at: 2025-03-12T10:21:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+/*!
+ * Copyright 2025 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// sample-metadata:
+//   title: Observability (Tracing) with OpenTelemetry using OTLP
+//   usage: node observability-traces-otlp.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID>
+
+'use strict';
+
+async function main(
+  projectId = 'my-project-id',
+  instanceId = 'my-instance-id',
+  databaseId = 'my-project-id'
+) {
+  // [START spanner_opentelemetry_traces_otlp_usage]
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    OTLPTraceExporter,
+  } = require('@opentelemetry/exporter-trace-otlp-grpc');
+  const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
+  const {TraceIdRatioBasedSampler} = require('@opentelemetry/sdk-trace-base');
path: samples/observability-traces-otlp.js
user: login: alkatrivedi
body: combine ?
created_at: 2025-03-12T10:21:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+/*!
+ * Copyright 2025 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// sample-metadata:
+//   title: Observability (Tracing) with OpenTelemetry using OTLP
+//   usage: node observability-traces-otlp.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID>
+
+'use strict';
+
+async function main(
+  projectId = 'my-project-id',
+  instanceId = 'my-instance-id',
+  databaseId = 'my-project-id'
+) {
+  // [START spanner_opentelemetry_traces_otlp_usage]
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    OTLPTraceExporter,
+  } = require('@opentelemetry/exporter-trace-otlp-grpc');
+  const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
+  const {TraceIdRatioBasedSampler} = require('@opentelemetry/sdk-trace-base');
+  const {Resource} = require('@opentelemetry/resources');
+  const {Spanner} = require('@google-cloud/spanner');
+
+  // Define a Resource with service metadata
+  const resource = new Resource({
+    'service.name': 'my-service',
+    'service.version': '1.0.0',
+  });
+
+  // Create an OTLP gRPC trace exporter
+  const traceExporter = new OTLPTraceExporter({
+    url: 'http://localhost:4317', // Default OTLP gRPC endpoint
+  });
+
+  // Create a provider with a custom sampler
+  const provider = new NodeTracerProvider({
+    sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
+    resource,
+    spanProcessors: [new BatchSpanProcessor(traceExporter)],
+  });
+
+  // Uncomment following line to register tracerProvider globally
+  // provider.register();
+
+  // Create the Cloud Spanner Client.
+  const spanner = new Spanner({
+    projectId: projectId,
+    observabilityOptions: {
+      tracerProvider: provider,
+      enableExtendedTracing: true,
+      enableEndToEndTracing: true,
+    },
+  });
+
+  // [END spanner_opentelemetry_traces_otlp_usage]
path: samples/observability-traces-otlp.js
user: login: alkatrivedi
body: move to end ?
created_at: 2025-03-12T10:22:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,101 @@
+/*!
+ * Copyright 2025 Google LLC. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// sample-metadata:
+//   title: Observability (Tracing) with OpenTelemetry using OTLP
+//   usage: node observability-traces-otlp.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID>
+
+'use strict';
+
+async function main(
+  projectId = 'my-project-id',
+  instanceId = 'my-instance-id',
+  databaseId = 'my-project-id'
+) {
+  // [START spanner_opentelemetry_traces_otlp_usage]
+  const {NodeTracerProvider} = require('@opentelemetry/sdk-trace-node');
+  const {
+    OTLPTraceExporter,
+  } = require('@opentelemetry/exporter-trace-otlp-grpc');
+  const {BatchSpanProcessor} = require('@opentelemetry/sdk-trace-base');
+  const {TraceIdRatioBasedSampler} = require('@opentelemetry/sdk-trace-base');
+  const {Resource} = require('@opentelemetry/resources');
+  const {Spanner} = require('@google-cloud/spanner');
+
+  // Define a Resource with service metadata
+  const resource = new Resource({
+    'service.name': 'my-service',
+    'service.version': '1.0.0',
+  });
+
+  // Create an OTLP gRPC trace exporter
+  const traceExporter = new OTLPTraceExporter({
+    url: 'http://localhost:4317', // Default OTLP gRPC endpoint
+  });
+
+  // Create a provider with a custom sampler
+  const provider = new NodeTracerProvider({
+    sampler: new TraceIdRatioBasedSampler(1.0), // Sample 100% of traces
+    resource,
+    spanProcessors: [new BatchSpanProcessor(traceExporter)],
+  });
+
+  // Uncomment following line to register tracerProvider globally
+  // provider.register();
+
+  // Create the Cloud Spanner Client.
+  const spanner = new Spanner({
+    projectId: projectId,
+    observabilityOptions: {
+      tracerProvider: provider,
+      enableExtendedTracing: true,
+      enableEndToEndTracing: true,
+    },
+  });
+
+  // [END spanner_opentelemetry_traces_otlp_usage]
path: samples/observability-traces-otlp.js
user: login: surbhigarg92
body: we dont want to move at end, for sample we only want to capture tracer provider and how to set it.
created_at: 2025-03-12T10:39:18Z
author_association: CONTRIBUTOR

PR comments:
user: login: snippet-bot[bot]
created_at: 2025-03-12T09:41:07Z
body: <!-- probot comment [11299897]-->
Here is the summary of changes.
<details>
  <summary>You are about to add 2 region tags.</summary>

  - [samples/observability-traces-otlp.js:28](https://github.com/googleapis/nodejs-spanner/blob/77aa8ffb4bec6dc7419ec423472aeeb7ac3c7d59/samples/observability-traces-otlp.js#L28), tag `spanner_opentelemetry_traces_otlp_usage`
- [samples/observability-traces.js:28](https://github.com/googleapis/nodejs-spanner/blob/77aa8ffb4bec6dc7419ec423472aeeb7ac3c7d59/samples/observability-traces.js#L28), tag `spanner_opentelemetry_traces_cloudtrace_usage`

</details>

---
This comment is generated by [snippet-bot](https://github.com/apps/snippet-bot).
If you find problems with this result, please file an issue at:
https://github.com/googleapis/repo-automation-bots/issues.
To update this comment, add `snippet-bot:force-run` label or use the checkbox below:
- [ ] Refresh this comment

author_association: NONE
user: login: generated-files-bot[bot]
created_at: 2025-03-12T10:38:26Z
body: <!-- probot comment [12634855]-->
*Warning*: This pull request is touching the following templated files:

* README.md - `README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml
* samples/README.md - `samples/README.md` is managed by [`synthtool`](https://github.com/googleapis/synthtool). However, a partials file can be used to update the README, e.g.: https://github.com/googleapis/nodejs-storage/blob/main/.readme-partials.yaml
author_association: NONE