# Subscribing to Live Events

Data flows through Live as events. Events can be detected or generated by plugins to represent some real condition. Once the data flows, the developer can mark the event to skip the real-time engine or the storage (as described in [event flow modifiers](https://platform.intelie.com/pipes-queries/event-flow-modifiers)). But, in general, the data will flow first to the real-time engine and then will be stored at Intelie Storage Providers as historical data.

From the query point of view, the Pipes expression can manifest the interest by both real-time and historical data. The historical part of the query will be fetched first, and finally, the real-time part of the query will monitor and deliver data to the developer code.

### Pipes query execution and data delivery

For short, the plugin backend code can take the responsibility to perform the Pipes query. This way typically is preferred since it allows the developer to encapsulate the query expression at some REST endpoint. For example:

```java
import net.intelie.live.*;

@UseProxy
@Path("/")
public class MyEventService {
    @NotNull
    private final Live live;

    public MyEventService(@NotNull Live live) {
        this.live = live;
    }

    @POST
    @Path("/metrics")
    @NeedsNoAuthority
    @Produces(MediaType.APPLICATION_JSON)
    public List<QueryResponse> followLastDayMetrics() throws Exception {
        Query query = new Query("__metrics")
                .span("last 1 day")
                .follow(true)
                .description("Retrieves the history of 1 day ago and monitors system metrics in real time");
        BayeuxQuery bayeuxQuery = new BayeuxQuery();
        bayeuxQuery.addQuery(query);
        return this.live.queries().registerBayeuxQuery(bayeuxQuery);
    }
}
```

The `Query` object can be encapsulated by `BayeuxQuery` before being registered at Live runtime. The [bayeux channel](https://docs.cometd.org/current3/reference/#_bayeux) semantics will produce an identifier for the **data channel** where the data will flow until the frontend. The channel identifier will be encapsulated in a `QueryResponse` object per each query.

As seen before in [Web Services](https://platform.intelie.com/developers/backend-api/web-services) section, the REST endpoint can be registered by plugin backend as following:

```java
live.web().addService("/events", new MyEventService(live))
```

In summary, in this section we prepared a **query** to run once the frontend code connects into the **data channel** to listen by events. It is prepared to deliver both **historical and real-time data** about the `__metrics` event type including the `last 1 day` of data and the `follow(true)` means the runtime will deliver any real-time data from now on as soon the historical part of the dataset be read from persistent storage (if any).

### Event subscription for web applications <a href="#user-content-event-subscription-for-web-applications" id="user-content-event-subscription-for-web-applications"></a>

Live delivers a frontend API called **Live Subscription Service**. It allows the developer to request the data channel (typically built upon **websockets** if your browser supports). Then, the plugin frontend code will be able to receive events produced by Pipes queries encapsulated by REST endpoints, as demonstrated in the previous section.

```javascript
response = await fetch("/services/plugin-tutorial/events/metrics", 
                       { method: "POST", body: "" })
channels = await response.json()
console.log(channels[0])
// {channel: '/data/7af9ff5eeefd46a2bbfec4768d11c2b3'}
```

The data channel identified by `/data/7af9ff5eeefd46a2bbfec4768d11c2b3` represents a CometD channel and typically the data will be transported by WebSockets if the HTTP server/proxies are properly configured.

However, Live enables a high-level **subscription** abstraction by the usage of the **Live Subscription Service** API and simplifies the code the plugin developer needs to write.

```typescript
import Subscriber from 'live/services/subscription'
const subscription = new Subscriber({
    url: `services/plugin-tutorial/events/metrics`
})
subscription.flush()
```

The **Subscription** object delivers the following API:

<table><thead><tr><th width="197.21971252566738">Method</th><th width="246.52491893729086">Parameter</th><th>Description</th></tr></thead><tbody><tr><td><strong>delegate</strong>(fn)</td><td><strong>fn</strong> (function): callback to handle the events</td><td>Handles all types of events sent by the Live platform</td></tr><tr><td><strong>on</strong>(type, fn)</td><td><strong>type</strong> (string): inform the event type to be used in the filter<br><strong>fn</strong> (function): callback to handle the event itself</td><td>Handles a single type of events, see <a href="web-application/dashboard-and-widgets/live-event-types">Live Event Types</a></td></tr><tr><td><strong>request</strong>(params, rIndex)</td><td><strong>params:</strong> (array) The request parameters<br><strong>rIndex:</strong> (number) The request identifier</td><td>Create a new Request for the back-end querying code</td></tr><tr><td><strong>flush</strong>(index)</td><td><strong>index:</strong> (string) The request identifier</td><td>Marks the user code as ready to listen by events</td></tr><tr><td><strong>close</strong>(index)</td><td><strong>index:</strong> (string) The request identifier</td><td>Closes the underlay cometd channel</td></tr></tbody></table>

A very simple web application code to identify only data events (as described at [Live Event Types](https://platform.intelie.com/developers/web-application/dashboard-and-widgets/live-event-types)) looks like the following:

```typescript
import Subscriber from 'live/services/subscription'

const subscription = new Subscriber({
    url: `services/plugin-tutorial/events/metrics`
})

export type EventMetrics = {
    stimestamp: number
    gtimestamp: number
    timestamp: number
    gperiod: number
    metric: string
    value: Record<string, string | {}>
    __src: 'core'
    __type: '__metrics'
}

subscription.on('event', (events :EventMetrics[]) => {   
    if(events[0].metric === "system") {
        console.log(events[0].timestamp) 
    } 

    if(events[0].metric === "disk") {
        // do something else
    } 
})

subscription.flush()
```

At `subscription.on('event', (events :EventMetrics[]) => {...}` we provided a callback to handle the data itself (using `event` as the event type). This callback receives as the first parameter a batch of data. At this point, the example above only prints out some information at `console.log`. After that, we use the `flush` method, which dispatches to the service the plugin code is, finally, ready to receive the events.

In summary, in this section, we create a subscriber by using the Live Subscription Service API, we request the data channel from the backend code REST endpoint `/services/plugin-tutorial/events/metrics` and Live runtime starts the query once the frontend code flushes the data channel.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://platform.intelie.com/developers/subscribing-to-live-events.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
