Skip to content

Commit

Permalink
feat: capture OpenTelemetry logs
Browse files Browse the repository at this point in the history
This makes sure that if error while uploading are triggered they are
reported at the end of the test session. This makes it easier to debug
issues.

Change-Id: I1dbd3e032e49ed916e2a02102dc68e706ea1cab5
  • Loading branch information
jd committed Dec 19, 2024
1 parent ed6a94b commit 9499e66
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
13 changes: 13 additions & 0 deletions pytest_mergify/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ def pytest_terminal_summary(
) -> None:
terminalreporter.section("Mergify CI")

# Make sure we shutdown and flush traces before existing: this makes
# sure that we capture the possible error logs, otherwise they are
# emitted on exit (atexit()).
if self.mergify_tracer.tracer_provider is not None:
self.mergify_tracer.tracer_provider.shutdown() # type: ignore[no-untyped-call]

if self.mergify_tracer.log_handler.log_list:
terminalreporter.write_line(
"There are been some errors reported by the tracer:", red=True
)
for line in self.mergify_tracer.log_handler.log_list:
terminalreporter.write_line(line)

if self.mergify_tracer.token is None:
terminalreporter.write_line(
"No token configured for Mergify; test results will not be uploaded",
Expand Down
27 changes: 27 additions & 0 deletions pytest_mergify/tracer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dataclasses
import logging
import os

import opentelemetry.sdk.resources
Expand Down Expand Up @@ -32,6 +33,17 @@ def on_start(
self.trace_id = span.context.trace_id


class ListLogHandler(logging.Handler):
"""Custom logging handler to capture log messages into a list."""

def __init__(self) -> None:
super().__init__()
self.log_list: list[str] = []

def emit(self, record: logging.LogRecord) -> None:
self.log_list.append(self.format(record))


@dataclasses.dataclass
class MergifyTracer:
token: str | None = dataclasses.field(
Expand All @@ -51,10 +63,25 @@ class MergifyTracer:
tracer_provider: opentelemetry.sdk.trace.TracerProvider | None = dataclasses.field(
init=False, default=None
)
log_handler: ListLogHandler = dataclasses.field(
init=False, default_factory=ListLogHandler
)

def __post_init__(self) -> None:
span_processor: SpanProcessor

# Set up the logger
self.log_handler.setLevel(logging.ERROR) # Capture ERROR logs by default
self.log_handler.setFormatter(
logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
)

logger = logging.getLogger("opentelemetry")
# FIXME: we should remove the handler when this tracer is not used
# (e.g., reconfigure() is called) Since reconfigure() is unlikely to be
# called outside our testing things, it's not a big deal to leak it.
logger.addHandler(self.log_handler)

if os.environ.get("PYTEST_MERGIFY_DEBUG"):
self.exporter = export.ConsoleSpanExporter()
span_processor = export.SimpleSpanProcessor(self.exporter)
Expand Down
33 changes: 33 additions & 0 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,36 @@ def test_foo():
result = pytester.runpytest_subprocess()
result.assert_outcomes(passed=1)
assert "Nothing to do" in result.stdout.lines


def test_errors_logs(
pytester: _pytest.pytester.Pytester,
reconfigure_mergify_tracer: conftest.ReconfigureT,
) -> None:
# This will try to upload traces, but we don't have a real exporter so it will log errors.
reconfigure_mergify_tracer(
{
"MERGIFY_TOKEN": "true",
"CI": "1",
"GITHUB_ACTIONS": "true",
"GITHUB_REPOSITORY": "foo/bar",
}
)
pytester.makepyfile(
"""
import pytest
from pytest_mergify import utils
def test_span(pytestconfig):
plugin = pytestconfig.pluginmanager.get_plugin("PytestMergify")
assert plugin is not None
assert plugin.mergify_tracer.exporter is not None
"""
)
result = pytester.runpytest_subprocess()
result.assert_outcomes(passed=1)
assert any(
"There are been some errors reported by the tracer:" == line
for line in result.stdout.lines
)

0 comments on commit 9499e66

Please sign in to comment.