Actors

 

This document describes how Semaphore works through the perspective of the system actors and the messages exchanged by them.

TODO Short description about infrastructure (i.e. actix-web, actix, tokio, futures), note that we are using the old style Future trait, and actix 0.7.x .

controller.rs

events.rs

The events.rs module contains functionality related to the processing of events. Raw events being sent to the system are first processed, and then sent to Sentry for saving.

The module contains to actors:

EventManager

The EventManager is an actor running in the main system arbiter. The system arbiter is a asynchronous arbiter created when the Semaphore starts. The upshot of this is that all processing done by the event manager should be extremly quick. It is ok to wait on I/O but no significant processing may be done in the EventManager.

Once the EventManager had obtained the project state and had decided that the event should be processed the EventManager passes the event to the EventProcessor actors.

 

TODO document all handlers

EventProcessor

The EventProcessor is an actor running in a SyncArbiter. There are multiple instances of the EventProcessor actor (roughly 1 per thread) (TODO RaduW check that I'm not talking nonsense here.).

The EventProcessor does the heavy lifting of event processing. The event processing does only synchronous work ( all the IO is handleed in the EventManager and all the needed state is passed to the EventProcessor)

Since all the work done by the event processor is the synchronous processing of an event there is only one type of message accepted by the EventProcessor actor:

ProcessEvent

The ProcessEvent handler prepares the event for ingestion. It normalizes the event, symbolicates its stack-trace and strips sensitive information (PPI stripping).

TODO finish here

keys.rs

outcome.rs

server.rs

store.rs

upstream.rs

project.rs

The project.rs module contains functionality related to the project state. Sentry events belong to projects and projects belong to organizations (Semaphore doesn't care at the moment about organizations).

Projects serve to group the events (so that each Sentry customer can only see and deal with his/hers own events) and prescribe how messages are to be processed ( what should be filtered, which data inside the event should be anonymised (i.e PPI stripping), etc).

All activities around obtaining, caching and refreshing the project state is handled in this module.

The module contains two actors:

From a high level perspective one obtains a Project from the ProjectCache and then uses the Project in order to get 'project specific' information.

Project

The Project actor is responsible with decisions about how an event for a particular project should be handled. The project runs in an async arbiter ( I think it actully runs in the SystemArbiter TODO check ir that is true, or if it runs in another async arbiter).

The system constructs an actor for each project used.

The Project actor runs in an async context.

The Project actor responds to the following message types:

GetProjectId

The GetProjectId handler returns the project_id (trivial functionality).

GetProjectState

The handler retuns the ProjectState, either directly (if it has a recent cached version) or by asking the ProjectCache to fetch it on its behalf.

Pseudo Code

GetEventAction

The handler answers the question: How should an event be handled?

An event may be handled in one of three ways specified by the EventAction enum.

Pseudo Code

RateLimit

The handler is used to update chached versions of project RateLimits.

Pseudo Code

ProjectCache

The ProjectCache actor is responsible for providing Project actors.

The ProjectCache runs in an asynchronous context. There is only one instance of the ProjectCache in the system.

The project runs in an async arbiter ( I think it actully runs in the SystemArbiter TODO check ir that is true, or if it runs in another async arbiter).

The ProjectCache actor responds to the following messages:

GetProject

Retuns a Project actor for the required project.

Pseudo Code

FetchProjectState

Registers the intention of a project to retrieve the project state.

The FetchProjectState functionality logicaly belongs to the Project actor but it is handled by the ProjectCache in order to batch requests for the project state from multiple Project actors.

A Project registers its desire to obtain its project state with the ProjectCache by sending the FetchProjectState and the ProjectCache batches all requests during a batching period and emits one request to the upstream (another semaphore or the Sentry server) for all required project states.

The handler checks if there is already a scheduled time for fetching project states and, if not, it schedules a delayed function that will do the actual fetching for all projects that registered their desire for getting the project state (see function: ProjectCache::fetch_states).

TODO: Add pseudo code

 

UpdateLocalStates

Updates project states for project states comming from a local file configuration.(TODO check if that is correct RaduW. 10.Oct.2019)

This message is emmited periodically by a thread that loops and periodically checks the local file system for configuration changes (see function: poll_local_states ).

 

 

Store endpoint request processing

GetEventAction
GetProject
QueueEvent
FetchProjectState
GetProjectState
GetEventAction
RateLimit
HandleEvent
GetProjectId
ProcessEvent
StoreEvent
SendRequest
UpdateLocalStates
/api/#PRJ#/store
store.storeEvent
UpstreamRelay
EventManager
Project
EventProcessor
(sync)
ProjectCache
StoreForwarder

Event ingestion

Created with Raphaël 2.2.0Event Ingestionstore_eventstore_eventProjectCacheProjectCacheProjectProjectEventManagerEventManagerEventProcessorEventProcessorGetProjectProjectGetEventActionEventActionQueueEventevent_idHandleEventGetProjectIdProjectIdGetEventActionEventActionGetProjectStateProjectStateProcessEventProcessEventResponse

 

Server bootstrap

Created with Raphaël 2.2.0main.mainmain.maincli.executecli.executeserver.lib.runserver.lib.runControllerControllerserver.actors.Serverserver.actors.Serverserver.serviceserver.serviceServiceStateServiceStatemake_apprunstartstartstart

ServiceState start

Created with Raphaël 2.2.0ServiceStateServiceStateUpstreamRelayUpstreamRelayEventManagerEventManagerKeyCacheKeyCacheProjectCacheProjectCachestart(config)start(config, upstream_realy)start(config,upstream_relay)start(config, upstream_relay)