Skip to content

Database API instrumentation customize operation name #3714

@Martin19037

Description

@Martin19037

What problem do you want to solve?

Currently, the span name produced by the dbapi instrumentation is constructed by skipping any potential leading comment and returning the first word of the query text. In my particular case, this often results in names such as "declare" or "select", and I have to check the actual db.statement in the span to find out what kind of query it actually was. As an out-of-the-box solution without any special configuration, this is good enough, but I would like to be able to refine the name if my query actually allows me to do so.

Describe the solution you'd like

I see two possible solutions:

Allow customization of the get_operation_name function
Introduce a hook parameter in the opentelemetry.instrumentation.dbapi.trace_integration function, with the same parameter spec as the current get_operation_name function, allowing you to customize the span name. Exposing the current implementation would also allow you to use it as a fallback method in your own hook.

Example usage:

import pyodbc
from opentelemetry.instrumentation.dbapi import CursorTracer, trace_integration
from opentelemetry.instrumentation.dbapi import get_operation_name  # pre-existing implementation

def my_operation_name(cursor: Any, args: tuple[Any, ...]) -> str:
    # Custom logic to produce span name
    # For example, look for well-known formatted comment in query text
    if (...):
        ...

    return get_operation_name(cursor, args)  # fall back to default implementation

trace_integration(pyodbc, 'Connection', 'odbc', get_operation_name=my_operation_name)
trace_integration(pyodbc, 'connect', 'odbc', get_operation_name=my_operation_name)

Span hook
The first proposed solution would only allow customization of the span name. Taking inspiration from the opentelemetry.instrumentation.fastapi package and its server_request_hook, you can take this concept further and allow customization of the whole span via a hook function.

import pyodbc
from opentelemetry.instrumentation.dbapi import CursorTracer, trace_integration
from opentelemetry.trace import Span

def my_span_hook(span: Span, cursor: Any, args: tuple[Any, ...]) -> None:
    # Customize the span as needed, not just name, but also attributes
    span.update_name('Custom operation')

trace_integration(pyodbc, 'Connection', 'odbc', span_hook=my_span_hook)
trace_integration(pyodbc, 'connect', 'odbc', span_hook=my_span_hook)

Describe alternatives you've considered

I did some experiments monkey patching the CursorTracer.get_operation_name method, similar to how the first proposal would function. While this does work, it relies on internal implementation detail and is likely to break with any update.

Additional Context

No response

Would you like to implement a fix?

None

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions