open-telemetry / open-telemetry/opentelemetry-python-contrib

psycopg2 instrumentation with cursor argument doesn't work

Open
#1,479 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug help wanted instrumentation
Dominant language
Python
Stars
1.1k
Forks
1.1k
Avg merge
4d 15h
Merged PRs (30d)
16

Description

Environment
python3.10
opentelemetry-instrumentation-psycopg2: 0.35b2

Steps to reproduce

import psycopg2
import psycopg2.extras
import opentelemetry.instrumentation.psycopg2
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider, sampling
from opentelemetry.sdk.trace.export import BatchSpanProcessor


def main():
    tracer_provider = TracerProvider(
        sampler=sampling.ALWAYS_ON,
        resource=Resource.create(
            {
                "service.name": "test-postgresql-instrumentation",
                "service.version": "1.0.0",
            }
        ),
    )
    trace.set_tracer_provider(tracer_provider)

    tracer_provider.add_span_processor(
        BatchSpanProcessor(
            OTLPSpanExporter(
                endpoint="https://<url>/e/<id>/api/v2/otlp/v1/traces",
                headers={
                    "Authorization": "Api-Token <token>"
                },
            )
        )
    )
    tracer = trace.get_tracer("test-postgresql-instrumentation-tracer")

    opentelemetry.instrumentation.psycopg2.Psycopg2Instrumentor().instrument()

    cnx = psycopg2.connect(database="test_db_name")
    cursor = cnx.cursor(cursor_factory=psycopg2.extras.DictCursor)
    with tracer.start_as_current_span("main-test-span"):
        cursor.execute("SELECT * FROM test")
    cursor.close()
    cnx.close()


if __name__ == "__main__":
    main()

What is the expected behavior?
SELECT instrumentation record in main-test-span

What is the actual behavior?
No SELECT record

Additional context
This works (cursor_factory attribute moved to connect method):

import psycopg2
import psycopg2.extras
import opentelemetry.instrumentation.psycopg2
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider, sampling
from opentelemetry.sdk.trace.export import BatchSpanProcessor


def main():
    tracer_provider = TracerProvider(
        sampler=sampling.ALWAYS_ON,
        resource=Resource.create(
            {
                "service.name": "test-postgresql-instrumentation",
                "service.version": "1.0.0",
            }
        ),
    )
    trace.set_tracer_provider(tracer_provider)

    tracer_provider.add_span_processor(
        BatchSpanProcessor(
            OTLPSpanExporter(
                endpoint="https://<url>/e/<id>/api/v2/otlp/v1/traces",
                headers={
                    "Authorization": "Api-Token <token>"
                },
            )
        )
    )
    tracer = trace.get_tracer("test-postgresql-instrumentation-tracer")

    opentelemetry.instrumentation.psycopg2.Psycopg2Instrumentor().instrument()

    cnx = psycopg2.connect(database="test_db_name", cursor_factory=psycopg2.extras.DictCursor)
    cursor = cnx.cursor()
    with tracer.start_as_current_span("main-test-span"):
        cursor.execute("SELECT * FROM test")
    cursor.close()
    cnx.close()


if __name__ == "__main__":
    main()

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at Psycopg2Instrumentor and trace how cursor_factory is handled when passed to cnx.cursor(), comparing it with the working connect(..., cursor_factory=...) case. Reproduce both examples, then verify that cursor.execute("SELECT * FROM test") creates a SELECT record inside main-test-span in each case.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, python
Domain
databases
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.