def test_custom_tracer_provider(self):
        provider = TracerProvider(
            resource=Resource.create(
                {
                    "service.name": "test",
                    "deployment.environment": "env",
                    "service.version": "1234",
                },
            ),
        )
        provider.add_span_processor(
            export.SimpleSpanProcessor(self.memory_exporter)
        )

        SQLAlchemyInstrumentor().instrument(tracer_provider=provider)
        from sqlalchemy import create_engine  # pylint: disable-all

        engine = create_engine("sqlite:///:memory:")
        cnx = engine.connect()
        cnx.execute("SELECT	1 + 1;").fetchall()
        spans = self.memory_exporter.get_finished_spans()

        self.assertEqual(len(spans), 2)
        self.assertEqual(spans[0].resource.attributes["service.name"], "test")
        self.assertEqual(
            spans[0].resource.attributes["deployment.environment"], "env"
        )
        self.assertEqual(
            spans[0].resource.attributes["service.version"], "1234"
        )
Пример #2
0
 def tearDown(self):
     # pylint: disable=invalid-name
     # clear the database and dispose the engine
     self.session.close()
     Base.metadata.drop_all(bind=self.engine)
     self.engine.dispose()
     SQLAlchemyInstrumentor().uninstrument()
     super().tearDown()
    def test_sqlcommenter_disabled(self):
        logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
        engine = create_engine("sqlite:///:memory:", echo=True)
        SQLAlchemyInstrumentor().instrument(
            engine=engine, tracer_provider=self.tracer_provider)
        cnx = engine.connect()
        cnx.execute("SELECT 1;").fetchall()

        self.assertEqual(self.caplog.records[-2].getMessage(), "SELECT 1;")
Пример #4
0
 def instrument_app(self) -> None:
     logger.info("Activating Opentelemetry tracing to app", app=self.title)
     trace.set_tracer_provider(tracer_provider)
     FastAPIInstrumentor.instrument_app(self)
     RequestsInstrumentor().instrument()
     HTTPXClientInstrumentor().instrument()
     RedisInstrumentor().instrument()
     Psycopg2Instrumentor().instrument()
     SQLAlchemyInstrumentor().instrument(engine=db.engine,
                                         tracer_provider=tracer_provider)
Пример #5
0
    def setUp(self):
        # create a traced engine with the given arguments
        SQLAlchemyInstrumentor().instrument()
        dsn = (
            "postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s" %
            POSTGRES_CONFIG)
        self.engine = sqlalchemy.create_engine(dsn)

        # prepare a connection
        self.conn = self.engine.connect()
        super().setUp()
    def test_instrument_engine_connect(self):
        engine = create_engine("sqlite:///:memory:")

        SQLAlchemyInstrumentor().instrument(
            engine=engine,
            tracer_provider=self.tracer_provider,
        )

        engine.connect()
        spans = self.memory_exporter.get_finished_spans()
        self.assertEqual(len(spans), 1)
    def test_create_engine_wrapper(self):
        SQLAlchemyInstrumentor().instrument()
        from sqlalchemy import create_engine  # pylint: disable-all

        engine = create_engine("sqlite:///:memory:")
        cnx = engine.connect()
        cnx.execute("SELECT	1 + 1;").fetchall()
        spans = self.memory_exporter.get_finished_spans()

        self.assertEqual(len(spans), 1)
        self.assertEqual(spans[0].name, "SELECT	1 + 1;")
    def test_trace_integration(self):
        engine = create_engine("sqlite:///:memory:")
        SQLAlchemyInstrumentor().instrument(
            engine=engine,
            tracer_provider=self.tracer_provider,
        )
        cnx = engine.connect()
        cnx.execute("SELECT	1 + 1;").fetchall()
        spans = self.memory_exporter.get_finished_spans()

        self.assertEqual(len(spans), 1)
        self.assertEqual(spans[0].name, "SELECT	1 + 1;")
Пример #9
0
        async def run():
            SQLAlchemyInstrumentor().instrument()
            from sqlalchemy.ext.asyncio import (  # pylint: disable-all
                create_async_engine, )

            engine = create_async_engine("sqlite+aiosqlite:///:memory:")
            async with engine.connect() as cnx:
                await cnx.execute(sqlalchemy.text("SELECT	1 + 1;"))
            spans = self.memory_exporter.get_finished_spans()
            self.assertEqual(len(spans), 1)
            self.assertEqual(spans[0].name, "SELECT :memory:")
            self.assertEqual(spans[0].kind, trace.SpanKind.CLIENT)
Пример #10
0
    def setUp(self):
        super().setUp()
        # create an engine with the given arguments
        self.engine = _create_engine(self.ENGINE_ARGS)

        # create the database / entities and prepare a session for the test
        Base.metadata.drop_all(bind=self.engine)
        Base.metadata.create_all(self.engine, checkfirst=False)
        self.session = sessionmaker(bind=self.engine)()
        # trace the engine
        SQLAlchemyInstrumentor().instrument(
            engine=self.engine, tracer_provider=self.tracer_provider)
        self.memory_exporter.clear()
 def test_sqlcommenter_enabled(self):
     engine = create_engine("sqlite:///:memory:")
     SQLAlchemyInstrumentor().instrument(
         engine=engine,
         tracer_provider=self.tracer_provider,
         enable_commenter=True,
         commenter_options={"db_framework": False},
     )
     cnx = engine.connect()
     cnx.execute("SELECT  1;").fetchall()
     self.assertRegex(
         self.caplog.records[-2].getMessage(),
         r"SELECT  1 /\*db_driver='(.*)',traceparent='\d{1,2}-[a-zA-Z0-9_]{32}-[a-zA-Z0-9_]{16}-\d{1,2}'\*/;",
     )
    def test_instrument_two_engines(self):
        engine_1 = create_engine("sqlite:///:memory:")
        engine_2 = create_engine("sqlite:///:memory:")

        SQLAlchemyInstrumentor().instrument(
            engines=[engine_1, engine_2],
            tracer_provider=self.tracer_provider,
        )

        cnx_1 = engine_1.connect()
        cnx_1.execute("SELECT	1 + 1;").fetchall()
        cnx_2 = engine_2.connect()
        cnx_2.execute("SELECT	1 + 1;").fetchall()

        spans = self.memory_exporter.get_finished_spans()
        # 2 queries + 2 engine connect
        self.assertEqual(len(spans), 4)
    def test_trace_integration(self):
        engine = create_engine("sqlite:///:memory:")
        SQLAlchemyInstrumentor().instrument(
            engine=engine,
            tracer_provider=self.tracer_provider,
        )
        cnx = engine.connect()
        cnx.execute("SELECT	1 + 1;").fetchall()
        spans = self.memory_exporter.get_finished_spans()

        self.assertEqual(len(spans), 2)
        # first span - the connection to the db
        self.assertEqual(spans[0].name, "connect")
        self.assertEqual(spans[0].kind, trace.SpanKind.CLIENT)
        # second span - the query itself
        self.assertEqual(spans[1].name, "SELECT :memory:")
        self.assertEqual(spans[1].kind, trace.SpanKind.CLIENT)
Пример #14
0
 def test_not_recording(self):
     mock_tracer = mock.Mock()
     mock_span = mock.Mock()
     mock_span.is_recording.return_value = False
     mock_tracer.start_span.return_value = mock_span
     with mock.patch("opentelemetry.trace.get_tracer") as tracer:
         tracer.return_value = mock_tracer
         engine = create_engine("sqlite:///:memory:")
         SQLAlchemyInstrumentor().instrument(
             engine=engine, tracer_provider=self.tracer_provider,
         )
         cnx = engine.connect()
         cnx.execute("SELECT	1 + 1;").fetchall()
         self.assertFalse(mock_span.is_recording())
         self.assertTrue(mock_span.is_recording.called)
         self.assertFalse(mock_span.set_attribute.called)
         self.assertFalse(mock_span.set_status.called)
Пример #15
0
    def __init__(self, uri, logger=logging):
        self.engine = create_engine(uri)
        self.logger = logger
        self.contacts_table = Table(
            "contacts",
            MetaData(self.engine),
            Column("username", String, nullable=False),
            Column("label", String, nullable=False),
            Column("account_num", String, nullable=False),
            Column("routing_num", String, nullable=False),
            Column("is_external", Boolean, nullable=False),
        )

        # Set up tracing autoinstrumentation for sqlalchemy
        SQLAlchemyInstrumentor().instrument(
            engine=self.engine,
            service="contacts",
        )
    def test_create_engine_wrapper(self):
        SQLAlchemyInstrumentor().instrument()
        from sqlalchemy import create_engine  # pylint: disable-all

        engine = create_engine("sqlite:///:memory:")
        cnx = engine.connect()
        cnx.execute("SELECT	1 + 1;").fetchall()
        spans = self.memory_exporter.get_finished_spans()

        self.assertEqual(len(spans), 2)
        # first span - the connection to the db
        self.assertEqual(spans[0].name, "connect")
        self.assertEqual(spans[0].kind, trace.SpanKind.CLIENT)
        # second span - the query
        self.assertEqual(spans[1].name, "SELECT :memory:")
        self.assertEqual(spans[1].kind, trace.SpanKind.CLIENT)
        self.assertEqual(
            spans[1].instrumentation_scope.name,
            "opentelemetry.instrumentation.sqlalchemy",
        )
        async def run():
            SQLAlchemyInstrumentor().instrument()
            from sqlalchemy.ext.asyncio import (  # pylint: disable-all
                create_async_engine,
            )

            engine = create_async_engine("sqlite+aiosqlite:///:memory:")
            async with engine.connect() as cnx:
                await cnx.execute(sqlalchemy.text("SELECT	1 + 1;"))
            spans = self.memory_exporter.get_finished_spans()
            self.assertEqual(len(spans), 2)
            # first span - the connection to the db
            self.assertEqual(spans[0].name, "connect")
            self.assertEqual(spans[0].kind, trace.SpanKind.CLIENT)
            # second span - the query
            self.assertEqual(spans[1].name, "SELECT :memory:")
            self.assertEqual(spans[1].kind, trace.SpanKind.CLIENT)
            self.assertEqual(
                spans[1].instrumentation_scope.name,
                "opentelemetry.instrumentation.sqlalchemy",
            )
Пример #18
0
    def __init__(self, uri, logger=logging):
        self.engine = create_engine(uri)
        self.logger = logger
        self.users_table = Table(
            'users',
            MetaData(self.engine),
            Column('accountid', String, primary_key=True),
            Column('username', String, unique=True, nullable=False),
            Column('passhash', LargeBinary, nullable=False),
            Column('firstname', String, nullable=False),
            Column('lastname', String, nullable=False),
            Column('birthday', Date, nullable=False),
            Column('timezone', String, nullable=False),
            Column('address', String, nullable=False),
            Column('state', String, nullable=False),
            Column('zip', String, nullable=False),
            Column('ssn', String, nullable=False),
        )

        # Set up tracing autoinstrumentation for sqlalchemy
        SQLAlchemyInstrumentor().instrument(
            engine=self.engine,
            service='users',
        )
Пример #19
0
    def __init__(self, app, service='atlas-api', sqlalchemy_engine=None, datadog_agent=None,
                 span_callback=None, ignored_paths: List[str] = None, sql_service=None):
        self.app = app
        trace.set_tracer_provider(TracerProvider())
        self.tracer = trace.get_tracer(__name__)
        if datadog_agent:
            from ddtrace.internal.writer import AgentWriter
            from opentelemetry.exporter.datadog import DatadogExportSpanProcessor, \
                DatadogSpanExporter
            exporter = DatadogSpanExporter(agent_url=datadog_agent, service=service)
            exporter._agent_writer = AgentWriter(datadog_agent)
            span_processor = DatadogExportSpanProcessor(exporter)
            trace.get_tracer_provider().add_span_processor(span_processor)

        AtlasFastAPIInstrumentor.instrument_app(app, span_callback=span_callback,
                                                ignored_paths=ignored_paths)
        RequestsInstrumentor().instrument()
        BotocoreInstrumentor().instrument(tracer_provider=trace.get_tracer_provider())
        BotoInstrumentor().instrument(tracer_provider=trace.get_tracer_provider())
        RedisInstrumentor().instrument(tracer_provider=trace.get_tracer_provider())
        if sqlalchemy_engine:
            sqlalch_service_name = service if not sql_service else sql_service
            SQLAlchemyInstrumentor().instrument(engine=sqlalchemy_engine,
                                                service=sqlalch_service_name)
 def tearDown(self):
     # clear the database and dispose the engine
     self.conn.close()
     self.engine.dispose()
     SQLAlchemyInstrumentor().uninstrument()
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

app = Flask(__name__)
app.config.from_object(Config)

db = SQLAlchemy(app)

# Set global TracerProvider before instrumenting
trace.set_tracer_provider(TracerProvider())

# Enable tracing for sqlalchemy library
SQLAlchemyInstrumentor().instrument()

# Enable tracing for Flask library
FlaskInstrumentor().instrument_app(app)

# Enable tracing for requests library
RequestsInstrumentor().instrument()

trace_exporter = AzureMonitorSpanExporter(
    connection_string=Config.CONNECTION_STRING
)
trace.get_tracer_provider().add_span_processor(
    BatchExportSpanProcessor(trace_exporter)
)

# Import here to avoid circular imports
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base

url = "mssql+pyodbc://sa:yourStrong(!)Password@localhost:1433/repro?driver=ODBC+Driver+17+for+SQL+Server"
engine = create_engine(url)
SQLAlchemyInstrumentor().instrument(engine=engine, )
Base = declarative_base()


class User(Base):
    __tablename__ = "user"

    id = Column(Integer, primary_key=True)
    name = Column(String(20))


def main():
    Base.metadata.drop_all(bind=engine)


if __name__ == "__main__":
    main()
Пример #23
0
 def tearDown(self):
     super().tearDown()
     SQLAlchemyInstrumentor().uninstrument()