Skip to content

Commit

Permalink
feat(EAP): Trace Item resolvers (#6732)
Browse files Browse the repository at this point in the history
### Context
In order to make room for new kinds of TraceItems (e.g. uptime monitors,
errors, logs, etc),add a layer of indirection to the RPC layer


Before:

```
RPC Flask Endpoint -> RPCEndpoint.execute() -> Snuba query pipeline
```

After:


```

                                           /-> EAP resolver -> Snuba query pipeline (or whatever else)
RPC Flask Endpoint -> RPCEndpoint.execute() -> Uptime resolver -> Snuba query pipeline (or whatever else)
                                           \-> Errors resolver -> Snuba query pipeline (or whatever else)
```

For rationale, please read [this
doc](https://www.notion.so/sentry/Where-does-RPC-Entity-specific-code-live-1238b10e4b5d806bb328d37c5f3bf522)

### How it works:

Every EAP endpoint has a `get_resolver` method based on the
`TraceItemName` passed in the request meta. A resolver has the same
inputs and outputs as the RPCEndpoint.

For each endpoint in EAP, there is a resolver class:

https://github.com/getsentry/snuba/pull/6732/files#diff-c018ef30d919d555c5e69908ce74e5f9144d613de3588a48d849f8c757b58628R22-R53

For each TraceItem we have, we implement the appropriate resolvers, this
PR moves EndpointTraceItemTable and EndpointTimeSeries implementations
for EAP spans into resolver implementations.

Resolvers are picked up automatically if they follow the directory
structure:

```
snuba/web/rpc/v1/resolvers
  |->R_eap_spans
  |->R_uptime
  |->R_logs
  |->R_etc
```

Implementing resolver classes in these directories will ❇️ just work ❇️
without needing to change endpoint code.

### Outstanding things

It's not clear *yet* what is really "common" and what is not. We will
figure this out through the course of doing this work

---------

Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
  • Loading branch information
volokluev and getsantry[bot] authored Jan 10, 2025
1 parent 77b69dc commit de96862
Show file tree
Hide file tree
Showing 11 changed files with 733 additions and 543 deletions.
42 changes: 42 additions & 0 deletions snuba/web/rpc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from google.protobuf.message import DecodeError
from google.protobuf.message import Message as ProtobufMessage
from sentry_protos.snuba.v1.error_pb2 import Error as ErrorProto
from sentry_protos.snuba.v1.request_common_pb2 import TraceItemName

from snuba import environment
from snuba.utils.metrics.backends.abstract import MetricsBackend
Expand All @@ -25,6 +26,42 @@
Tout = TypeVar("Tout", bound=ProtobufMessage)


class TraceItemDataResolver(Generic[Tin, Tout], metaclass=RegisteredClass):
def __init__(
self, timer: Timer | None = None, metrics_backend: MetricsBackend | None = None
) -> None:
self._timer = timer or Timer("endpoint_timing")
self._metrics_backend = metrics_backend or environment.metrics

@classmethod
def config_key(cls) -> str:
return f"{cls.endpoint_name()}__{cls.trace_item_name()}"

@classmethod
def endpoint_name(cls) -> str:
if cls.__name__ == "TraceItemDataResolver":
return cls.__name__
raise NotImplementedError

@classmethod
def trace_item_name(cls) -> TraceItemName.ValueType:
return TraceItemName.TRACE_ITEM_NAME_UNSPECIFIED

@classmethod
def get_from_trace_item_name(
cls, trace_item_name: TraceItemName.ValueType
) -> "Type[TraceItemDataResolver[Tin, Tout]]":
return cast(
Type["TraceItemDataResolver[Tin, Tout]"],
getattr(cls, "_registry").get_class_from_name(
f"{cls.endpoint_name()}__{trace_item_name}"
),
)

def resolve(self, in_msg: Tin) -> Tout:
raise NotImplementedError


class RPCEndpoint(Generic[Tin, Tout], metaclass=RegisteredClass):
def __init__(self, metrics_backend: MetricsBackend | None = None) -> None:
self._timer = Timer("endpoint_timing")
Expand All @@ -46,6 +83,11 @@ def version(cls) -> str:
def config_key(cls) -> str:
return f"{cls.__name__}__{cls.version()}"

def get_resolver(
self, trace_item_name: TraceItemName.ValueType
) -> TraceItemDataResolver[Tin, Tout]:
raise NotImplementedError

@property
def metrics(self) -> MetricsWrapper:
return MetricsWrapper(
Expand Down
Loading

0 comments on commit de96862

Please sign in to comment.