From 5503ba2f36b4e8cdc8f59c1979fd42cf5b2703d4 Mon Sep 17 00:00:00 2001 From: Ben Donnelly Date: Mon, 19 Feb 2024 10:10:55 +0000 Subject: [PATCH 1/3] feat(events): use events for snapshot in spans closes #39 --- src/deep/api/plugin/__init__.py | 3 ++- src/deep/api/plugin/otel.py | 17 ++++++++++++++++- src/deep/api/plugin/python.py | 3 ++- src/deep/api/plugin/span/__init__.py | 11 +++++++++++ src/deep/processor/context/snapshot_action.py | 2 +- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/deep/api/plugin/__init__.py b/src/deep/api/plugin/__init__.py index b7569d3..af3d908 100644 --- a/src/deep/api/plugin/__init__.py +++ b/src/deep/api/plugin/__init__.py @@ -148,10 +148,11 @@ class SnapshotDecorator(Plugin, abc.ABC): """Implement this to decorate collected snapshots with attributes.""" @abc.abstractmethod - def decorate(self, context: ActionContext) -> Optional[BoundedAttributes]: + def decorate(self, snapshot_id: str, context: ActionContext) -> Optional[BoundedAttributes]: """ Decorate a snapshot with additional data. + :param snapshot_id: the id of the collected snapshot :param context: the action context for this action :return: the additional attributes to attach diff --git a/src/deep/api/plugin/otel.py b/src/deep/api/plugin/otel.py index d0064ca..c92f698 100644 --- a/src/deep/api/plugin/otel.py +++ b/src/deep/api/plugin/otel.py @@ -67,6 +67,16 @@ def add_attribute(self, key: str, value: str): """ self.proxy.set_attribute(key, value) + def add_event(self, name, attributes=None): + """ + Add an event to the span. + + :param name: the event name + :param attributes: the event attributes + :return: + """ + self.proxy.add_event(name, attributes=attributes) + def close(self): """Close the span.""" if not self.proxy.end_time: @@ -132,16 +142,21 @@ def resource(self) -> Optional[Resource]: return Resource.create(attributes=attributes) return None - def decorate(self, context: ActionContext) -> Optional[BoundedAttributes]: + def decorate(self, snapshot_id: str, context: ActionContext) -> Optional[BoundedAttributes]: """ Decorate a snapshot with additional data. + :param snapshot_id: the id of the collected snapshot :param context: the action context for this action :return: the additional attributes to attach """ span = self.current_span() if span is not None: + span.add_event(context.location_action.location.name, + attributes={"snapshot": snapshot_id, + "tracepoint": context.location_action.id, + "context": context.trigger_context.id}) return BoundedAttributes(attributes={ "span_name": span.name, "trace_id": span.trace_id, diff --git a/src/deep/api/plugin/python.py b/src/deep/api/plugin/python.py index 22d7e38..f38343b 100644 --- a/src/deep/api/plugin/python.py +++ b/src/deep/api/plugin/python.py @@ -35,10 +35,11 @@ class PythonPlugin(ResourceProvider, SnapshotDecorator, TracepointLogger): This plugin provides the python version to the resource, and the thread name to the attributes. """ - def decorate(self, context: ActionContext) -> Optional[BoundedAttributes]: + def decorate(self, snapshot_id: str, context: ActionContext) -> Optional[BoundedAttributes]: """ Decorate a snapshot with additional data. + :param snapshot_id: the id of the collected snapshot :param context: the action context for this action :return: the additional attributes to attach diff --git a/src/deep/api/plugin/span/__init__.py b/src/deep/api/plugin/span/__init__.py index 4d68be8..859ab28 100644 --- a/src/deep/api/plugin/span/__init__.py +++ b/src/deep/api/plugin/span/__init__.py @@ -79,6 +79,17 @@ def add_attribute(self, key: str, value: str): """ pass + @abc.abstractmethod + def add_event(self, name, attributes=None): + """ + Add an event to the span. + + :param name: the event name + :param attributes: the event attributes + :return: + """ + pass + @abc.abstractmethod def close(self): """Close the span.""" diff --git a/src/deep/processor/context/snapshot_action.py b/src/deep/processor/context/snapshot_action.py index 8d95216..a699614 100644 --- a/src/deep/processor/context/snapshot_action.py +++ b/src/deep/processor/context/snapshot_action.py @@ -179,7 +179,7 @@ def _decorate_snapshot(self, ctx): attributes = BoundedAttributes(attributes={'ctx_id': ctx.id}, immutable=False) for decorator in ctx.config.snapshot_decorators: try: - decorate = decorator.decorate(self.action_context) + decorate = decorator.decorate(self.snapshot.id, self.action_context) if decorate is not None: attributes.merge_in(decorate) except Exception: From 4985afbcf61f51287a93d19afa41bf2e04f9ada5 Mon Sep 17 00:00:00 2001 From: Ben Donnelly Date: Mon, 19 Feb 2024 18:39:43 +0000 Subject: [PATCH 2/3] feat(events): fix tests --- tests/unit_tests/api/plugin/test_otel.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/api/plugin/test_otel.py b/tests/unit_tests/api/plugin/test_otel.py index 773a473..2979270 100644 --- a/tests/unit_tests/api/plugin/test_otel.py +++ b/tests/unit_tests/api/plugin/test_otel.py @@ -14,6 +14,7 @@ # along with this program. If not, see . import unittest +import mockito from opentelemetry import trace from opentelemetry.sdk.resources import Resource, SERVICE_NAME from opentelemetry.sdk.trace import TracerProvider @@ -39,12 +40,23 @@ def test_load_plugin(self): def test_collect_attributes(self): with trace.get_tracer_provider().get_tracer("test").start_as_current_span("test-span"): plugin = OTelPlugin() - attributes = plugin.decorate("snap_id", None) + + mock = mockito.mock() + mock.trigger_context = mock + mock.trigger_context.id = "id" + mock.location_action = mock + mock.location_action.id = "id" + mock.location_action.location = mock + mock.location_action.location.name = "test" + + attributes = plugin.decorate("snap_id", mock) self.assertIsNotNone(attributes) self.assertEqual("test-span", attributes.get("span_name")) self.assertIsNotNone(attributes.get("span_id")) self.assertIsNotNone(attributes.get("trace_id")) - self.assertEqual(plugin.current_span().proxy.attributes, {"snapshot": "snap_id"}) + self.assertEqual(plugin.current_span().proxy.events[0].name, "test") + self.assertEqual(plugin.current_span().proxy.events[0].attributes, + {'snapshot': 'snap_id', 'tracepoint': 'id', 'context': 'id'}) def test_create_span(self): plugin = OTelPlugin() From 0db4a433102ceda2e60b3320fb353e2b9af17d07 Mon Sep 17 00:00:00 2001 From: Ben Donnelly Date: Mon, 19 Feb 2024 18:44:04 +0000 Subject: [PATCH 3/3] feat(events): update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36a4964..56859f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - **[BUGFIX]**: fix(duration): snapshot duration not set [#37](https://github.com/intergral/deep/pull/37) [@Umaaz](https://github.com/Umaaz) - **[BUGFIX]**: fix(attributes): snapshot attributes not set [#38](https://github.com/intergral/deep/pull/38) [@Umaaz](https://github.com/Umaaz) - **[BUGFIX]**: fix(resource): discovered resources overwriting each other [#41](https://github.com/intergral/deep/pull/41) [@Umaaz](https://github.com/Umaaz) +- **[BUGFIX]**: feat(events): use events for snapshot in spans [#40](https://github.com/intergral/deep/pull/40) [@Umaaz](https://github.com/Umaaz) # 1.1.0 (06/02/2024)