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()