Agnostic Event Reporting

Micha Sherman
Fiverr Tech
Published in
4 min readOct 3, 2020
Photo by Carlos Muza on Unsplash

At Fiverr, BI events are an integral part of our day to day. Events are reported from our FE and BE services to multiple sources (reporting channels) where each channel has its own purpose and use. This article focuses on the JavaScript API but the concept can be used in any environment.

We use an awesome library developed in house called obs with dedicated utilities for each of our reporting channels —

  1. BigQuery (Mainly used by analysts).
  2. Mixpanel (Mainly used by product managers).
  3. Graphite (Mainly used by developers).

When reporting an event, we are required to build an object specifically structured according to the reporting channel API.

Using the obs api is very simple and it generally looks as follows:

When integrating into a service (or a package), it is a common practice to export the reporting functionality to a dedicated class (bigQueryReporter, mixpanelReporter, graphiteReporter).

I’ve done it over and over myself in multiple services.

Generally I have a couple of issues with the code above.

First, it can get real ugly real fast. When we have a react component that reports three events which are reported both to BigQuery and Mixpanel (in some cases to Graphite as well) it makes the code virtually unreadable.

Second, it is not scalable. When a new reporting channel is introduced (for example if we’ll start reporting events to Snowflake) we will have to go over all of our event reports (as well as their tests) and update each one manually.

Clearing The Clutter

Photo by The Creative Exchange on Unsplash

I was aiming for a way to reduce the clutter that follows each of these reports. Furthermore, I was thinking of a scalable solution that would enable us to add a new reporting channel with as few changes as possible introduced to our business logic layer.

Consider the following use case. We have a page managing collections (i.e. lists) at Fiverr. You can view your collections, filter them, create a new collection, edit or delete one.

Event Types

We start with defining our event types. The EventTypes object is shared between all reporting channels. Every event will have a unique and descriptive event key. The hierarchy of these events is important as well as we will see later.

Definition Layer

Next we have our definition layer. Here we are mapping between the event key and the event representation. If an event is not mapped in our definition layer, it would simply not be reported.

We have a definition layer for each reporting channel — notice that the BigQuery definition layer is leaner as we are not required to report some of the events to the BigQuery channel.

Construction Layer

The construction layer is essentially responsible for translating our event parameters into the required format for each reporting channel. The construction method can either return a function (Which will be called with the enrichment params) or a string (Which will be reported as is).

Similarly we’ll have an event constructor for Mixpanel.

The Graphite event constructor is very simple.

Reporting Channels

This is where we configure our reporting channels. We bind the reporting utility with our events from the definition layer and we’re almost ready to go.

This is where the magic happens.

Now we use our brand new events reporter and report the event as follows:

et voilà! A cleaner and scalable way to integrate event reporting in our business logic.

Global Event Enrichment

Notice that our events reporter has an enrich method. This can be used to globally enrich our events reporter (Usually on service initialization) with some global enrichment parameters like userId, platform etc. These parameters would be available for each event constructor.

Generic Reporting

Consider the following use case: We have a generic ModalWrapper component in React that handles our modal functionality. We would like it to report show, cancel and submit events. We can leverage our event type hierarchy.

Specific Channel Reporting

Generally, an event would not be reported if it is not a part of our definition layer. But what if it is a part of the definition layer but we still want to report it to a specific channel?

Consider the following use case: We can share a collection with a team and keep a copy to ourselves. We are required to report that the collection is shared to all channels but we want to report that a new collection is created only to BigQuery. Notice our report method has a third parameter — reportingChannels (Which equals all of our channels by default).

Wrapping Up

The concept shown in this article is merely my idea of how event reporting can be integrated better into our services and can be implemented in a various of ways. The core idea is based on these three models:

  1. Event Types
  2. Definition Layer
  3. Construction Layer

“When I am working on a problem, I never think about beauty but when I have finished, if the solution is not beautiful, I know it is wrong.”
- R. Buckminster Fuller

Fiverr is hiring, learn more about us here

--

--