Skip to content

Commit 4142b33

Browse files
gustavocidornelaswhoseoyster
authored andcommitted
Introduce Openlayer tracer
1 parent 23bb675 commit 4142b33

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

openlayer/tracing/__init__.py

Whitespace-only changes.

openlayer/tracing/steps.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""Module with the different Step classes that can be used in a trace."""
2+
3+
import time
4+
from typing import Any, Dict, Optional
5+
6+
7+
class Step:
8+
def __init__(
9+
self,
10+
name: str,
11+
inputs: Optional[Any] = None,
12+
output: Optional[Any] = None,
13+
metadata: Dict[str, any] = {},
14+
) -> None:
15+
self.name = name
16+
self.inputs = inputs
17+
self.output = output
18+
self.metadata = metadata
19+
20+
self.step_type = "user_call"
21+
self.start_time = time.time()
22+
self.end_time = None
23+
self.ground_truth = None
24+
self.latency = None
25+
26+
self.steps = []
27+
28+
def add_nested_step(self, nested_step: "Step") -> None:
29+
"""Adds a nested step to the current step."""
30+
self.steps.append(nested_step)
31+
32+
def update_data(self, **kwargs: Any) -> None:
33+
"""Updates the step data."""
34+
for key, value in kwargs.items():
35+
if hasattr(self, key):
36+
setattr(self, key, value)
37+
38+
def to_dict(self) -> Dict[str, Any]:
39+
"""Dictionary representation of the Step."""
40+
return {
41+
"name": self.name,
42+
"type": self.step_type,
43+
"inputs": self.inputs,
44+
"output": self.output,
45+
"groundTruth": self.ground_truth,
46+
"metadata": self.metadata,
47+
"steps": [nested_step.to_dict() for nested_step in self.steps],
48+
"latency": self.latency,
49+
"startTime": self.start_time,
50+
"endTime": self.end_time,
51+
}

openlayer/tracing/tracer.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""Module with the logic to create and manage traces and steps."""
2+
3+
import inspect
4+
from typing import Any, Dict, Optional, Generator
5+
from contextlib import contextmanager
6+
import contextvars
7+
from functools import wraps
8+
9+
from . import steps
10+
from . import traces
11+
import time
12+
13+
_current_step = contextvars.ContextVar("current_step")
14+
_current_trace = contextvars.ContextVar("current_trace")
15+
16+
17+
@contextmanager
18+
def create_step(
19+
name: str,
20+
inputs: Optional[Any] = None,
21+
output: Optional[Any] = None,
22+
metadata: Dict[str, any] = {},
23+
) -> Generator[steps.Step, None, None]:
24+
"""Starts a trace and yields a Step object."""
25+
new_step = steps.Step(name=name, inputs=inputs, output=output, metadata=metadata)
26+
27+
parent_step = _current_step.get(None)
28+
is_root_step = parent_step is None
29+
30+
if parent_step is None:
31+
print("Starting a new trace...")
32+
current_trace = traces.Trace()
33+
_current_trace.set(current_trace) # Set the current trace in context
34+
current_trace.add_step(new_step)
35+
else:
36+
print(f"Adding step {name} to parent step {parent_step.name}")
37+
current_trace = _current_trace.get()
38+
parent_step.add_nested_step(new_step)
39+
40+
token = _current_step.set(new_step)
41+
42+
try:
43+
yield new_step
44+
finally:
45+
_current_step.reset(token)
46+
if is_root_step:
47+
print("Ending the trace...")
48+
print("-" * 80)
49+
print(current_trace.to_dict())
50+
print("-" * 80)
51+
else:
52+
# TODO: stream to Openlayer
53+
print(f"Ending step {name}")
54+
55+
56+
def trace(*step_args, **step_kwargs):
57+
def decorator(func):
58+
func_signature = inspect.signature(func)
59+
60+
@wraps(func)
61+
def wrapper(*func_args, **func_kwargs):
62+
if step_kwargs.get("name") is None:
63+
step_kwargs["name"] = func.__name__
64+
with create_step(*step_args, **step_kwargs) as step:
65+
output = func(*func_args, **func_kwargs)
66+
end_time = time.time()
67+
latency = (end_time - step.start_time) * 1000 # in ms
68+
inputs = func_signature.bind(*func_args, **func_kwargs).arguments
69+
70+
step.update_data(
71+
inputs=inputs,
72+
output=output,
73+
end_time=end_time,
74+
latency=latency,
75+
)
76+
return output
77+
78+
return wrapper
79+
80+
return decorator

openlayer/tracing/traces.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Module with the Trace class."""
2+
3+
from typing import Any, Dict
4+
5+
from .steps import Step
6+
7+
8+
class Trace:
9+
def __init__(self):
10+
self.steps = []
11+
self.current_step = None
12+
13+
def add_step(self, step: Step) -> None:
14+
"""Adds a step to the trace."""
15+
self.steps.append(step)
16+
17+
def to_dict(self) -> Dict[str, Any]:
18+
"""Dictionary representation of the Trace."""
19+
return {"rows": [step.to_dict() for step in self.steps]}

0 commit comments

Comments
 (0)