Realtime Client Library API

Metachannels

Overview

Metachannels are a namespace of channels beginning with the [meta] qualifier. This separates them from regular channels. An example of a metachannel is [meta]channel.lifecycle or [meta]clientEvents:connections.

There are a number of metachannels available:

[meta]log
This metachannel broadcasts error messages that you would not otherwise have any way of receiving (with the exception of errors delivering push notifications, see below). For example, if Ably receives an error response when delivering a reactor webhook to your endpoint, Ably sends a message on the log metachannel with information about the error. Errors where the client can be directly notified are not sent on the log metachannel. For example, if a client attempts to publish a message but exceeds a channel rate limit, the client can be notified by an error callback passed to publish.
[meta]log:push
This metachannel is similar to [meta]log, but only for errors that happen during delivery of push notifications.
[meta]channel.lifecycle
This metachannel publishes messages about channel lifecycle.
[meta]connection.lifecycle
This metachannel publishes messages about the lifecycle of realtime connections.
[meta]clientEvents:connections
This metachannel publishes metadata for a sample of connection events.
[meta]clientEvents:apiRequests
This metachannel publishes metadata for a sample of API request events.

Permissions

To subscribe to a metachannel you require an Ably key or token that has suitable capabilities. The resource name or names in the capability must include the [meta] qualifier explicitly.

If you are using an API key, you can set the key’s capabilities in the Ably dashboard. If you are using tokens, you specify capabilities within the token.

The following shows an example of a capability allowing subscription to all metachannels:

{"[meta]*":["subscribe"]}

The above capability allows for the token to subscribe to any meta channel. The wildcard * indicates anything can follow the [meta] claim, so an example of a valid channel would be [meta]log. However, this capability does not allow for any other actions to be performed on the metachannels, nor does it allow the token to do anything with any non-metachannels.

The following shows an example of a capability allowing all permissible actions on all metachannels and all regular channels:

{
  "[meta]*":["*"],
  "*":["*"]
}

The above permission provides two capabilities; the ability to perform any action on any metachannel, such as [meta]log with "[meta]*":["*"], and the ability to perform any action on any channel such as another:channel with "*":["*"].

However, you are never able to publish or be present in a metachannel, so this permission results in an effective permission that excludes publish and presence capabilities in [meta] channels. This is due to the intersecting capabilities.

If [meta] is not specified in the permissions, you will be unable to access the metachannels. An example of this is the following:

{
  "*":["*"]
}

Although the above provides all capabilities in all regular channels, without a [meta] permission being explicitly specified, you will be unable to perform any actions on a metachannel.

To provide all capabilities on all metachannel and channels you can use the following:

{
  "[*]*":["*"]
}

These wildcard rules are summarized here:

  • * as a resource name matches all regular channels, but not metachannels.
  • To match both regular channels and metachannels you can use [*]*.
  • To match all metachannels and no regular channels you can use [meta]*.
  • To match just a single metachannel you can use, for example, [meta]channel.lifecycle.

For further information on capabilities, please refer to the following resources:

Lifecycle Events

The following events are published as messages on the [meta]channel.lifecycle channel. In all cases, the data member of the message is a ChannelDetails instance.

channel.opened
indicates that the channel has been activated globally; that is, it has become active in at least one region, having previously been inactive. The embedded ChannelDetails.status includes occupancy globally.
channel.closed
indicates that the channel has been deactivated globally.
channel.region.active
indicates that the channel has been activated in a specific region. The included ChannelDetails.status includes occupancy in that region.
channel.region.inactive
indicates that the channel has been deactivated in a specific region. The included ChannelDetails.status includes occupancy in that region.
channel.occupancy
indicates a change in global occupancy on the channel. Not all occupancy changes are sent; there is a minimum interval on a per-channel basis, so if the occupancy is changing continuously, then only periodic snapshots of occupancy are sent. Further roll-up of events may occur depending on the capacity of the lifecycle channel. Any occupancy changes in which any of the occupancy categories changes from 0 to a non-zero count, or vice versa, are always included. This feature is only available on a per-app basis to Ably’s enterprise customers. It is recommended that you use inband channel occupancy events instead.

The following code snippet shows how to subscribe to channel.closed channel lifecycle events:

const channel = ably.channels.get('[meta]channel.lifecycle');

channel.subscribe('channel.closed', (msg) => {
    console.log('lifecycle meta channel (closed): ', msg.data);
});

The following code snippet shows how to subscribe to all channel lifecycle events:

const channel = ably.channels.get('[meta]channel.lifecycle');

channel.subscribe((msg) => {
    console.log('Event type: ' + msg.name, msg.data);
});

channel.occupancy lifecycle events

When channel.occupancy events are enabled for your app, you can subscribe to channel occupancy events by attaching to the channel [meta]channel.lifecycle using a realtime connection. However, please bear in mind that realtime connections and channels have rate limits based on your package size. If the rate of channel lifecycle events exceeds this, a realtime connection is not going to be a reliable way to consume these events as you may get disconnected or lifecycle events may be discarded.

While the channel lifecycle metachannel can provide occupancy metrics, there may be a performance impact, since this involves funnelling occupancy updates for every channel in the app to a single metachannel. This approach does not scale well as the number of channels grows, and so has limited use cases. There are two recommended alternatives:

  • Inband channel occupancy events – for use cases where the entity that needs to determine occupancy is attached to the channel.
  • Occupancy rules – for use cases where the entity needing to determine channel occupancy is not connected to the channel. A channel occupancy reactor rule allows you to obtain occupancy updates from a set of channels in a centralized way, that doesn’t involve attaching to all of them. Please get in touch for further information.

Sampled connection and request events

Sampled connection and request events can be used to monitor the usage of Ably services. Events are published to metachannels that contain metadata for a sample of connections and API requests. These events can be used to compile statistics on app usage, enabling you to perform arbitrary data processing and aggregation related to client population and client activity.

Note that this is an Enterprise-only feature and must be enabled for each app you would like to sample. Please contact us to enable this functionality.

Events are published on the metachannels [meta]clientEvents:connections and [meta]clientEvents:apiRequests.

The following code snippet shows how to subscribe to connection.opened events:

const channel = ably.channels.get('[meta]clientEvents:connections');

channel.subscribe('connection.opened', (msg) => {
    console.log('connection opened: ', msg.data);
});

The following code snippet shows how to subscribe to all sampled API request events:

const channel = ably.channels.get('[meta]clientEvents:apiRequests');

// To subscribe to all event types
channel.subscribe((msg) => {
    console.log('Event type: ' + msg.name, msg.data);
});

Sample rate

The rate of sampling dictates the number of events published to the metachannels. For example, a rate of 0.1% for connections would publish an average of 1 message in every 1000. The sample rate can be configured independently for connections and API requests within the same app.

Connections

Sampled connection events for an app are published to the channel [meta]clientEvents:connections. Connection events can be used to compile statistics relating to client population.

The connection event types are:

connection.opened
The connection was successfully made by the client to Ably.
connection.closed
The connection was explicitly closed by the client.
connection.refused
The connection was rejected for an expected reason, such as invalid credentials or a malformed request.
connection.failed
The connection was rejected for an unexpected reason, such as a network failure.

Events contain a subset of the following metadata in the data field:

host
The host the connection was made to.
Type: String
requestId
The unique ID of the request that Ably can use to correlate a connection event with internal logs, if necessary.
Type: String
region
The region the connection was made from.
Type: String
headers
The headers sent with the connection.
Type: JSON Object
query
The parsed query string of the connection request, excluding authentication parameters. It contains connection information such as the client library version and any custom transport parameters.
Type: JSON Object
connectionId
The unique ID of the connection.
Type: String
clientId
The ID of the client that attempted the connection.
Type: String
channels
A list of channels included in the request. This is only relevant where channels are supported as part of the connection request, such as with SSE.
Type: Array
duration
The duration the connection was open for.
Type: Integer
error
The details of any error encountered whilst making the connection request. It includes an error message, error code and HTTP status code.
Type: JSON Object

An example of a connection.closed event is:

{
  "host": "realtime.ably.io",
  "requestId": "fbbcb0ab-fa56-47c4-bbd4-fccc22a271b8",
  "region": "us-east-1", 
  "headers": {
    "host": "realtime.ably.io",
    ...
  },
  "query": {
    "format": "json",
    "heartbeats": "true",
    "v": "1.2",
    "lib": "js-web-1.2.9"
  },
  "connectionId": "54321",
  "clientId": "12345",
  "duration": 61151
}

API requests

Sampled API request events for an app are published to the channel [meta]clientEvents:apiRequests. API request events can be used to compile statistics relating to client activity.

The request event types are:

request.succeeded
The request was successful.
request.refused
The request was rejected for an expected reason, such as a malformed request or insufficient privileges.
request.failed
The request was rejected for an unexpected reason, such as a network failure.

Events contain a subset of the following metadata in the data field:

host
The host the request was made to.
Type: String
requestId
The unique ID of the request that Ably can use to correlate a request event with internal logs, if necessary.
Type: String
region
The region the request was made in.
Type: String
headers
The headers sent with the request.
Type: JSON Object
query
The details of the parsed request query, including information such as the request format.
Type: JSON Object
path
The path of the endpoint called in the request, for example /channels/{channel-name}/messages.
Type: String
channels
A list of channels the request was made against.
Type: Array
error
The details of any error encountered whilst making the request. It includes an error message, error code and HTTP status code.
Type: JSON Object

An example of a request.succeeded event is:

{
  "host": "rest.ably.io",
  "requestId": "fbbcb0ab-fa56-47c4-bbd4-fccc22a271c9",
  "region": "us-east-2",
  "headers": {
    "host": "rest.ably.io",
    ...
  },
  "query": {
    "format": "json"
  },
  "path": "/channels/example-channel/messages",
  "channels": [
    "my-test-channel"
  ]
}

Reactor rules

You can associate Reactor rules with metachannels in the same way as for regular channels. Reactor rules are often used with metachannels so that events can be sent to serverless endpoints, queues, and streams. To configure a reactor rule with a metachannel, use the Message source and use a channelFilter of, for example, ^\[meta\]log. Normally the channelFilter regex will only match normal, non-meta channels; however, a regex of the form ^\[qualifier\]pattern is special-cased to match channels with that qualifier. The pattern is a regex as normal.

Channel lifecycle outbound webhooks

When creating an outbound webhook Reactor rule it is possible to select Channel Lifecycle as the source instead of selecting Message and filtering on the [meta]channel.lifecycle channel. The advantage of this is that events will be simpler to parse as they will not be wrapped in Message objects.


API reference
Documentation

Need help?

If you need any help with your implementation or if you have encountered any problems, do get in touch. You can also quickly find answers from our knowledge base, and blog.