Skip to content

Commit

Permalink
auto-instr: Add support for programmatic instrumentation (#579)
Browse files Browse the repository at this point in the history
Fixes #554

This makes it possible to call the instrument method with arguments that make programmatic instrumentation possible.

This also makes the children of BaseInstrumentors to be singletons. In this way regardless of how many times the programmatic instrumentation or uninstrumentation methods are called they will only be executed once.
  • Loading branch information
ocelotl authored Apr 22, 2020
1 parent 16b9d88 commit 305c1f4
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ def __init__(self):
super().__init__()
self._original_flask = None

def _instrument(self):
def _instrument(self, **kwargs):
self._original_flask = flask.Flask
flask.Flask = _InstrumentedFlask

def _uninstrument(self):
def _uninstrument(self, **kwargs):
flask.Flask = self._original_flask
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,41 @@
class BaseInstrumentor(ABC):
"""An ABC for instrumentors"""

def __init__(self):
self._is_instrumented = False
_instance = None
_is_instrumented = False

def __new__(cls):

if cls._instance is None:
cls._instance = object.__new__(cls)

return cls._instance

@abstractmethod
def _instrument(self) -> None:
def _instrument(self, **kwargs):
"""Instrument"""

@abstractmethod
def _uninstrument(self) -> None:
def _uninstrument(self, **kwargs):
"""Uninstrument"""

def instrument(self) -> None:
def instrument(self, **kwargs):
"""Instrument"""

if not self._is_instrumented:
result = self._instrument()
result = self._instrument(**kwargs)
self._is_instrumented = True
return result

_LOG.warning("Attempting to instrument while already instrumented")

return None

def uninstrument(self) -> None:
def uninstrument(self, **kwargs):
"""Uninstrument"""

if self._is_instrumented:
result = self._uninstrument()
result = self._uninstrument(**kwargs)
self._is_instrumented = False
return result

Expand Down
18 changes: 10 additions & 8 deletions opentelemetry-auto-instrumentation/tests/test_instrumentor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,27 @@


class TestInstrumentor(TestCase):
def test_protect(self):
class Instrumentor(BaseInstrumentor):
def _instrument(self):
return "instrumented"
class Instrumentor(BaseInstrumentor):
def _instrument(self, **kwargs):
return "instrumented"

def _uninstrument(self):
return "uninstrumented"
def _uninstrument(self, **kwargs):
return "uninstrumented"

instrumentor = Instrumentor()
def test_protect(self):
instrumentor = self.Instrumentor()

with self.assertLogs(level=WARNING):
self.assertIs(instrumentor.uninstrument(), None)

self.assertEqual(instrumentor.instrument(), "instrumented")

with self.assertLogs(level=WARNING):
self.assertIs(instrumentor.instrument(), None)

self.assertEqual(instrumentor.uninstrument(), "uninstrumented")

with self.assertLogs(level=WARNING):
self.assertIs(instrumentor.uninstrument(), None)

def test_singleton(self):
self.assertIs(self.Instrumentor(), self.Instrumentor())

0 comments on commit 305c1f4

Please sign in to comment.