-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: (observability, samples): add tracing end-to-end sample (#2130)
* feat: (observability, samples): add tracing end-to-end sample This change documents an end-to-end observability tracing sample using OpenTelemetry, which then exports trace spans to Google Cloud Trace. Updates #2079 * Update with code review comments * Minimize observability sample * Tailor samples to match rubric * Add OBSERVABILITY.md docs file * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * system-test: add sample test * samples: remove demo of User Defined Traces * Address review feedback * Remove the vestige of tag until the team decides an appropriate one * Address Surbhi's review feedback * Update samples/system-test/spanner.test.js --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com> Co-authored-by: surbhigarg92 <[email protected]>
- Loading branch information
1 parent
701e226
commit 66d99e8
Showing
6 changed files
with
250 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
## Observability with OpenTelemetry | ||
|
||
This Cloud Spanner client supports [OpenTelemetry Traces](https://opentelemetry.io/), which gives insight into the client internals and aids in debugging/troubleshooting production issues. | ||
|
||
By default, the functionality is disabled. You shall need to add OpenTelemetry dependencies, and must configure and | ||
enable OpenTelemetry with appropriate exporters at the startup of your application: | ||
|
||
**Table of contents:** | ||
|
||
* [Observability](#observability) | ||
* [Tracing](#tracing) | ||
* [OpenTelemetry Dependencies](#opentelemetry-dependencies) | ||
* [OpenTelemetry Configuration](#opentelemetry-configuration) | ||
* [SQL Statement span annotation](#sql-statement-span-annotation) | ||
* [OpenTelemetry gRCP instrumentation](#opentelemetry-grpc-instrumentation) | ||
* [Tracing Sample](#tracing-sample) | ||
|
||
### Tracing | ||
|
||
#### OpenTelemetry Dependencies | ||
|
||
Add the following dependencies in your `package.json` or install them directly. | ||
```javascript | ||
// Required packages for OpenTelemetry SDKs | ||
"@opentelemetry/sdk-trace-base": "^1.26.0", | ||
"@opentelemetry/sdk-trace-node": "^1.26.0", | ||
|
||
// Package to use Google Cloud Trace exporter | ||
"@google-cloud/opentelemetry-cloud-trace-exporter": "^2.4.1", | ||
|
||
// Packages to enable gRPC instrumentation | ||
"@opentelemetry/instrumentation": "^0.53.0", | ||
"@opentelemetry/instrumentation-grpc": "^0.53.0", | ||
``` | ||
|
||
#### OpenTelemetry Configuration | ||
|
||
```javascript | ||
const { | ||
NodeTracerProvider, | ||
TraceIdRatioBasedSampler, | ||
} = require('@opentelemetry/sdk-trace-node'); | ||
const { | ||
BatchSpanProcessor, | ||
} = require('@opentelemetry/sdk-trace-base'); | ||
const { | ||
TraceExporter, | ||
} = require('@google-cloud/opentelemetry-cloud-trace-exporter'); | ||
const exporter = new TraceExporter(); | ||
|
||
// Create the tracerProvider that the exporter shall be attached to. | ||
const provider = new NodeTracerProvider({resource: resource}); | ||
provider.addSpanProcessor(new BatchSpanProcessor(exporter)); | ||
|
||
// Create the Cloud Spanner Client. | ||
const {Spanner} = require('@google-cloud/spanner'); | ||
const spanner = new Spanner({ | ||
projectId: projectId, | ||
observabilityOptions: { | ||
// Inject the TracerProvider via SpannerOptions or | ||
// register it as a global by invoking `provider.register()` | ||
tracerProvider: provider, | ||
}, | ||
}); | ||
``` | ||
|
||
#### SQL Statement span annotation | ||
|
||
To allow your SQL statements to be annotated in the appropriate spans, you need to opt-in, because | ||
SQL statements can contain sensitive personally-identifiable-information (PII). | ||
|
||
You can opt-in by either: | ||
|
||
* Setting the environment variable `SPANNER_ENABLE_EXTENDED_TRACING=true` before your application is started | ||
* In code, setting `enableExtendedTracing: true` in your SpannerOptions before creating the Cloud Spanner client | ||
|
||
```javascript | ||
const spanner = new Spanner({ | ||
projectId: projectId, | ||
observabilityOptions: { | ||
tracerProvider: provider, | ||
enableExtendedTracing: true, | ||
}, | ||
``` | ||
#### OpenTelemetry gRPC instrumentation | ||
Optionally, you can enable OpenTelemetry gRPC instrumentation which produces traces of executed remote procedure calls (RPCs) | ||
in your programs by these imports and instantiation. You could pass in the traceProvider or register it globally | ||
by invoking `tracerProvider.register()` | ||
```javascript | ||
const {registerInstrumentations} = require('@opentelemetry/instrumentation'); | ||
const {GrpcInstrumentation} = require('@opentelemetry/instrumentation-grpc'); | ||
registerInstrumentations({ | ||
tracerProvider: tracerProvider, | ||
instrumentations: [new GrpcInstrumentation()], | ||
}); | ||
``` | ||
#### Tracing Sample | ||
For more information please see this [sample code](./samples/observability-traces.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/*! | ||
* Copyright 2024 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 | ||
// usage: node observability-traces.js <PROJECT-ID> <INSTANCE-ID> <DATABASE-ID> | ||
|
||
'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)); | ||
|
||
// 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. | ||
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 spanner = new Spanner({ | ||
projectId: projectId, | ||
observabilityOptions: { | ||
tracerProvider: provider, | ||
enableExtendedTracing: true, | ||
}, | ||
}); | ||
|
||
// 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)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters