Extending BSB
Build custom plugins to extend BSB's capabilities. Create your own events, logging, configuration, and metrics implementations.
Plugin Types
BSB can be extended with four types of infrastructure plugins. Each plugin type has a specific base class and interface to implement.
Events Plugin
Route events between services. Implement RabbitMQ, Kafka, Redis Pub/Sub, or any message broker.
Extends BSBEventsLogging Plugin
Send logs to external systems. Implement Graylog, Elasticsearch, Datadog, or custom log aggregators.
Extends BSBLoggingConfig Plugin
Load configuration from external sources. Implement Consul, etcd, Vault, or custom config providers.
Extends BSBConfigMetrics Plugin
Export metrics to monitoring systems. Implement Prometheus, OpenTelemetry, StatsD, or custom collectors.
Extends BSBMetricsCreating an Events Plugin
An events plugin routes messages between services. Here's a skeleton for a RabbitMQ implementation:
import { BSBEvents, BSBEventsConstructor } from "@bettercorp/service-base";
import { Readable } from "node:stream";
import { DTrace } from "@bettercorp/service-base";
export class Plugin extends BSBEvents<null> {
private connection: any; // Your RabbitMQ connection
constructor(config: BSBEventsConstructor<null>) {
super(config);
}
public async init(trace: DTrace) {
// Connect to RabbitMQ
this.connection = await connect(process.env.RABBITMQ_URL);
this.log.info(trace, "Connected to RabbitMQ");
}
public async onBroadcast(
trace: DTrace,
pluginName: string,
event: string,
listener: (trace: DTrace, args: any[]) => Promise<void>
): Promise<void> {
// Subscribe to a fanout exchange
}
public async emitBroadcast(
trace: DTrace,
pluginName: string,
event: string,
args: any[]
): Promise<void> {
// Publish to a fanout exchange
}
public async onEvent(
trace: DTrace,
pluginName: string,
event: string,
listener: (trace: DTrace, args: any[]) => Promise<void>
): Promise<void> {
// Subscribe to a queue
}
public async emitEvent(
trace: DTrace,
pluginName: string,
event: string,
args: any[]
): Promise<void> {
// Publish to a queue
}
public async onReturnableEvent(
trace: DTrace,
pluginName: string,
event: string,
listener: (trace: DTrace, args: any[]) => Promise<any>
): Promise<void> {
// Subscribe to RPC queue
}
public async emitEventAndReturn(
trace: DTrace,
pluginName: string,
event: string,
timeoutSeconds: number,
args: any[]
): Promise<any> {
// Publish to RPC queue and wait for response
}
// Stream methods...
public async receiveStream(...) { }
public async sendStream(...) { }
public dispose() {
this.connection?.close();
}
}
Creating a Logging Plugin
A logging plugin receives log messages and sends them to an external system:
import { BSBLogging, BSBLoggingConstructor } from "@bettercorp/service-base";
import { DTrace, LogMeta } from "@bettercorp/service-base";
export class Plugin extends BSBLogging<null> {
constructor(config: BSBLoggingConstructor<null>) {
super(config);
}
public async debug<T extends string>(
plugin: string,
trace: DTrace,
message: T,
meta?: LogMeta<T>
): Promise<void> {
await this.sendToGraylog("debug", plugin, trace, message, meta);
}
public async info<T extends string>(
plugin: string,
trace: DTrace,
message: T,
meta?: LogMeta<T>
): Promise<void> {
await this.sendToGraylog("info", plugin, trace, message, meta);
}
public async warn<T extends string>(
plugin: string,
trace: DTrace,
message: T,
meta?: LogMeta<T>
): Promise<void> {
await this.sendToGraylog("warn", plugin, trace, message, meta);
}
public async error<T extends string>(
plugin: string,
trace: DTrace,
message: T,
errorOrMeta?: Error | LogMeta<T>,
meta?: LogMeta<T>
): Promise<void> {
await this.sendToGraylog("error", plugin, trace, message, meta);
}
private async sendToGraylog(level: string, ...args: any[]) {
// Send to Graylog GELF endpoint
}
}
Plugin Discovery
BSB discovers plugins in this order:
./src/plugins/- Local development plugins./lib/plugins/- Compiled plugins$BSB_PLUGIN_DIR/- External plugin directory (for Docker)node_modules/- npm-installed plugins
Name your plugin folder with the appropriate prefix: events-*, logging-*, config-*, or metrics-*.