NestJS Profiler
API Reference

nest-profiler-rabbitmq

Types and API of the RabbitMQ message collectors.

The package ships two independent modules: RabbitMqCollectorModule profiles the messages the application consumes (one profile per @RabbitSubscribe delivery), and RabbitMqPublishCollectorModule lists the messages it publishes in a RabbitMQ panel.

RabbitMqInfo

Payload of a message profile's entrypoint.data (entrypoint type: 'rabbitmq'). The module registers a rabbitmq entrypoint type, so the profiler renders a dedicated RabbitMQ list table

  • with its own filters: Delivery (first delivery / redelivered), Exchange and Handler (both populated from the values actually captured) and a free-text Routing key - and a Message detail tab, including the captured RabbitMQ headers and payload. The HTTP-status filters do not appear here, since a consumed message has no HTTP response.

Prop

Type

RabbitMqPublishEntry

One row of the RabbitMQ panel — a message the profiled request published through AmqpConnection.publish. Collected by RabbitMqPublishCollectorModule.

Prop

Type

Public exports

import { RabbitMqCollectorModule } from '@eleven-labs/nest-profiler-rabbitmq';
import { RabbitMqContextAdapter } from '@eleven-labs/nest-profiler-rabbitmq';
import {
  RABBITMQ_ENTRYPOINT_TYPE,
  RABBITMQ_ENTRYPOINT_TYPE_DEF,
  buildRabbitMqEntrypointType,
} from '@eleven-labs/nest-profiler-rabbitmq';
import { RabbitMqPublishCollectorModule } from '@eleven-labs/nest-profiler-rabbitmq';
import { RabbitMqPublishCollector } from '@eleven-labs/nest-profiler-rabbitmq';
import { RabbitMqDiscoverSource } from '@eleven-labs/nest-profiler-rabbitmq';

import type { RabbitMqCollectorModuleOptions } from '@eleven-labs/nest-profiler-rabbitmq';
import type { RabbitMqCollectorModuleAsyncOptions } from '@eleven-labs/nest-profiler-rabbitmq';
import type { RabbitMqInfo } from '@eleven-labs/nest-profiler-rabbitmq';
import type { RabbitMqPublishEntry } from '@eleven-labs/nest-profiler-rabbitmq';
import type { RabbitMqPublishCollectorModuleOptions } from '@eleven-labs/nest-profiler-rabbitmq';
import type { RabbitMqPublishCollectorModuleAsyncOptions } from '@eleven-labs/nest-profiler-rabbitmq';

RabbitMqCollectorModuleOptions

interface RabbitMqCollectorModuleOptions {
  /** Capture incoming RabbitMQ message headers (masked). Default: `true`. */
  captureHeaders?: boolean;
  /** Capture the deserialized message payload. Default: `true`. */
  captureBody?: boolean;
  /** Extra header names (lowercase) to mask, merged with the built-in list. */
  maskHeaders?: string[];
  /** What counts as a failed message. Default: the handler threw. */
  error?: ProfilerErrorOptions;
}

A consumed message carries no status code, so error rests on whether the handler threw — narrow it to the exceptions that matter, or take over with classify. See What counts as an error.

Gate the module per environment with ConditionalModule.registerWhen(RabbitMqCollectorModule.forRoot({ … }), isProfilerEnabled) — the same pattern used for every profiler module.

RabbitMqPublishCollectorModuleOptions

interface RabbitMqPublishCollectorModuleOptions {
  /** Capture the headers passed to `publish()` (masked). Default: `true`. */
  captureHeaders?: boolean;
  /** Capture the published message. Default: `true`. */
  captureBody?: boolean;
  /** Extra header names (lowercase) to mask, merged with the built-in list. */
  maskHeaders?: string[];
  /** Depth / size caps on the captured payload, forwarded to `toSafeData`. */
  payloadLimits?: SafeDataOptions;
  /** A publish at or above this duration (ms) is tagged `slow`. Default: `50`. */
  slowThreshold?: number;
  /** Identical publishes repeated this many times are tagged `n-plus-one`. Default: `2`. */
  nPlusOneThreshold?: number;
  /** A profile publishing this many messages is tagged `chatty`. Default: `10`. */
  chattyThreshold?: number;
  /** Severities of the `slow` / `n-plus-one` / `chatty` tags. */
  slowSeverity?: TagSeverity;
  nPlusOneSeverity?: TagSeverity;
  chattySeverity?: TagSeverity;
  /** What counts as a failed publish. Default: `publish()` rejected. */
  error?: EntryErrorOptions;
}

A publish carries no status code either, so error rests on publish() having rejected; a message the channel buffered (accepted: false) is a warning, not a failure.

Registering the module is enough — publishers keep injecting AmqpConnection unchanged, and AmqpConnection.request() (RPC) is captured too, since golevelup routes it through publish.

app.module.ts
ConditionalModule.registerWhen(RabbitMqPublishCollectorModule.forRoot(), isProfilerEnabled);

Setup — consuming

Register the module in the application that consumes your messages (the same process that hosts the profiler):

app.module.ts
import { Module } from '@nestjs/common';
import { ConditionalModule } from '@nestjs/config';
import { RabbitMqCollectorModule } from '@eleven-labs/nest-profiler-rabbitmq';

const isProfilerEnabled = (env: NodeJS.ProcessEnv) => env['PROFILER_ENABLED'] === 'true';

@Module({
  imports: [
    ConditionalModule.registerWhen(RabbitMqCollectorModule.forRoot(), isProfilerEnabled),
    // your RabbitMQModule with @RabbitSubscribe handlers
  ],
})
export class AppModule {}

Drive the options from ConfigService (or any provider) with forRootAsync(), gated per environment with ConditionalModule (recommended) — it resolves option values only, not enabled (see Enabling and disabling the profiler):

import { ConditionalModule, ConfigService } from '@nestjs/config';

ConditionalModule.registerWhen(
  RabbitMqCollectorModule.forRootAsync({
    inject: [ConfigService],
    useFactory: (config: ConfigService) => ({
      captureBody: config.get<boolean>('profiler.rabbitmqCaptureBody') ?? true,
      maskHeaders: config.get<string[]>('profiler.maskHeaders') ?? [],
    }),
  }),
  isProfilerEnabled,
);

Wire the core ProfilerModule once at the root — see Enabling and disabling the profiler. If a service injects TracerService directly, also register its ProfilerNoopModule fallback.

@golevelup/nestjs-rabbitmq and amqplib are optional peer dependencies - the ones you already install to talk to the broker. Neither module needs changes to your @RabbitSubscribe handlers or your publishers.

Setup — publishing

RabbitMqPublishCollectorModule stands alone: a publish-only API registers it and nothing else from this package. It patches AmqpConnection.prototype.publish and records the calls made while a profile is active, so a publish outside a profiled request (at bootstrap, from a cron job) records nothing.

app.module.ts
import { Module } from '@nestjs/common';
import { ConditionalModule } from '@nestjs/config';
import { RabbitMqPublishCollectorModule } from '@eleven-labs/nest-profiler-rabbitmq';

@Module({
  imports: [
    ConditionalModule.registerWhen(RabbitMqPublishCollectorModule.forRoot(), isProfilerEnabled),
    // your RabbitMQModule.forRoot(...)
  ],
})
export class AppModule {}

The panel is profile-scoped, so it works under any entrypoint: an HTTP request, a CLI command, or a consumed message when RabbitMqCollectorModule is registered too — which is how the messages a consumer republishes show up.

How a message profile is shaped

A consumed message has no HTTP request/response. The profiler synthesises a profile whose entrypoint is { type: 'rabbitmq', data: RabbitMqInfo }:

FieldValue
entrypoint.typerabbitmq
entrypoint.data.exchangeThe exchange (empty string for the default exchange)
entrypoint.data.routingKeyThe routing key
entrypoint.data.headersRabbitMQ message headers, sensitive ones masked (when captureHeaders is enabled)
entrypoint.data.payloadThe deserialized payload (when captureBody is enabled)
response.statusCode200 on success, 500 when the handler threw

The exchange, routing key, handler, redelivered flag and RabbitMQ consumer/delivery tags are kept on entrypoint.data. Because the handler runs inside the profiler's CLS context, profile-scoped collectors (HTTP client, database, …) capture the work it performs and contribute their own panels.

The Discover / RabbitMQ view

RabbitMqCollectorModule also registers a ProfilerDiscoverSource (RabbitMqDiscoverSource), which contributes the Discover / RabbitMQ view — visible when @eleven-labs/nest-profiler-routes is installed. It reports what the application declared at startup, read from the resolved RabbitMQModule configuration: no management-API call, no extra credentials, and it stays accurate while the broker is unreachable.

The topology, as sections above the handler list:

SectionWhat it lists
ConnectionsEvery declared connection with its broker URI (credentials masked), prefetch, channels and handler configs
ExchangesEach exchange with its type, durability flags and arguments
QueuesEach queue with the binding that feeds it (← exchange (routing keys)), its flags and its x-… arguments
Exchange bindingsEach exchangeBindings entry with its pattern

Queues no handler consumes — dead-letter, retry and delay queues — are listed too: they are part of the flow even though nothing subscribes to them.

The handlers, one entry per registration golevelup performs, each expanding to the full subscription rather than just its exchange → routingKey locator:

GroupWhat it lists
Subscriptionqueue, exchange, routingKey, the connection it runs on, its module-level handler config and channel
BindingsEach bindings: [{ exchange, routingKey }] pair, when the handler binds across exchanges
Queue optionsThe queueOptions it asserts, with arguments spread one x-… key per row
BehaviourallowNonJsonMessages, errorBehavior, batchOptions, a custom deserializer, …

Two golevelup behaviours the view makes visible: a handler with no connection is registered on every declared connection (listed once per connection — the classic multi-vhost trap), and a handler whose name matches no entry in that connection's handlers map is not registered at all, which the entry states in place of its description.

Powered & maintained by

On this page