Editor's note, 3 October 2026. This post covers an earlier namespace. It still runs on the same API. Anlyon's product today is shared limits and receipts for AI agent actions.
"The agent handled it" is not an answer you can give an auditor, a customer, or yourself at 3am. You need to know what it actually did: what was delivered, what failed, what retried, and how that changed this week. Because your agent asks Anlyon for an action by name and Anlyon makes the production call itself, Anlyon can record what happened to each one: the action version that ran, what the destination replied, who approved it, and which run caused it. That record lives on the invocation (actions.invocations(), and Outcomes and receipts in the docs). This post covers the aggregate view on top of it: delivery statistics for messages and schedules, failure rates and usage over time. The other half of the audit trail is the run and span tree.
Analytics Overview
Anlyon tracks:
- Message delivery statistics
- Success and failure rates
- Delivery latency
- Schedule execution history
- Usage patterns over time
Getting Started
import { Client } from '@anlyonhq/sdk';
const client = new Client({
apiKey: process.env.ANLYON_API_KEY!,
});
// Get message analytics
const analytics = await client.analytics.messages({
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
});
console.log(`Total messages: ${analytics.data.total}`);
console.log(`Delivered: ${analytics.data.delivered}`);
console.log(`Failed: ${analytics.data.failed}`);
console.log(`Success rate: ${analytics.data.successRate}%`);
Message Analytics
Overall Statistics
const stats = await client.analytics.messages({
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
});
console.log('Message Statistics:', {
total: stats.data.total,
delivered: stats.data.delivered,
failed: stats.data.failed,
pending: stats.data.pending,
successRate: `${stats.data.successRate}%`,
averageLatency: `${stats.data.averageLatency}ms`,
});
Time-Series Data
Get hourly or daily breakdowns:
const timeSeries = await client.analytics.messages({
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
granularity: 'daily', // or 'hourly'
});
timeSeries.data.timeSeries.forEach(entry => {
console.log(`${entry.date}: ${entry.delivered} delivered, ${entry.failed} failed`);
});
Filter by Status
Analyze specific message states:
// Get only failed messages
const failed = await client.analytics.messages({
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
status: 'failed',
});
// Get only delivered messages
const delivered = await client.analytics.messages({
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
status: 'delivered',
});
Schedule Analytics
Track CRON schedule execution:
const scheduleStats = await client.analytics.schedules({
startDate: '2025-01-01T00:00:00Z',
endDate: '2025-01-31T23:59:59Z',
});
console.log('Schedule Statistics:', {
totalExecutions: scheduleStats.data.totalExecutions,
successful: scheduleStats.data.successful,
failed: scheduleStats.data.failed,
successRate: `${scheduleStats.data.successRate}%`,
});
Usage Analytics
Monitor your usage and quotas:
// Get current usage
const usage = await client.billing.getUsage();
console.log('Current Usage:', {
messagesToday: usage.data.usage.messagesToday,
messagesThisMonth: usage.data.usage.messagesThisMonth,
bandwidth: usage.data.usage.bandwidth,
remaining: usage.data.remaining,
});
// Get usage history
const history = await client.billing.getUsageHistory({ days: 30 });
history.data.history.forEach(day => {
console.log(`${day.date}: ${day.messagesPublished} messages published`);
});
Building Dashboards
Real-Time Dashboard
async function buildDashboard() {
// Get current stats
const [messages, schedules, usage] = await Promise.all([
client.analytics.messages({
startDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
endDate: new Date().toISOString(),
}),
client.analytics.schedules({
startDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(),
endDate: new Date().toISOString(),
}),
client.billing.getUsage(),
]);
return {
messages: {
total: messages.data.total,
successRate: messages.data.successRate,
averageLatency: messages.data.averageLatency,
},
schedules: {
totalExecutions: schedules.data.totalExecutions,
successRate: schedules.data.successRate,
},
usage: {
messagesToday: usage.data.usage.messagesToday,
messagesThisMonth: usage.data.usage.messagesThisMonth,
remaining: usage.data.remaining,
},
};
}
Historical Trends
async function getTrends(days: number = 30) {
const endDate = new Date();
const startDate = new Date();
startDate.setDate(startDate.getDate() - days);
const analytics = await client.analytics.messages({
startDate: startDate.toISOString(),
endDate: endDate.toISOString(),
granularity: 'daily',
});
return analytics.data.timeSeries.map(entry => ({
date: entry.date,
delivered: entry.delivered,
failed: entry.failed,
successRate: (entry.delivered / (entry.delivered + entry.failed)) * 100,
}));
}
Setting Up Alerts
Usage Alerts
Anlyon automatically sends alerts when you approach quota limits. Configure thresholds:
await client.notifications.updatePreferences({
quotaAlertThresholds: [50, 75, 90, 100], // Alert at these percentages
emailRecipients: ['ops@example.com'],
enabledTypes: ['quota_warning', 'quota_exceeded'],
});
Failure Rate Alerts
Monitor for delivery failure spikes:
async function checkFailureRate() {
const stats = await client.analytics.messages({
startDate: new Date(Date.now() - 60 * 60 * 1000).toISOString(), // Last hour
endDate: new Date().toISOString(),
});
const failureRate = (stats.data.failed / stats.data.total) * 100;
if (failureRate > 10) { // Alert if > 10% failure rate
// Send alert to monitoring system
console.warn(`High failure rate detected: ${failureRate}%`);
}
}
Integration with Monitoring Tools
Prometheus Metrics
import { Registry, Counter, Gauge } from 'prom-client';
const registry = new Registry();
const messagesTotal = new Counter({
name: 'relay_messages_total',
help: 'Total messages published',
registers: [registry],
});
const messagesDelivered = new Counter({
name: 'relay_messages_delivered',
help: 'Messages delivered successfully',
registers: [registry],
});
async function updateMetrics() {
const stats = await client.analytics.messages({
startDate: new Date(Date.now() - 60 * 60 * 1000).toISOString(),
endDate: new Date().toISOString(),
});
messagesTotal.inc(stats.data.total);
messagesDelivered.inc(stats.data.delivered);
}
Datadog Integration
import { StatsD } from 'node-statsd';
const statsd = new StatsD();
async function sendToDatadog() {
const stats = await client.analytics.messages({
startDate: new Date(Date.now() - 60 * 60 * 1000).toISOString(),
endDate: new Date().toISOString(),
});
statsd.gauge('relay.messages.total', stats.data.total);
statsd.gauge('relay.messages.delivered', stats.data.delivered);
statsd.gauge('relay.messages.failed', stats.data.failed);
statsd.gauge('relay.success_rate', stats.data.successRate);
}
Best Practices
- Monitor regularly: Set up automated checks for key metrics
- Track trends: Look for patterns in success rates over time
- Set appropriate alerts: Don't alert on every failure, focus on trends
- Analyze failures: Use analytics to understand why messages fail
- Optimize based on data: Use latency metrics to optimize endpoints
Next Steps
- Learn about Dead Letter Queue management
- Explore notification preferences
- Check out our TypeScript SDK guide
Monitor with confidence using Anlyon analytics! 📊
