Skip to content
reaatechREAATECH

@reaatech/llm-cost-telemetry-exporters

npm v0.1.0

Provides exporter classes (CloudWatchExporter

@reaatech/llm-cost-telemetry-exporters

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

Telemetry exporters for pushing LLM cost data to observability platforms. Supports AWS CloudWatch (standard + EMF), GCP Cloud Monitoring (custom metrics), and Grafana Loki/Phoenix (JSON-line push API).

Installation

terminal
npm install @reaatech/llm-cost-telemetry-exporters
# or
pnpm add @reaatech/llm-cost-telemetry-exporters

Cloud SDKs are peer dependencies — install only the ones you use:

terminal
pnpm add @aws-sdk/client-cloudwatch  # for CloudWatchExporter
pnpm add @google-cloud/monitoring    # for CloudMonitoringExporter

Feature Overview

  • CloudWatch exporter — publishes LLMCost and LLMAggregatedCost metrics with rich dimensions
  • Cloud Monitoring exporter — creates custom time series at custom.googleapis.com/llm/
  • Phoenix/Loki exporter — pushes JSON-line logs to Grafana Loki’s push API
  • EMF format — CloudWatch supports Embedded Metric Format for structured log-based metrics
  • Batched export — configurable batch sizes with automatic flushing
  • Retry with backoff — all exporters inherit exponential backoff from BaseExporter

Quick Start

typescript
import { CloudWatchExporter, PhoenixExporter } from "@reaatech/llm-cost-telemetry-exporters";
 
const cw = new CloudWatchExporter({
  region: "us-east-1",
  namespace: "LLM/Costs",
});
 
const phoenix = new PhoenixExporter({
  host: "http://loki:3100",
  defaultLabels: { service: "llm-cost-telemetry" },
});
 
await cw.exportSpans(spans);
await phoenix.exportRecords(records);

API Reference

BaseExporter

Abstract base class shared by all exporters:

typescript
import { BaseExporter, type ExportResult } from "@reaatech/llm-cost-telemetry-exporters";

Methods

MethodDescription
exportSpans(spans)Export individual cost spans
exportRecords(records)Export aggregated cost records
exportWithRetry(fn)Wrap with exponential backoff
healthCheck()Check exporter connectivity
close()Graceful shutdown

Properties

PropertyTypeDescription
isEnabledbooleanWhether the exporter is active
batchSizenumberMax items per batch

CloudWatchExporter

Publishes to AWS CloudWatch using PutMetricData:

typescript
import {
  CloudWatchExporter,
  type CloudWatchExporterOptions,
} from "@reaatech/llm-cost-telemetry-exporters";
 
const exporter = new CloudWatchExporter({
  type: "cloudwatch",
  enabled: true,
  region: "us-east-1",
  namespace: "LLM/Costs",
  emfEnabled: true,
  logGroupName: "/aws/llm/costs",
  batchSize: 20,
  flushInterval: 60000,
});

CloudWatchExporterOptions

PropertyTypeDefaultDescription
regionstringus-east-1AWS region
namespacestringLLM/CostsCloudWatch metric namespace
emfEnabledbooleantrueEnable Embedded Metric Format
logGroupNamestring/aws/llm/costsEMF log group name
batchSizenumber20Max metrics per PutMetricData call
flushIntervalnumber60000Auto-flush interval in ms

Published Metrics

MetricDimensions
LLMCostProvider, Model, Tenant, Feature, Route
LLMAggregatedCostProvider, Model, Tenant, Feature, Route

CloudMonitoringExporter

Publishes to GCP Cloud Monitoring as custom metrics:

typescript
import {
  CloudMonitoringExporter,
  type CloudMonitoringExporterOptions,
} from "@reaatech/llm-cost-telemetry-exporters";
 
const exporter = new CloudMonitoringExporter({
  type: "cloud-monitoring",
  enabled: true,
  projectId: "my-gcp-project",
  metricTypePrefix: "custom.googleapis.com/llm",
  resourceType: "gce_instance",
  batchSize: 200,
  flushInterval: 60000,
});

CloudMonitoringExporterOptions

PropertyTypeDefaultDescription
projectIdstring(required)GCP project ID
metricTypePrefixstringcustom.googleapis.com/llmMetric type prefix
resourceTypestringgce_instanceMonitored resource type
batchSizenumber200Max time series per request
flushIntervalnumber60000Auto-flush interval in ms

Published Time Series

MetricType
custom.googleapis.com/llm/costGAUGE, DOUBLE
custom.googleapis.com/llm/aggregated_costGAUGE, DOUBLE

PhoenixExporter

Pushes JSON-line logs to Grafana Loki:

typescript
import {
  PhoenixExporter,
  type PhoenixExporterOptions,
} from "@reaatech/llm-cost-telemetry-exporters";
 
const exporter = new PhoenixExporter({
  type: "phoenix",
  enabled: true,
  host: "http://loki:3100",
  defaultLabels: {
    service: "llm-cost-telemetry",
    environment: "production",
  },
  username: "loki-user",       // optional
  password: "loki-pass",       // optional
  batchSize: 100,
  flushInterval: 30000,
});

PhoenixExporterOptions

PropertyTypeDefaultDescription
hoststringhttp://localhost:3100Loki push endpoint
defaultLabelsRecord<string, string>{ service, environment }Default Loki stream labels
usernamestringBasic auth username
passwordstringBasic auth password
batchSizenumber100Max entries per push
flushIntervalnumber30000Auto-flush interval in ms

Push Endpoint

Data is pushed to {host}/loki/api/v1/push as Loki streams with configurable labels.

Usage Patterns

Multi-Exporter Setup

typescript
import {
  CloudWatchExporter,
  CloudMonitoringExporter,
  PhoenixExporter,
} from "@reaatech/llm-cost-telemetry-exporters";
 
const exporters = [
  new CloudWatchExporter({ region: "us-east-1" }),
  new PhoenixExporter({ host: "http://loki:3100" }),
];
 
for (const exporter of exporters) {
  if (exporter.isEnabled) {
    await exporter.exportSpans(spans);
  }
}

Batched Export with Automatic Flush

All exporters buffer data and flush automatically at the configured interval:

typescript
const exporter = new CloudWatchExporter({
  region: "us-east-1",
  batchSize: 20,       // 20 metrics per API call
  flushInterval: 60000, // flush every 60 seconds
});
 
// Add spans — auto-flushes when batch is full or interval fires
await exporter.exportSpans(spans);

Custom BaseExporter

Extend BaseExporter to build your own exporter:

typescript
import { BaseExporter, type ExportResult } from "@reaatech/llm-cost-telemetry-exporters";
import type { CostSpan, CostRecord } from "@reaatech/llm-cost-telemetry";
 
class DatadogExporter extends BaseExporter {
  async exportSpans(spans: CostSpan[]): Promise<ExportResult> {
    return this.exportWithRetry(async () => {
      // Push to Datadog
      return { success: true, count: spans.length };
    });
  }
 
  async exportRecords(records: CostRecord[]): Promise<ExportResult> {
    return this.exportWithRetry(async () => {
      return { success: true, count: records.length };
    });
  }
}

License

MIT