instrumentation.ts
It's easy to add observability to your indexer using our native instrumentation powered by OpenTelemetry.
Convention
To add instrumentation to your project, create a instrumentation.ts
file at the root (next to apibara.config.ts
).
This file should export a register
function, this function is called once by the runtime before the production indexer is started.
import type { RegisterFn } from "apibara/types";
export const register: RegisterFn = async () => {
// Setup OpenTelemetry SDK exporter
};
Logger
You can also replace the default logger by exporting a logger
function from instrumentation.ts
. This function should return a console
-like object with the same methods as console
.
import type { LoggerFactoryFn } from "apibara/types";
export const logger: LoggerFactoryFn = ({ indexer, indexers, preset }) => {
// Build console here.
};
Examples
OpenTelemetry with OpenTelemetry Collector
The OpenTelemetry Collector offers a vendor-agnostic implementation for receiving, processing, and exporting telemetry data. Using the collector with Apibara allows you to collect and send both metrics and traces to your preferred observability backend.
1. Install required dependencies
First, install the required OpenTelemetry packages:
pnpm install @opentelemetry/api @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-metrics-otlp-grpc @opentelemetry/exporter-trace-otlp-grpc @opentelemetry/resources @opentelemetry/sdk-node @opentelemetry/sdk-metrics @opentelemetry/sdk-trace-node @opentelemetry/semantic-conventions
2. Update instrumentation.ts to use the OpenTelemetry Collector
Create or update the instrumentation.ts
file at the root of your project:
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
import {
defaultResource,
resourceFromAttributes,
} from "@opentelemetry/resources";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { NodeSDK } from "@opentelemetry/sdk-node";
import { SimpleSpanProcessor } from "@opentelemetry/sdk-trace-node";
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from "@opentelemetry/semantic-conventions";
import type { RegisterFn } from "apibara/types";
export const register: RegisterFn = async () => {
// Create a resource that identifies your service
const resource = defaultResource().merge(
resourceFromAttributes({
[ATTR_SERVICE_NAME]: "apibara",
[ATTR_SERVICE_VERSION]: "1.0.0",
})
);
const collectorOptions = {
// configure the grpc endpoint of the opentelemetry-collector
url: "http://localhost:4317",
};
// Configure the OTLP exporter for metrics using grpc protocol,
const metricExporter = new OTLPMetricExporter(collectorOptions);
const metricReader = new PeriodicExportingMetricReader({
exporter: metricExporter,
exportIntervalMillis: 1000,
});
// Configure the OTLP exporter for traces using grpc protocol,
const traceExporter = new OTLPTraceExporter(collectorOptions);
const spanProcessors = [new SimpleSpanProcessor(traceExporter)];
// Configure the SDK
const sdk = new NodeSDK({
resource,
spanProcessors,
metricReader,
instrumentations: [getNodeAutoInstrumentations()],
});
// Start the SDK
sdk.start();
};
3. Build and run your indexer to see the metrics and traces on the configured OpenTelemetry Collector.
pnpm build
pnpm start --indexer=your-indexer
The following metrics are available out of the box:
current_block
: The latest block number being processed by the indexerprocessed_blocks_total
: Total number of blocks that have been processedreorgs_total
: Number of chain reorganizations detected and handled
Additionally, you can observe detailed traces showing:
- Block processing lifecycle and duration
- Individual transform function execution time
- Chain reorganization handling
Prometheus
Collecting metrics with Prometheus and visualizing them is a powerful way to monitor your indexers. This section shows how to set up OpenTelemetry with Prometheus.
1. Install required dependencies
First, install the required OpenTelemetry packages:
pnpm install @opentelemetry/api @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-prometheus @opentelemetry/resources @opentelemetry/sdk-node @opentelemetry/semantic-conventions
2. Update instrumentation.ts to use the OpenTelemetry SDK
Update the instrumentation.ts
file at the root of your project:
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
import {
defaultResource,
resourceFromAttributes,
} from "@opentelemetry/resources";
import { NodeSDK } from "@opentelemetry/sdk-node";
import {
ATTR_SERVICE_NAME,
ATTR_SERVICE_VERSION,
} from "@opentelemetry/semantic-conventions";
import type { RegisterFn } from "apibara/types";
export const register: RegisterFn = async () => {
// Create a resource that identifies your service
const resource = defaultResource().merge(
resourceFromAttributes({
[ATTR_SERVICE_NAME]: "apibara",
[ATTR_SERVICE_VERSION]: "1.0.0",
})
);
// By default port 9464 will be exposed on the apibara app
const prometheusExporter = new PrometheusExporter();
// Configure the SDK
const sdk = new NodeSDK({
resource,
metricReader: prometheusExporter,
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
};
3. Build and run your indexer to see the metrics and traces on your configured observability platform.
pnpm build
pnpm start --indexer=your-indexer
Sentry
1. Install required dependencies
First, install the required Sentry package:
pnpm install @sentry/node
2. Update instrumentation.ts to use Sentry
Update the instrumentation.ts
file at the root of your project:
import * as Sentry from "@sentry/node";
import type { RegisterFn } from "apibara/types";
export const register: RegisterFn = async () => {
Sentry.init({
dsn: "__YOUR_DSN__",
tracesSampleRate: 1.0,
});
};
3. Build and run your indexer with Sentry error tracking enabled
pnpm build
pnpm start --indexer=your-indexer
The Sentry SDK uses OpenTelemetry under the hood, which means any OpenTelemetry instrumentation that emits spans will automatically be picked up by Sentry without additional configuration.
For more information on how to use Sentry with OpenTelemetry, refer to the Sentry documentation.