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 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.
- [meta]stats:minute
- This metachannel publishes app statistics.
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:
{<a href="[">[meta]*</a>"subscribe"]}
CopyCopied!
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:
{
<a href="[">[meta]*</a>"*"],
"*":["*"]
}
CopyCopied!
The above permission provides two capabilities; the ability to perform any action on any metachannel, such as [meta]log
with <a href="[">[meta]*</a>"*"]
, 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:
{
"*":["*"]
}
CopyCopied!
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:
{
"[*]*":["*"]
}
CopyCopied!
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.
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);
});
CopyCopied!
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);
});
CopyCopied!
App statistics
The Ably system collects usage statistics on a per-app basis and exposes them via the REST API as described in the statistics documentation.
These app statistics are also published every minute to a metachannel named [meta]stats:minute
, with each message being formatted according to the app-stats JSON schema.
You can subscribe to the stats metachannel with the following example code:
const channel = ably.channels.get("[meta]stats:minute");
channel.subscribe("update", event => {
console.log(JSON.stringify(event, undefined, 2));
});
CopyCopied!
This code subscribes to update
events on the stats metachannel. The update
events are published every minute and contain the statistics for only the past minute. No other events are supported in this metachannel at this time.
An example of the event received is shown here:
{
"name": "update",
"id": "trVvT-KeEw:0:0",
"encoding": null,
"data": {
"intervalId": "2021-10-07:16:23",
"unit": "minute",
"schema": "https://schemas.ably.com/json/app-stats-0.0.1.json",
"entries": {
"connections.all.peak": 1,
"connections.all.min": 1,
"connections.all.mean": 0.2,
"connections.all.opened": 2,
"apiRequests.all.succeeded": 2,
"apiRequests.tokenRequests.succeeded": 2
}
}
}
CopyCopied!
Where:
- name
- The
update
event. No other events are currently supported. - id
- The unique ID of the event.
- encoding
- Encoding of the event data.
- intervalId
- This is an indication of the date/time interval that this stats record relates to.
- unit
- Currently only per-minute stats are supported.
- schema
- The JSON schema used for the encoding of the event.
- entries
- This is a flattened representation of the categories for which there are non-zero entries for this stats record.
It is possible to stream these values directly to the console by connecting and subscribing using Server-Sent Events (SSE)
curl -s -u "<loading API key, please wait>" "https://realtime.ably.io/sse?channel=[meta]stats:minute&v=1.2"
Demo OnlyCopyCopied!
This would return stats events in the following format:
id: [email protected]
event: message
data: {"id":"MVphZHA7l9:0:0","timestamp":1633679346026,"encoding":"json","channel":"[meta]stats:minute","data":"{\<a href="\">intervalId\</a>"2021-10-08:07:48\",\<a href="\">unit\</a>"minute\",\<a href="\">schema\</a>"https://schemas.ably.com/json/app-stats-0.0.1.json\",\"entries\":{\"messages.all.all.count\":1,\"messages.all.messages.count\":1,\"messages.outbound.realtime.all.count\":1,\"messages.outbound.realtime.messages.count\":1,\"messages.outbound.all.all.count\":1,\"messages.outbound.all.messages.count\":1,\"connections.all.peak\":2,\"connections.all.min\":1,\"connections.all.mean\":1,\"connections.all.opened\":1}}","name":"update"}
CopyCopied!
As there could potentially be a delay of up to one minute before the first stat event, you can obtain the most recent stat, followed by subsequent events, by using the rewind
option. For the Curl command, add the rewind=1
query parameter:
curl -s -u "<loading API key, please wait>" "https://realtime.ably.io/sse?channel=[meta]stats:minute&v=1.2&rewind=1"
Demo OnlyCopyCopied!
For the client library SDK example you can use the rewind
channel parameter
const channel = ably.channels.get("[meta]stats:minute", {params: {rewind: '1'}});
CopyCopied!
You can also use the History API to obtain stats from this metachannel, as shown in the following example:
curl -s -u "<loading API key, please wait>" "https://rest.ably.io/channels/[meta]stats:minute/messages?limit=1"
Demo OnlyCopyCopied!
This retrieves the most recent event.
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);
});
CopyCopied!
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);
});
CopyCopied!
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
}
CopyCopied!
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"
]
}
CopyCopied!