Skip to content

[RUM-14242] Introduce event bus pattern for data processing#6

Merged
cdn34dd merged 2 commits into
mainfrom
carlosnogueira/RUM-14242/data-bus-implementation
Feb 10, 2026
Merged

[RUM-14242] Introduce event bus pattern for data processing#6
cdn34dd merged 2 commits into
mainfrom
carlosnogueira/RUM-14242/data-bus-implementation

Conversation

@cdn34dd

@cdn34dd cdn34dd commented Feb 4, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Create an event management system to handle the various types of events required by the SDK where all the main event handlers are decoupled from each other and self select which events to handle.

Communication happens through a central hub that acts as dispatch point.

Changes

Adds EventManager class and defines the required types and constants necessary for its use.

Test instructions

In order to use this system, we must first instantiate the EventManager and the required handler classes like so:

const eventManager = new EventManager();
const handler: EventHandler<Event> = {
      canHandle: ...,
      handle: ...,
};
eventManager.registerHandler(handler);

const event: Event = {
      track: EventTrack.TRACE, 
      source: EventSource.MAIN,
      status: EventStatus.RAW,
      data,
}
eventManager.notify(event);

Checklist

  • Tested locally (playground)
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.

@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Feb 4, 2026

Copy link
Copy Markdown

⚠️ Code Quality    ✅ Code Vulnerabilities    ✅ Library Vulnerabilities

Fix all issues with Cursor

⚠️ Warnings

🛠️ 4 Code quality issues detected

Medium: typescript-best-practices/no-console (Fix with Cursor) Avoid leaving console debug statements View rule
src/transport/http.ts:15
Low: typescript-code-style/no-new (Fix with Cursor) Avoid new operators outside of assignments or comparisons View rule
src/index.ts:25
Low: typescript-code-style/no-new (Fix with Cursor) Avoid new operators outside of assignments or comparisons View rule
src/index.ts:24
Low: typescript-code-style/no-new (Fix with Cursor) Avoid new operators outside of assignments or comparisons View rule
src/index.ts:23
View all

ℹ️ Info

🛡️ No new code vulnerabilities
📚 No new vulnerable libraries detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 042ef39 | Docs | Datadog PR Page | Was this helpful? Give us feedback!

Comment thread src/utils/id.ts Outdated
Comment thread src/event/handler/TransportHandler.ts Outdated
Comment thread src/utils/id.ts Outdated
Comment thread src/event/processor/TraceProcessor.ts Outdated
Comment thread src/event/handler/AssemblyHandler.ts Outdated
Comment thread src/utils/id.ts Outdated
Comment thread src/event/handler/AssemblyHandler.ts Outdated
Comment thread src/event/types.ts Outdated
Comment thread src/utils/id.ts Outdated
Comment thread src/event/handler/AssemblyHandler.ts Outdated
@bcaudan

bcaudan commented Feb 5, 2026

Copy link
Copy Markdown
Collaborator

Early review:

scope:

I think we could limit this one to EventManager introduction only. we could deal with assembly, trace processing, ... in subsequent PRs.
We could have the createDummyViewEvent notify event and sendEvent handle them for now.

API:

  • register pattern:

💭 I am expecting some classes to registerHandler and notify, I wonder if may not be more convenient to pass the EventManager as a dependency and let the class register its handler rather than implement the handler interface.

const eventManager = new EventManager();

const assembly = new Assembly(hooks, eventManager);


class Assembly {
  constructor(...) {
     this.eventManager.registerHandler({
         canHandle: (event: Event) => event.status === RAW,
         process: this.processRawEvent
      })
  }
}

it could also allow one class to register multiple handlers which could provide some flexibility.

  • handle VS process:

Any intent with differentiating handle and process?

  • Event:

I would like to introduce some lifecycle events at some point, like session expired / session renew. Do we think we should use the same event manager or split lifecycle and collected events?

@cdn34dd cdn34dd force-pushed the carlosnogueira/RUM-14242/data-bus-implementation branch from 2c40382 to aa8b185 Compare February 5, 2026 15:16
@cdn34dd cdn34dd marked this pull request as ready for review February 5, 2026 15:59
@cdn34dd cdn34dd requested a review from bcaudan as a code owner February 5, 2026 15:59

@bcaudan bcaudan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using Event manager with CreateDummyEvent and sendEvent to have a first integration with it?

Comment thread src/event/constants.ts
Comment on lines +11 to +15
export const EventTrack = {
LOG: 'logs',
RUM: 'rum',
TRACE: 'spans',
} as const;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 suggestion: ‏what about using endpoint naming for consistency?

Suggested change
export const EventTrack = {
LOG: 'logs',
RUM: 'rum',
TRACE: 'spans',
} as const;
export const EventTrack = {
LOGS: 'logs',
RUM: 'rum',
SPANS: 'spans',
} as const;

Comment thread src/event/constants.ts Outdated
Comment on lines +17 to +21
export const EventType = {
LOG: 'log',
RUM: 'rum',
TRACE: 'span',
} as const;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 suggestion: ‏does not seem to be used for now

Suggested change
export const EventType = {
LOG: 'log',
RUM: 'rum',
TRACE: 'span',
} as const;

Comment thread src/event/types.ts Outdated
Comment on lines +3 to +14
export interface CollectableEvent {
kind: 'collectable';
track: (typeof EventTrack)[keyof typeof EventTrack];
source: (typeof EventSource)[keyof typeof EventSource];
status: (typeof EventStatus)[keyof typeof EventStatus];
data: unknown;
}

export interface LifetimeEvent {
kind: 'lifetime';
data: unknown;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 suggestion: ‏instead of kind and status, what about only using kind? not sure that Raw and Server event need to share the same properties

RawEvent {
  kind: 'raw'
  source
  data
}

ServerEvent {
  kind: 'server'
  track
  data
}

LifetimeEvent {
  kind: 'lifetime'
  data
}

Comment thread src/event/types.ts Outdated
Comment on lines +11 to +12
export interface LifetimeEvent {
kind: 'lifetime';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 suggestion: ‏In browser sdk, we are using the LifeCycle naming which seems more appropriate to me than Lifetime for events like "end user activity", session renew", ...

Comment thread src/event/EventManager.ts Outdated
continue;
}

handler.handle(event, (e) => this.notify(e));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 suggestion: it is not obvious to me that we already need to introduce:

  • handling of multiple events though notify
  • calling notify from the handler

I think we could keep things simple at first, see how we end up using it and add more complexity along the way‏

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think having a bit more flexibility in the implementation at this point is an issue. As for the notify from the handler, that goes allow what we discussed previously on how data should flow, I could have misunderstood something, but then we should resync to make sure were aligned on what we're aiming for.

@cdn34dd cdn34dd force-pushed the carlosnogueira/RUM-14242/data-bus-implementation branch from aa8b185 to 2a17405 Compare February 6, 2026 13:01
@cdn34dd cdn34dd requested a review from bcaudan February 6, 2026 13:02
Comment thread src/transport/http.ts Outdated
- Add Assembly to transform RawEvents into ServerEvents
- Convert Transport to class that listens for ServerEvents
- Convert DummyMainView to class that emits RawEvents
- Connect components via EventManager
@cdn34dd cdn34dd force-pushed the carlosnogueira/RUM-14242/data-bus-implementation branch from 2a17405 to 042ef39 Compare February 9, 2026 18:47
Comment thread src/index.ts
Comment thread src/index.ts
Comment thread src/index.ts
Comment thread src/transport/http.ts

@bcaudan bcaudan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@cdn34dd cdn34dd merged commit 6f17833 into main Feb 10, 2026
10 checks passed
@cdn34dd cdn34dd deleted the carlosnogueira/RUM-14242/data-bus-implementation branch February 10, 2026 09:30
@bcaudan bcaudan mentioned this pull request Mar 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants