Skip to content

Commit b44bf41

Browse files
authored
test: Adding functional tests for MySQL integration (#526)
E2E verification for span creation using mysql and dbapi integrations
1 parent 7c2ceba commit b44bf41

4 files changed

Lines changed: 153 additions & 5 deletions

File tree

ext/opentelemetry-ext-docker-tests/tests/check_availability.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2020, OpenTelemetry Authors
1+
# Copyright The OpenTelemetry Authors
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -11,17 +11,23 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import logging
1415
import os
1516
import time
16-
import traceback
1717

18+
import mysql.connector
1819
import psycopg2
1920
import pymongo
2021

2122
MONGODB_COLLECTION_NAME = "test"
2223
MONGODB_DB_NAME = os.getenv("MONGODB_DB_NAME", "opentelemetry-tests")
2324
MONGODB_HOST = os.getenv("MONGODB_HOST", "localhost")
2425
MONGODB_PORT = int(os.getenv("MONGODB_PORT", "27017"))
26+
MYSQL_DB_NAME = os.getenv("MYSQL_DB_NAME ", "opentelemetry-tests")
27+
MYSQL_HOST = os.getenv("MYSQL_HOST ", "localhost")
28+
MYSQL_PORT = int(os.getenv("MYSQL_PORT ", "3306"))
29+
MYSQL_USER = os.getenv("MYSQL_USER ", "testuser")
30+
MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD ", "testpassword")
2531
POSTGRES_DB_NAME = os.getenv("POSTGRESQL_DB_NAME", "opentelemetry-tests")
2632
POSTGRES_HOST = os.getenv("POSTGRESQL_HOST", "localhost")
2733
POSTGRES_PASSWORD = os.getenv("POSTGRESQL_HOST", "testpassword")
@@ -30,6 +36,8 @@
3036
RETRY_COUNT = 5
3137
RETRY_INTERVAL = 5 # Seconds
3238

39+
logger = logging.getLogger(__name__)
40+
3341

3442
def check_pymongo_connection():
3543
# Try to connect to DB
@@ -46,7 +54,27 @@ def check_pymongo_connection():
4654
except Exception as ex:
4755
if i == RETRY_COUNT - 1:
4856
raise (ex)
49-
traceback.print_exc()
57+
logger.exception(ex)
58+
time.sleep(RETRY_INTERVAL)
59+
60+
61+
def check_mysql_connection():
62+
# Try to connect to DB
63+
for i in range(RETRY_COUNT):
64+
try:
65+
connection = mysql.connector.connect(
66+
user=MYSQL_USER,
67+
password=MYSQL_PASSWORD,
68+
host=MYSQL_HOST,
69+
port=MYSQL_PORT,
70+
database=MYSQL_DB_NAME,
71+
)
72+
connection.close()
73+
break
74+
except Exception as ex:
75+
if i == RETRY_COUNT - 1:
76+
raise (ex)
77+
logger.exception(ex)
5078
time.sleep(RETRY_INTERVAL)
5179

5280

@@ -66,13 +94,14 @@ def check_postgres_connection():
6694
except Exception as ex:
6795
if i == RETRY_COUNT - 1:
6896
raise (ex)
69-
traceback.print_exc()
97+
logger.exception(ex)
7098
time.sleep(RETRY_INTERVAL)
7199

72100

73101
def check_docker_services_availability():
74102
# Check if Docker services accept connections
75103
check_pymongo_connection()
104+
check_mysql_connection()
76105
check_postgres_connection()
77106

78107

ext/opentelemetry-ext-docker-tests/tests/docker-compose.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@ services:
55
ports:
66
- "27017:27017"
77
image: mongo:latest
8-
8+
otmysql:
9+
ports:
10+
- "3306:3306"
11+
image: mysql:latest
12+
restart: always
13+
environment:
14+
MYSQL_USER: testuser
15+
MYSQL_PASSWORD: testpassword
16+
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
17+
MYSQL_DATABASE: opentelemetry-tests
918
otpostgres:
1019
image: postgres
1120
ports:
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
import time
17+
import unittest
18+
19+
import mysql.connector
20+
21+
from opentelemetry import trace as trace_api
22+
from opentelemetry.ext.mysql import trace_integration
23+
from opentelemetry.sdk.trace import Tracer, TracerProvider
24+
from opentelemetry.sdk.trace.export import SimpleExportSpanProcessor
25+
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
26+
InMemorySpanExporter,
27+
)
28+
29+
MYSQL_USER = os.getenv("MYSQL_USER ", "testuser")
30+
MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD ", "testpassword")
31+
MYSQL_HOST = os.getenv("MYSQL_HOST ", "localhost")
32+
MYSQL_PORT = int(os.getenv("MYSQL_PORT ", "3306"))
33+
MYSQL_DB_NAME = os.getenv("MYSQL_DB_NAME ", "opentelemetry-tests")
34+
35+
36+
class TestFunctionalMysql(unittest.TestCase):
37+
@classmethod
38+
def setUpClass(cls):
39+
cls._connection = None
40+
cls._cursor = None
41+
cls._tracer_provider = TracerProvider()
42+
cls._tracer = Tracer(cls._tracer_provider, None)
43+
cls._span_exporter = InMemorySpanExporter()
44+
cls._span_processor = SimpleExportSpanProcessor(cls._span_exporter)
45+
cls._tracer_provider.add_span_processor(cls._span_processor)
46+
trace_integration(cls._tracer)
47+
cls._connection = mysql.connector.connect(
48+
user=MYSQL_USER,
49+
password=MYSQL_PASSWORD,
50+
host=MYSQL_HOST,
51+
port=MYSQL_PORT,
52+
database=MYSQL_DB_NAME,
53+
)
54+
cls._cursor = cls._connection.cursor()
55+
56+
@classmethod
57+
def tearDownClass(cls):
58+
if cls._connection:
59+
cls._connection.close()
60+
61+
def setUp(self):
62+
self._span_exporter.clear()
63+
64+
def validate_spans(self):
65+
spans = self._span_exporter.get_finished_spans()
66+
self.assertEqual(len(spans), 2)
67+
for span in spans:
68+
if span.name == "rootSpan":
69+
root_span = span
70+
else:
71+
db_span = span
72+
self.assertIsInstance(span.start_time, int)
73+
self.assertIsInstance(span.end_time, int)
74+
self.assertIsNotNone(root_span)
75+
self.assertIsNotNone(db_span)
76+
self.assertEqual(root_span.name, "rootSpan")
77+
self.assertEqual(db_span.name, "mysql.opentelemetry-tests")
78+
self.assertIsNotNone(db_span.parent)
79+
self.assertEqual(db_span.parent.name, root_span.name)
80+
self.assertIs(db_span.kind, trace_api.SpanKind.CLIENT)
81+
self.assertEqual(db_span.attributes["db.instance"], MYSQL_DB_NAME)
82+
self.assertEqual(db_span.attributes["net.peer.name"], MYSQL_HOST)
83+
self.assertEqual(db_span.attributes["net.peer.port"], MYSQL_PORT)
84+
85+
def test_execute(self):
86+
"""Should create a child span for execute
87+
"""
88+
with self._tracer.start_as_current_span("rootSpan"):
89+
self._cursor.execute("CREATE TABLE IF NOT EXISTS test (id INT)")
90+
self.validate_spans()
91+
92+
def test_executemany(self):
93+
"""Should create a child span for executemany
94+
"""
95+
with self._tracer.start_as_current_span("rootSpan"):
96+
data = ["1", "2", "3"]
97+
stmt = "INSERT INTO test (id) VALUES (%s)"
98+
self._cursor.executemany(stmt, data)
99+
self.validate_spans()
100+
101+
def test_callproc(self):
102+
"""Should create a child span for callproc
103+
"""
104+
with self._tracer.start_as_current_span("rootSpan"), self.assertRaises(
105+
Exception
106+
):
107+
self._cursor.callproc("test", ())
108+
self.validate_spans()

tox.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ commands =
259259
deps =
260260
pytest
261261
docker-compose >= 1.25.2
262+
mysql-connector-python ~= 8.0
262263
pymongo ~= 3.1
263264
psycopg2 ~= 2.8.4
264265

@@ -269,6 +270,7 @@ commands_pre =
269270
pip install -e {toxinidir}/opentelemetry-api \
270271
-e {toxinidir}/opentelemetry-sdk \
271272
-e {toxinidir}/ext/opentelemetry-ext-dbapi \
273+
-e {toxinidir}/ext/opentelemetry-ext-mysql \
272274
-e {toxinidir}/ext/opentelemetry-ext-psycopg2 \
273275
-e {toxinidir}/ext/opentelemetry-ext-pymongo
274276
docker-compose up -d

0 commit comments

Comments
 (0)