Skip to main content

Event Inheritance

FDL supports event inheritance so you can build hierarchies of events. For example, let's say that we are running a company that makes both sales and subscription revenue. You can make a "revenue" event and have both types inherit from that event:

event Revenue
{
value : Float!
}

session {
event Purchase {
import Revenue
productid : ID!
}
event Subscription {
import Revenue
userid : ID!
}
}

The Purchase and Subscription events happen at the session level, and each have two fields. Productid and value for Purchase, and userid and value for Subscription.

The import keyword will copy the given event's fields into the new definition. Field names within an event must be unique, so you need to be thoughtful with your names. If the imported event has a field named the same as the event doing the importing, you'll get a name conflict and compiler error.

Causal also uses the import keyword in a couple of other useful ways. When specifying a metric, you can refer to base events like Revenue and have all the derived events automatically count towards that metric. Causal will also create a view for the Revenue metric that will include a union of all instances of the derived metric. That makes it easy to define reports on total revenue, and have them be kept automatically up to date as new revenue streams are added.

Syntactic Sugar

You can also import an event directly into a feature or session:

event Revenue
{
value : Float!
}

feature A {
import Revenue
}

feature B {
event Revenue {
import Revenue
}
}

The two features here are exactly equivalent.

Signaling Abstract Events

We call the Revenue event in the previous two examples an abstract event. Abstract events never appear in the data warehouse and cannot be directly signalled. They can only be imported into events that appear on a feature or session.

However, Causal does allow you to signal abstract events using the signalAbstract methods in the API. For the above example, the compiler will generate a signalAbstractRevenue method. Calling this method with an impression id will find the correct importing feature using that impression id and signal the event on that feature. One caveat is that the signalAbstract will fail if the importing event has required fields that are not defined in the abstract event.

So, using signalAbstract with the Purchase or Subscription events, above, will fail with a missing required argument error.

You can also signal abstract events on sessions. Say you define another revenue event in your session:

session {
event Revenue {
import Revenue
}
}

If Causal doesn't have an impression with the same ID that was passed into the signalAbstractRevenue method, it will add the event to the session.

Note that if there are 2 events that import Revenue in the session, Causal has no way of determining which event type should get signalled. In that case, you will get an error.

session {
"""
You can't signal a Purchase event through signalAbstractRevenue.
Causal doesn't know whether it would be a Purchase or a Subscription
"""
event Purchase {
import Revenue
}
event Subscription {
import Revenue
}
}