skysignal:agent

v1.0.30Published 2 weeks ago

SkySignal Agent

Official APM agent for monitoring Meteor.js applications with SkySignal.

Features

  • System Metrics Monitoring - CPU, memory, disk, network, V8 heap, event loop utilization, and process resource usage
  • Method Performance Traces - Track Meteor Method execution with operation-level profiling and COLLSCAN detection
  • Publication Monitoring - Monitor publication performance and subscriptions
  • Publication Efficiency Analysis - Detect over-fetching (missing field projections) and unbounded cursors
  • Error Tracking - Automatic server-side and client-side error capture with browser context
  • Log Collection - Capture console.* and Meteor Log.* output with structured metadata and sampling
  • HTTP Request Monitoring - Track outgoing HTTP requests
  • Outbound HTTP Instrumentation - Zero-patch diagnostics_channel tracing for outbound HTTP/HTTPS and fetch requests
  • Database Query Monitoring - MongoDB query performance tracking with COLLSCAN flagging
  • Live Query Monitoring - Per-observer driver detection for Change Streams (Meteor 3.5+), oplog, and polling
  • DNS Timing - Measure DNS resolution latency by wrapping dns.lookup and dns.resolve
  • CPU Profiling - On-demand inspector-based CPU profiling when CPU exceeds a configurable threshold
  • Deprecated API Detection - Track sync vs async Meteor API usage to guide Meteor 3.x migration
  • Environment Snapshots - Periodic capture of package versions, Node.js flags, and OS metadata
  • Vulnerability Scanning - Hourly npm audit with severity reporting for high/critical CVEs
  • Real User Monitoring (RUM) - Browser-side Core Web Vitals (LCP, FID, CLS, TTFB, FCP, TTI) with automatic performance warnings
  • SPA Route Tracking - Automatic performance collection on every route change
  • Session Tracking - 30-minute user sessions with localStorage persistence
  • Browser Context - Automatic device, browser, OS, and network information collection
  • Batch Processing - Efficient batching and async delivery to minimize performance impact
  • Worker Thread Offloading - Optional worker_threads pool for compression to keep the host event loop clear

Installation

Add the package to your Meteor application:

meteor add skysignal:agent

Quick Start

1. Get Your API Key

Sign up at SkySignal and create a new site to get your API key.

2. Configure the Agent

Add the package to your Meteor application:

meteor add skysignal:agent

3. Configure the Agent

The agent can be configured via Meteor settings, environment variables, or both. When both are used, Meteor settings take priority over environment variables.

Option A: Meteor Settings File

settings-production.json:

1{
2  "skysignal": {
3    "apiKey": "sk_your_api_key_here",
4    "enabled": true,
5    "appVersion": "1.2.3",
6  },
7  "public": {
8    "skysignal": {
9      "publicKey": "pk_your_public_key_here",
10      "rum": {
11        "enabled": true,
12        "sampleRate": 1.0,
13      },
14      "errorTracking": {
15        "enabled": true,
16        "captureUnhandledRejections": true
17      }
18    }
19  }
20}

Option B: Environment Variables

SKYSIGNAL_API_KEY=sk_your_api_key_here meteor run

Option C: Both (Settings override env vars)

# API key from env, tuning from settings
SKYSIGNAL_API_KEY=sk_your_api_key_here meteor run --settings settings.json

The agent auto-starts when it finds a valid apiKey in either Meteor.settings.skysignal or the SKYSIGNAL_API_KEY environment variable.

Configuration Options

All configuration options can be set via Meteor.settings.skysignal or environment variables. When both are present, the priority order is:

  1. Meteor.settings (highest priority)
  2. Environment variables (fallback)
  3. Default values (lowest priority)

Environment Variables

Every server-side configuration option has a corresponding environment variable. Boolean values accept true/1/yes and false/0/no (case-insensitive). Invalid values are warned and skipped.

Environment VariableConfig KeyType
SKYSIGNAL_API_KEYapiKeyString
SKYSIGNAL_ENDPOINTendpointString
SKYSIGNAL_ENABLEDenabledBoolean
SKYSIGNAL_DEBUGdebugBoolean
SKYSIGNAL_HOSThostString
SKYSIGNAL_APP_VERSIONappVersionString
SKYSIGNAL_BATCH_SIZEbatchSizeInteger
SKYSIGNAL_BATCH_SIZE_BYTESbatchSizeBytesInteger
SKYSIGNAL_FLUSH_INTERVALflushIntervalInteger
SKYSIGNAL_TRACE_SAMPLE_RATEtraceSampleRateFloat
SKYSIGNAL_RUM_SAMPLE_RATErumSampleRateFloat
SKYSIGNAL_INDEX_USAGE_SAMPLE_RATEindexUsageSampleRateFloat
SKYSIGNAL_LOG_SAMPLE_RATElogSampleRateFloat
SKYSIGNAL_COLLECT_SYSTEM_METRICScollectSystemMetricsBoolean
SKYSIGNAL_COLLECT_TRACEScollectTracesBoolean
SKYSIGNAL_COLLECT_ERRORScollectErrorsBoolean
SKYSIGNAL_COLLECT_HTTPcollectHttpRequestsBoolean
SKYSIGNAL_COLLECT_MONGO_POOLcollectMongoPoolBoolean
SKYSIGNAL_COLLECT_COLLECTION_STATScollectCollectionStatsBoolean
SKYSIGNAL_COLLECT_DDPcollectDDPConnectionsBoolean
SKYSIGNAL_COLLECT_RUMcollectRUMBoolean
SKYSIGNAL_COLLECT_JOBScollectJobsBoolean
SKYSIGNAL_COLLECT_LOGScollectLogsBoolean
SKYSIGNAL_COLLECT_DNS_TIMINGScollectDnsTimingsBoolean
SKYSIGNAL_COLLECT_OUTBOUND_HTTPcollectOutboundHttpBoolean
SKYSIGNAL_COLLECT_CPU_PROFILEScollectCpuProfilesBoolean
SKYSIGNAL_COLLECT_LIVE_QUERIEScollectLiveQueriesBoolean
SKYSIGNAL_COLLECT_PUBLICATIONScollectPublicationsBoolean
SKYSIGNAL_COLLECT_ENVIRONMENTcollectEnvironmentBoolean
SKYSIGNAL_COLLECT_VULNERABILITIEScollectVulnerabilitiesBoolean
SKYSIGNAL_COLLECT_DEPRECATED_APIScollectDeprecatedApisBoolean
SKYSIGNAL_INGEST_AGGREGATIONingestAggregationBoolean
SKYSIGNAL_LOG_LEVELSlogLevelsComma-separated
SKYSIGNAL_LOG_MAX_MESSAGE_LENGTHlogMaxMessageLengthInteger
SKYSIGNAL_LOG_CAPTURE_CONSOLElogCaptureConsoleBoolean
SKYSIGNAL_LOG_CAPTURE_METEOR_LOGlogCaptureMeteorLogBoolean

All collection interval and performance options also have corresponding SKYSIGNAL_* environment variables. See lib/env.js for the complete mapping.

API Configuration

OptionTypeDefaultDescription
apiKeyStringrequiredYour SkySignal API key (sk_ prefix)
endpointStringhttps://dash.skysignal.appSkySignal API endpoint
enabledBooleantrueEnable/disable the agent

Host & Version Identification

OptionTypeDefaultDescription
hostStringos.hostname()Host identifier for this instance
appVersionStringAuto-detectApp version from package.json or manually configured
buildHashStringAuto-detectBuild hash for source map lookup. Auto-detects from BUILD_HASH or GIT_SHA environment variables

Batching Configuration

OptionTypeDefaultDescription
batchSizeNumber50Max items per batch before auto-flush
batchSizeBytesNumber262144Max bytes (256KB) per batch
flushIntervalNumber10000Interval (ms) to flush batched data

Sampling Rates

OptionTypeDefaultDescription
traceSampleRateNumber1.0Server trace sample rate (0-1). Set to 0.1 for 10%
rumSampleRateNumber0.5RUM sample rate (0-1). 50% by default for high-volume

Collection Intervals

OptionTypeDefaultDescription
systemMetricsIntervalNumber60000System metrics collection interval (1 minute)
mongoPoolIntervalNumber60000MongoDB pool metrics interval (1 minute)
collectionStatsIntervalNumber300000Collection stats interval (5 minutes)
ddpConnectionsIntervalNumber30000DDP connection updates interval (30 seconds)
jobsIntervalNumber30000Background job stats interval (30 seconds)
dnsTimingsIntervalNumber60000DNS timing aggregation interval (1 minute)
outboundHttpIntervalNumber60000Outbound HTTP aggregation interval (1 minute)
cpuProfileCheckIntervalNumber30000CPU check interval for threshold profiling (30 seconds)
deprecatedApisIntervalNumber300000Deprecated API usage reporting interval (5 minutes)
publicationsIntervalNumber300000Publication efficiency reporting interval (5 minutes)
environmentIntervalNumber1800000Environment snapshot interval (30 minutes)
vulnerabilitiesIntervalNumber3600000Vulnerability scan interval (1 hour)

Feature Flags

OptionTypeDefaultDescription
collectSystemMetricsBooleantrueCollect system metrics (CPU, memory, disk, network)
collectTracesBooleantrueCollect method/publication traces
collectErrorsBooleantrueCollect errors and exceptions
collectHttpRequestsBooleantrueCollect HTTP request metrics
collectMongoPoolBooleantrueCollect MongoDB connection pool metrics
collectCollectionStatsBooleantrueCollect MongoDB collection statistics
collectDDPConnectionsBooleantrueCollect DDP/WebSocket connection metrics
collectLiveQueriesBooleantrueCollect Meteor live query metrics (change streams, oplog, polling)
collectJobsBooleantrueCollect background job metrics
collectLogsBooleantrueCollect server-side logs from console and Meteor Log
collectRUMBooleanfalseClient-side RUM (disabled by default, requires publicKey)
collectDnsTimingsBooleantrueCollect DNS resolution latency by wrapping dns.lookup/dns.resolve
collectOutboundHttpBooleantrueCollect outbound HTTP metrics via diagnostics_channel (Node 16+)
collectCpuProfilesBooleantrueEnable on-demand CPU profiling when CPU exceeds threshold
collectDeprecatedApisBooleantrueTrack sync vs async Meteor API usage (migration readiness)
collectPublicationsBooleantrueDetect publication over-fetching and missing projections
collectEnvironmentBooleantrueCapture environment metadata (packages, flags, OS info)
collectVulnerabilitiesBooleantrueRun npm audit scans and report high/critical CVEs
ingestAggregationBooleantrueRoll up live query / subscription telemetry into fixed-shape aggregates before shipping. Reduces server ingest row counts 10-100× on high-volume apps. Requires a platform version that supports the aggregate ingest endpoints (v1.0.30+). Set to false to post per-observer / per-subscription records instead.

Agent-Side Aggregation

When ingestAggregation is enabled (the default), the LiveQueriesCollector and DDPCollector pre-aggregate telemetry on the agent into two compact payload shapes (one per live query signature, one per publication + params signature) and POST them to:

  • POST /api/v1/live-queries/aggregates
  • POST /api/v1/subscriptions/aggregates

The platform responds with the current recommended flush interval and aggregate sample rate for the site. The agent honors the guidance on its next flush, letting the platform dial back flush frequency when a site is under load without requiring a restart.

When to disable: deployments on a platform version older than v1.0.30 (the aggregate endpoints will 404), or when you specifically need per-entity records for debugging. Disabling is also harmless on low-volume apps — the dashboard UX is identical either way.

The platform dashboard shows an "Aggregated ingest" chip on the Live Queries and Pub/Sub tabs when metrics for the selected time range were served from the aggregate path.

MongoDB Pool Configuration

OptionTypeDefaultDescription
mongoPoolFixedConnectionMemoryNumbernullOptional: fixed bytes per connection for memory estimation

Method Tracing Configuration

OptionTypeDefaultDescription
traceMethodArgumentsBooleantrueCapture method arguments (sanitized)
maxArgLengthNumber1000Max string length for arguments
traceMethodOperationsBooleantrueCapture detailed operation timeline

Index Usage Tracking

OptionTypeDefaultDescription
captureIndexUsageBooleantrueCapture MongoDB index usage via explain()
indexUsageSampleRateNumber0.05Sample 5% of queries for explain()
explainVerbosityStringexecutionStatsqueryPlanner | executionStats | allPlansExecution
explainSlowQueriesOnlyBooleanfalseOnly explain queries exceeding slow threshold

Performance Safeguards

OptionTypeDefaultDescription
maxBatchRetriesNumber3Max retries for failed batches
requestTimeoutNumber3000API request timeout (3 seconds)
maxMemoryMBNumber50Max memory (MB) for batches

CPU Profiling Configuration

OptionTypeDefaultDescription
cpuProfileThresholdNumber80CPU usage percentage to trigger an on-demand profile
cpuProfileDurationNumber10000Duration (ms) of the CPU profile sample
cpuProfileCooldownNumber300000Minimum time (ms) between consecutive profiles (5 minutes)

Worker Offload (Large Pools)

OptionTypeDefaultDescription
useWorkerThreadBooleanfalseEnable worker thread for large pools
workerThresholdNumber50Spawn worker if pool size exceeds this

Background Job Monitoring

OptionTypeDefaultDescription
collectJobsBooleantrueEnable background job monitoring
jobsIntervalNumber30000Job stats collection interval (30 seconds)
jobsPackageStringnullAuto-detect, or specify: "msavin:sjobs"

Log Collection

OptionTypeDefaultDescription
collectLogsBooleantrueEnable log capturing
logLevelsArray["info", "warn", "error", "fatal"]Log levels to capture (excludes debug by default)
logSampleRateNumber1.0Sample rate (0-1). Reduce for high-volume apps
logMaxMessageLengthNumber10000Max characters per log message before truncation
logCaptureConsoleBooleantrueIntercept console.log, console.info, console.warn, console.error, console.debug
logCaptureMeteorLogBooleantrueIntercept Meteor Log.info, Log.warn, Log.error, Log.debug

Live Query Monitoring

OptionTypeDefaultDescription
collectLiveQueriesBooleantrueEnable reactive query observer monitoring (change streams, oplog, polling)
liveQueriesIntervalNumber60000Reporting interval in ms (60 seconds)
liveQueriesMaxObserversNumber5000Max tracked observers before eviction (min: 500). Increase for high-traffic apps
liveQueriesPerformanceThresholdsObjectnullOptional: custom performance thresholds per observer type

Client-Side Error Tracking

Client-side error tracking is configured in Meteor.settings.public.skysignal.errorTracking and auto-initializes alongside RUM.

OptionTypeDefaultDescription
errorTracking.enabledBooleantrueEnable client-side error capture
errorTracking.captureUnhandledRejectionsBooleantrueCapture unhandled Promise rejections
errorTracking.debugBooleanfalseLog error tracker activity to the browser console

What Gets Monitored

System Metrics (Automatic)

The agent automatically collects:

  • CPU Usage - Overall CPU utilization percentage
  • CPU Cores - Number of CPU cores available
  • Load Average - 1m, 5m, 15m load averages
  • Memory Usage - Total, used, free, and percentage (heap, external, RSS)
  • Event Loop Utilization - 0-1 ratio of how busy the event loop is (Node 14.10+)
  • V8 Heap Statistics - Per-space breakdown (new_space, old_space, code_space, etc.), native context count, detached context leak detection
  • Process Resource Usage - User/system CPU time, voluntary/involuntary context switches, filesystem reads/writes (via process.resourceUsage())
  • Active Resources - Handle/request counts by type (Timer, TCPWrap, FSReqCallback) for resource leak detection (Node 17+)
  • Container Memory Limit - cgroup memory constraint for containerized deployments (Node 19+)
  • Disk Usage - Disk space utilization (platform-dependent)
  • Network Traffic - Bytes in/out (platform-dependent)
  • Process Count - Number of running processes (platform-dependent)
  • Agent Version - Tracks the installed agent version for compatibility checks

Collected every 60 seconds by default.

Method Traces

Automatic instrumentation of Meteor Methods:

  • Method name and execution time
  • Operation-level breakdown (DB queries, async operations, compute time)
  • Detailed MongoDB operation tracking with explain() support
  • COLLSCAN detection - Flags queries performing full collection scans (no index used)
  • Slow aggregation pipeline capture - Captures sanitized pipeline stages for slow aggregations
  • N+1 query detection and slow query analysis
  • this.unblock() analysis with optimization recommendations
  • Wait time tracking (DDP queue, connection pool)
  • Error tracking with stack traces
  • User context and session correlation

Publication Monitoring

Track publication performance:

  • Publication name and execution time
  • Subscription lifecycle tracking
  • Document counts (added, changed, removed)
  • Data transfer size estimation
  • Live query efficiency (oplog vs polling)

DDP Connection Monitoring

Real-time WebSocket connection tracking:

  • Active connection count and status
  • Message volume (sent/received) by type
  • Bandwidth usage per connection
  • Latency measurements (ping/pong)
  • Subscription tracking per connection

MongoDB Pool Monitoring

Connection pool health and performance:

  • Pool configuration (min/max size, timeouts)
  • Active vs available connections
  • Checkout wait times (avg, max, P95)
  • Queue length and timeout tracking
  • Memory usage estimation

Live Query Monitoring

Meteor reactive query tracking with per-observer driver detection:

  • Change Stream detection (Meteor 3.5+), oplog, and polling observer types
  • Per-observer introspection via handle._multiplexer._observeDriver.constructor.name
  • Fallback to MONGO_OPLOG_URL heuristic for pre-3.5 Meteor apps
  • Reactive efficiency metric: (changeStream + oplog) / total observers
  • Observer count by collection
  • Document update rates
  • Performance ratings (optimal/good/slow)
  • Query signature deduplication

Background Job Monitoring

Track msavin:sjobs (Steve Jobs) and other job packages:

  • Job execution times and status
  • Queue length and worker utilization
  • Failed job tracking with error details
  • Job type categorization

DNS Timing

Measure DNS resolution latency to detect slow or misconfigured resolvers:

  • Wraps dns.lookup() and dns.resolve() without replacing them
  • Per-hostname resolution times with avg, P95, and max latency
  • Failure counts and error tracking
  • Ring buffer (last 500 samples) to bound memory
  • Particularly useful in Docker/K8s environments where DNS is a common latency source

Reported every 60 seconds by default.

Outbound HTTP Instrumentation

Track outbound HTTP/HTTPS requests using Node.js diagnostics_channel (Node 16+):

  • Zero monkey-patching — uses the same mechanism as OpenTelemetry and Undici
  • Request timing breakdown: DNS, connect, TLS handshake, TTFB, total duration
  • Request/response metadata: method, host, path, status code, content-length
  • Error rates for external API dependencies
  • Aggregated per endpoint to minimize cardinality

Reported every 60 seconds by default.

CPU Profiling (On-Demand)

Automatic CPU profiling when CPU usage spikes above a configurable threshold:

  • Uses the built-in inspector module (same as Chrome DevTools) — zero dependencies
  • Triggered automatically when CPU exceeds the threshold (default: 80%)
  • Sends a summary (top functions by self-time), not raw profile data
  • Configurable duration (default: 10s) and cooldown (default: 5 min between profiles)
  • Minimal overhead when not actively profiling

Deprecated API Detection

Track synchronous vs asynchronous Meteor API usage to measure migration readiness:

  • Wraps Mongo.Collection prototype methods to count sync vs async calls
  • Tracks Collection.find().fetch() vs fetchAsync(), findOne() vs findOneAsync(), etc.
  • Tracks Meteor.call() vs Meteor.callAsync()
  • Per-collection counters with negligible overhead (just increments)
  • Helps prioritize Meteor 3.x async migration efforts

Reported every 5 minutes by default.

Publication Efficiency Analysis

Detect over-fetching and unbounded publications:

  • Wraps Meteor.publish to intercept returned cursors
  • Checks _cursorDescription.options.fields for missing projections (over-fetching flag)
  • Tracks document counts per publication (average and max)
  • Flags publications returning large result sets without limits
  • Per-publication call counts and efficiency scores

Reported every 5 minutes by default.

Environment Snapshots

Periodic capture of application environment metadata:

  • Installed package versions from process.versions and package.json
  • Node.js flags (process.execArgv)
  • Environment variable keys (NOT values — security-conscious)
  • OS platform, release, CPU count, total memory
  • Collected immediately on start, then refreshed periodically

Reported every 30 minutes by default.

Vulnerability Scanning

Automated security scanning for known package vulnerabilities:

  • Runs npm audit --json on a configurable schedule
  • Supports both npm audit v6 and v7+ JSON formats
  • Only reports high and critical severity vulnerabilities to reduce noise
  • Tracks: package name, severity, advisory title, fix availability
  • Deduplicates results (skips reporting if unchanged since last scan)
  • 30-second timeout on npm audit to prevent blocking

Reported every 1 hour by default. Initial scan delayed 60s after startup.

Error Tracking

Automatic error capture on both server and client:

  • Server-side errors with stack traces
  • Client-side errors via window.onerror and unhandledrejection handlers
  • Browser context (URL, user agent, viewport, user ID)
  • Error grouping and fingerprinting
  • Affected users and methods
  • Build hash correlation for source maps
  • Batched delivery to /api/v1/errors with public key authentication

Log Collection

Server-side log capture with structured metadata:

  • Intercepts console.log, console.info, console.warn, console.error, console.debug
  • Intercepts Meteor Log.info, Log.warn, Log.error, Log.debug
  • Configurable log levels (default: info, warn, error, fatal)
  • Sampling support for high-volume apps
  • Message truncation to prevent oversized payloads
  • Automatic host and timestamp enrichment
  • Correlation with Meteor Method traces via methodName and traceId
  • Programmatic log submission via SkySignalAgent.addLog()

Real User Monitoring (RUM) - Client-Side

Automatic browser-side performance monitoring collecting Core Web Vitals and providing PageSpeed-style performance warnings.

What Gets Collected

Core Web Vitals:

  • LCP (Largest Contentful Paint) - Measures loading performance
    • Good: <2.5s | Needs Improvement: 2.5-4s | Poor: >4s
  • FID (First Input Delay) - Measures interactivity
    • Good: <100ms | Needs Improvement: 100-300ms | Poor: >300ms
  • CLS (Cumulative Layout Shift) - Measures visual stability
    • Good: <0.1 | Needs Improvement: 0.1-0.25 | Poor: >0.25
  • TTFB (Time to First Byte) - Measures server response time
    • Good: <800ms | Needs Improvement: 800-1800ms | Poor: >1800ms
  • FCP (First Contentful Paint) - Measures perceived load speed
    • Good: <1.8s | Needs Improvement: 1.8-3s | Poor: >3s
  • TTI (Time to Interactive) - Measures time until page is fully interactive
    • Good: <3.8s | Needs Improvement: 3.8-7.3s | Poor: >7.3s

Additional Context:

  • Browser name and version
  • Device type (mobile, tablet, desktop)
  • Operating system
  • Network connection type, downlink speed, RTT
  • Viewport and screen dimensions
  • User ID (via Meteor.userId() for correlation with server-side traces)
  • Session ID (30-minute sessions with localStorage persistence)
  • Page route and referrer
  • Top 10 slowest resources

Configuration

RUM monitoring auto-initializes from your Meteor settings.

settings-development.json:

1{
2  "skysignal": {
3    "apiKey": "sk_your_server_api_key_here",
4    "endpoint": "http://localhost:3000"
5  },
6  "public": {
7    "skysignal": {
8      "publicKey": "pk_your_public_key_here",
9      "endpoint": "http://localhost:3000",
10      "rum": {
11        "enabled": true,
12        "sampleRate": 1.0,
13        "debug": false
14      },
15      "errorTracking": {
16        "enabled": true,
17        "captureUnhandledRejections": true,
18        "debug": false
19      }
20    }
21  }
22}

Configuration Options:

OptionTypeDefaultDescription
publicKeyStringrequiredSkySignal Public Key (pk_ prefix) - Safe for client-side use
endpointString(same origin)Base URL of SkySignal API (e.g., http://localhost:3000 or https://dash.skysignal.app)
rum.enabledBooleantrueEnable/disable RUM collection
rum.sampleRateNumberAutoSample rate (0-1). Auto: 100% for localhost, 50% for production
rum.debugBooleanfalseEnable console logging for debugging
errorTracking.enabledBooleantrueEnable client-side error capture via window.onerror and unhandledrejection
errorTracking.captureUnhandledRejectionsBooleantrueCapture unhandled Promise rejections
errorTracking.debugBooleanfalseLog error tracker activity to the browser console

Key Security Note:

  • API Key (sk_ prefix): Server-side only, keep in private settings.skysignal. Used for server-to-server communication.
  • Public Key (pk_ prefix): Client-side safe, can be in settings.public.skysignal. Used for browser RUM collection.
  • This follows the Stripe pattern of separating public/private keys for security.

The agent automatically:

  • Collects Core Web Vitals using Google's web-vitals library
  • Tracks SPA route changes and collects metrics for each route
  • Batches measurements and sends via fire-and-forget HTTP with keepalive: true
  • Provides PageSpeed-style console warnings for poor performance
  • Correlates metrics with server-side traces via Meteor.userId()

SPA Route Change Tracking

The RUM client automatically detects route changes in single-page applications by:

  • Overriding history.pushState and history.replaceState
  • Listening for popstate events (browser back/forward)
  • Listening for hashchange events (hash-based routing)

Each route change triggers a new performance collection, allowing you to track performance across your entire application navigation flow.

Performance Warnings

When Core Web Vitals exceed recommended thresholds, the RUM collector logs PageSpeed-style warnings to the console:

[SkySignal RUM] Largest Contentful Paint (LCP) is slow: 4200ms. LCP should be under 2.5s for good user experience. Consider optimizing images, removing render-blocking resources, and improving server response times.

These warnings help developers identify performance issues during development and testing.

Manual Usage (Advanced)

While RUM auto-initializes, you can also use it manually:

1import { SkySignalRUM } from 'meteor/skysignal:agent';
2
3// Check if initialized
4if (SkySignalRUM.isInitialized()) {
5  // Get current session ID
6  const sessionId = SkySignalRUM.getSessionId();
7
8  // Get current metrics (for debugging)
9  const metrics = SkySignalRUM.getMetrics();
10
11  // Get performance warnings (for debugging)
12  const warnings = SkySignalRUM.getWarnings();
13
14  // Manually track a page view (for custom routing)
15  SkySignalRUM.trackPageView('/custom-route');
16}

How It Works

  1. Session Management - Creates a 30-minute session in localStorage, renews on user activity
  2. Core Web Vitals Collection - Uses Google's web-vitals library for accurate measurements
  3. Browser Context Collection - Detects browser, device, OS, network info from user agent and Navigator API
  4. Performance Warnings - Compares metrics against PageSpeed thresholds and logs warnings
  5. Batching - Batches measurements (default: 10 per batch, 5-second flush interval)
  6. HTTP Transmission - Sends to /api/v1/rum endpoint with keepalive: true for reliability
  7. SPA Detection - Automatically resets and re-collects metrics on route changes

Advanced Usage

Custom Metrics

Track business-specific KPIs and performance indicators with the custom metrics API:

Counter Metrics

Use counters for values that only increment (orders placed, emails sent, API calls):

1import { SkySignalAgent } from 'meteor/skysignal:agent';
2
3// Simple counter increment
4SkySignalAgent.counter('orders.completed');
5
6// Counter with custom value and tags
7SkySignalAgent.counter('items.sold', 5, {
8  tags: { category: 'electronics', store: 'NYC' }
9});
10
11// Track API requests by endpoint
12SkySignalAgent.counter('api.requests', 1, {
13  tags: { endpoint: '/users', method: 'GET', status: '200' }
14});

Timer Metrics

Use timers for measuring durations (API response times, job execution, processing time):

1// Track payment processing time
2const start = Date.now();
3await processPayment(order);
4SkySignalAgent.timer('payment.processing', Date.now() - start, {
5  tags: { provider: 'stripe', currency: 'USD' }
6});
7
8// Track external API call duration
9const start = Date.now();
10const result = await fetch('https://api.example.com/data');
11SkySignalAgent.timer('external.api.call', Date.now() - start, {
12  tags: { service: 'example', endpoint: '/data', status: result.status }
13});

Gauge Metrics

Use gauges for point-in-time values that go up or down (queue size, active users, inventory):

1// Track queue depth
2const queueSize = await getQueueSize('email-queue');
3SkySignalAgent.gauge('queue.size', queueSize, {
4  unit: 'items',
5  tags: { queue: 'email' }
6});
7
8// Track active users
9const activeUsers = Meteor.server.sessions.size;
10SkySignalAgent.gauge('users.active', activeUsers, {
11  unit: 'users'
12});
13
14// Track inventory levels
15SkySignalAgent.gauge('inventory.stock', 150, {
16  unit: 'items',
17  tags: { product: 'widget-123', warehouse: 'NYC' }
18});

Generic trackMetric Method

For full control, use the generic trackMetric() method:

1SkySignalAgent.trackMetric({
2  name: 'checkout.flow',
3  type: 'counter',      // 'counter' | 'timer' | 'gauge'
4  value: 1,
5  unit: 'conversions',  // optional
6  tags: {               // optional - for filtering in dashboard
7    product: 'premium',
8    region: 'us-east-1'
9  }
10});

Manual Trace Submission

Track custom operations:

1const startTime = Date.now();
2
3// Your code here...
4
5SkySignalAgent.client.addTrace({
6  traceType: 'method',
7  methodName: 'myCustomOperation',
8  timestamp: new Date(startTime),
9  duration: Date.now() - startTime,
10  userId: this.userId,
11  operations: [
12    { type: 'start', time: 0, details: {} },
13    { type: 'db', time: 50, details: { collection: 'users', func: 'findOne' } },
14    { type: 'complete', time: 150, details: {} }
15  ]
16});

Manual Log Submission

Send structured logs programmatically, bypassing console.* / Meteor Log.* interception:

1import { SkySignalAgent } from 'meteor/skysignal:agent';
2
3// Simple log
4SkySignalAgent.addLog('info', 'User signed up', { userId: 'abc123' });
5
6// Error log with context
7SkySignalAgent.addLog('error', 'Payment failed', {
8  orderId: 'xyz-789',
9  provider: 'stripe',
10  errorCode: 'card_declined'
11});
12
13// Warning with structured metadata
14SkySignalAgent.addLog('warn', 'Rate limit approaching', {
15  endpoint: '/api/search',
16  currentRate: 450,
17  limit: 500
18});

Log levels: debug, info, warn, error, fatal

Logs submitted via addLog() are tagged with source: "api" to distinguish them from auto-captured console/Meteor logs.

Stopping the Agent

To gracefully stop the agent (e.g., during shutdown):

1SkySignalAgent.stop();

This will:

  1. Stop all collectors
  2. Flush any remaining batched data
  3. Clear all intervals

Performance Impact

The agent is designed to have minimal performance impact on your application:

Built-in Optimizations

  • Fire-and-forget batching - Data is batched and sent asynchronously using setImmediate() for lowest latency
  • HTTP connection pooling - Reuses TCP connections with keepAlive to reduce handshake overhead
  • Gzip compression - Large payloads (>1KB) are compressed before sending to reduce bandwidth
  • Non-blocking collection - System metrics use async commands to avoid blocking the event loop
  • Object pooling - HTTP request tracking reuses pre-allocated objects to reduce GC pressure
  • Optimized URL matching - Combined regex patterns for O(1) exclude pattern matching
  • Staggered startup - Collectors start with 500ms intervals to avoid CPU spikes at boot
  • Configurable intervals - Adjust collection frequency based on your needs
  • Automatic retries - Failed requests are re-queued with exponential backoff and jitter

Typical Overhead

  • CPU: < 1% additional usage
  • Memory: ~10-20MB for batching queues
  • Network: ~1KB per metric (less with compression), sent in batches
  • Event loop: < 1ms impact per collection cycle

Troubleshooting

Agent Not Sending Data

  1. Check that your API key is correct
  2. Verify enabled: true in configuration
  3. Check server logs for error messages
  4. Verify network connectivity to SkySignal API

High Memory Usage

If you notice high memory usage:

  1. Reduce batchSize to flush data more frequently
  2. Reduce collection intervals
  3. Disable collectors you don't need

Missing System Metrics

Some system metrics (disk, network, process count) require platform-specific APIs:

  • Use the systeminformation npm package for comprehensive cross-platform metrics
  • These metrics may return null on certain platforms

API Reference

SkySignalAgent

Main agent singleton instance.

Configuration Methods

  • configure(options) - Configure the agent with options
  • start() - Start all collectors and monitoring
  • stop() - Stop all collectors and flush data

Custom Metrics Methods

MethodDescription
counter(name, value?, options?)Track incremental values (default value: 1)
timer(name, duration, options?)Track durations in milliseconds
gauge(name, value, options?)Track point-in-time values
trackMetric(options)Generic method with full control

Log Methods

MethodDescription
addLog(level, message, metadata?)Submit a structured log entry. Level: debug, info, warn, error, fatal

Options object:

  • tags - Object with key-value pairs for filtering
  • unit - Unit of measurement (e.g., 'ms', 'items', 'percent')
  • timestamp - Optional Date (defaults to now)

Properties

  • client - HTTP client instance for manual data submission
  • config - Current configuration object
  • collectors - Active collector instances
  • started - Boolean indicating if agent is running

Support