-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add OpenTelemetry tracing to spanner calls (#107)
* feat: add optional span creation with OpenTelemetry * bring back support for python2.7 * address comments * fix 2.7 tests * nit fixes * db.statement join with ; * Update docs/opentelemetry-tracing.rst Co-authored-by: larkee <[email protected]>
- Loading branch information
Showing
15 changed files
with
910 additions
and
92 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
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,36 @@ | ||
Tracing with OpenTelemetry | ||
================================== | ||
This library uses `OpenTelemetry <https://opentelemetry.io/>`_ to automatically generate traces providing insight on calls to Cloud Spanner. | ||
For information on the benefits and utility of tracing, see the `Cloud Trace docs <https://cloud.google.com/trace/docs/overview>`_. | ||
|
||
To take advantage of these traces, we first need to install opentelemetry: | ||
|
||
.. code-block:: sh | ||
pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation | ||
We also need to tell OpenTelemetry which exporter to use. For example, to export python-spanner traces to `Cloud Tracing <https://cloud.google.com/trace>`_, add the following lines to your application: | ||
|
||
.. code:: python | ||
from opentelemetry import trace | ||
from opentelemetry.sdk.trace import TracerProvider | ||
from opentelemetry.trace.sampling import ProbabilitySampler | ||
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter | ||
# BatchExportSpanProcessor exports spans to Cloud Trace | ||
# in a seperate thread to not block on the main thread | ||
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor | ||
# Create and export one trace every 1000 requests | ||
sampler = ProbabilitySampler(1/1000) | ||
# Use the default tracer provider | ||
trace.set_tracer_provider(TracerProvider(sampler=sampler)) | ||
trace.get_tracer_provider().add_span_processor( | ||
# Initialize the cloud tracing exporter | ||
BatchExportSpanProcessor(CloudTraceSpanExporter()) | ||
) | ||
Generated spanner traces should now be available on `Cloud Trace <https://console.cloud.google.com/traces>`_. | ||
|
||
Tracing is most effective when many libraries are instrumented to provide insight over the entire lifespan of a request. | ||
For a list of libraries that can be instrumented, see the `OpenTelemetry Integrations` section of the `OpenTelemetry Python docs <https://opentelemetry-python.readthedocs.io/en/stable/>`_ |
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,65 @@ | ||
# Copyright 2020 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. | ||
|
||
"""Manages OpenTelemetry trace creation and handling""" | ||
|
||
from contextlib import contextmanager | ||
|
||
from google.api_core.exceptions import GoogleAPICallError | ||
from google.cloud.spanner_v1.gapic import spanner_client | ||
|
||
try: | ||
from opentelemetry import trace | ||
from opentelemetry.trace.status import Status, StatusCanonicalCode | ||
from opentelemetry.instrumentation.utils import http_status_to_canonical_code | ||
|
||
HAS_OPENTELEMETRY_INSTALLED = True | ||
except ImportError: | ||
HAS_OPENTELEMETRY_INSTALLED = False | ||
|
||
|
||
@contextmanager | ||
def trace_call(name, session, extra_attributes=None): | ||
if not HAS_OPENTELEMETRY_INSTALLED or not session: | ||
# Empty context manager. Users will have to check if the generated value is None or a span | ||
yield None | ||
return | ||
|
||
tracer = trace.get_tracer(__name__) | ||
|
||
# Set base attributes that we know for every trace created | ||
attributes = { | ||
"db.type": "spanner", | ||
"db.url": spanner_client.SpannerClient.SERVICE_ADDRESS, | ||
"db.instance": session._database.name, | ||
"net.host.name": spanner_client.SpannerClient.SERVICE_ADDRESS, | ||
} | ||
|
||
if extra_attributes: | ||
attributes.update(extra_attributes) | ||
|
||
with tracer.start_as_current_span( | ||
name, kind=trace.SpanKind.CLIENT, attributes=attributes | ||
) as span: | ||
try: | ||
yield span | ||
except GoogleAPICallError as error: | ||
if error.code is not None: | ||
span.set_status(Status(http_status_to_canonical_code(error.code))) | ||
elif error.grpc_status_code is not None: | ||
span.set_status( | ||
# OpenTelemetry's StatusCanonicalCode maps 1-1 with grpc status codes | ||
Status(StatusCanonicalCode(error.grpc_status_code.value[0])) | ||
) | ||
raise |
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
Oops, something went wrong.