Caching, scheduling, service discovery, logging implementations, and configuration utilities for Backstage backend infrastructure.
Caching services with support for multiple backends including Redis, Memcache, and in-memory storage.
/**
* Cache manager providing caching capabilities with multiple backends
*/
class CacheManager {
constructor(options?: CacheManagerOptions);
/**
* Get cache client with specified options
* @param options - Cache configuration options
* @returns Promise resolving to cache client instance
*/
getClient(options?: CacheManagerOptions): Promise<CacheClient>;
}
interface CacheManagerOptions {
defaultTtl?: number;
useCompression?: boolean;
connection?: string;
store?: 'memory' | 'redis' | 'memcache' | 'valkey';
}
interface CacheClient {
get(key: string): Promise<JsonValue | undefined>;
set(key: string, value: JsonValue, options?: CacheSetOptions): Promise<void>;
delete(key: string): Promise<void>;
has(key: string): Promise<boolean>;
}
interface CacheSetOptions {
ttl?: number;
}Host-based service discovery for locating and connecting to other services.
/**
* Host-based service discovery implementation
*/
class HostDiscovery implements DiscoveryService {
constructor(options: HostDiscoveryOptions);
/**
* Get the base URL for a service
* @param serviceId - Unique identifier for the service
* @returns Promise resolving to the service's base URL
*/
getBaseUrl(serviceId: string): Promise<string>;
/**
* Get external base URL for a service (for client-side access)
* @param serviceId - Unique identifier for the service
* @returns Promise resolving to the service's external URL
*/
getExternalBaseUrl(serviceId: string): Promise<string>;
}
interface HostDiscoveryOptions {
/**
* Base path for service discovery
*/
basePath?: string;
/**
* Specific endpoint configurations
*/
endpoints?: HostDiscoveryEndpoint[];
}
interface HostDiscoveryEndpoint {
service: string;
host: string;
port?: number;
path?: string;
}Task scheduling service with cron-like scheduling capabilities.
/**
* Default implementation factory for scheduler service
*/
class DefaultSchedulerService {
/**
* Creates a SchedulerService instance with the provided configuration
* @param options - Configuration options for creating the scheduler service
* @returns A SchedulerService instance ready for task scheduling
*/
static create(options: {
database: DatabaseService;
logger: LoggerService;
rootLifecycle: RootLifecycleService;
httpRouter: HttpRouterService;
pluginMetadata: PluginMetadataService;
}): SchedulerService;
}Winston-based logging implementations with structured logging support.
/**
* Winston-based logger implementation
*/
class WinstonLogger implements Logger {
constructor(options: WinstonLoggerOptions);
/**
* Log an info message
* @param message - Log message
* @param meta - Additional metadata
*/
info(message: string, meta?: LogMeta): void;
/**
* Log a warning message
* @param message - Log message
* @param meta - Additional metadata
*/
warn(message: string, meta?: LogMeta): void;
/**
* Log an error message
* @param message - Log message
* @param meta - Additional metadata
*/
error(message: string, meta?: LogMeta): void;
/**
* Log a debug message
* @param message - Log message
* @param meta - Additional metadata
*/
debug(message: string, meta?: LogMeta): void;
/**
* Create a child logger with additional context
* @param fields - Additional fields for child logger
* @returns Child logger instance
*/
child(fields: LogMeta): Logger;
}
interface WinstonLoggerOptions {
level?: 'error' | 'warn' | 'info' | 'debug';
format?: 'json' | 'colorize';
defaultMeta?: LogMeta;
}
type LogMeta = Record<string, unknown>;Configuration utilities and secret enumeration for secure configuration handling.
/**
* Creates an enumerator for configuration secrets
* @param options - Secret enumeration options
* @returns Function to enumerate secrets in configuration
*/
function createConfigSecretEnumerator(
options?: ConfigSecretEnumeratorOptions
): ConfigSecretEnumerator;
interface ConfigSecretEnumeratorOptions {
substitute?: boolean;
}
type ConfigSecretEnumerator = (
config: Config,
context: ConfigSecretContext
) => ConfigSecretEntry[];
interface ConfigSecretContext {
visibility: ConfigVisibility[];
}
interface ConfigSecretEntry {
key: string;
value?: string;
}
interface RootConfigFactoryOptions {
remote?: {
reloadIntervalSeconds?: number;
};
}Cache Management:
import { CacheManager } from "@backstage/backend-defaults/cache";
const cacheManager = new CacheManager({
store: 'redis',
connection: 'redis://localhost:6379',
defaultTtl: 3600 // 1 hour
});
const cache = await cacheManager.getClient();
// Cache operations
await cache.set('user:123', { name: 'John', role: 'admin' }, { ttl: 1800 });
const user = await cache.get('user:123');
const exists = await cache.has('user:123');
await cache.delete('user:123');Service Discovery:
import { HostDiscovery } from "@backstage/backend-defaults/discovery";
const discovery = new HostDiscovery({
basePath: '/api',
endpoints: [
{
service: 'catalog',
host: 'catalog-service',
port: 7007
},
{
service: 'scaffolder',
host: 'scaffolder-service',
port: 7007,
path: '/scaffolder'
}
]
});
// Get service URLs
const catalogUrl = await discovery.getBaseUrl('catalog');
const publicCatalogUrl = await discovery.getExternalBaseUrl('catalog');
console.log(catalogUrl); // http://catalog-service:7007/api
console.log(publicCatalogUrl); // https://backstage.company.com/apiTask Scheduling:
import { DefaultSchedulerService } from "@backstage/backend-defaults/scheduler";
import { Duration } from "luxon";
const scheduler = new DefaultSchedulerService();
// Schedule a recurring task
const task = await scheduler.scheduleTask(
{
frequency: Duration.fromObject({ minutes: 30 }),
initialDelay: Duration.fromObject({ seconds: 10 }),
timeout: Duration.fromObject({ minutes: 5 })
},
async ({ signal }) => {
console.log('Running scheduled task...');
// Check for cancellation
if (signal.aborted) {
console.log('Task was cancelled');
return;
}
// Perform task work
await performBackgroundWork();
console.log('Task completed');
},
{
id: 'data-sync-task',
scope: 'global'
}
);
// Manually trigger task
await scheduler.triggerTask('data-sync-task');
// Get task info
const taskInfo = await scheduler.getScheduledTask('data-sync-task');
console.log('Next run:', taskInfo.nextExecutionTime);Winston Logger:
import { WinstonLogger } from "@backstage/backend-defaults/rootLogger";
const logger = new WinstonLogger({
level: 'info',
format: 'json',
defaultMeta: {
service: 'my-plugin',
version: '1.0.0'
}
});
// Basic logging
logger.info('Application started');
logger.warn('Configuration missing', { key: 'database.host' });
logger.error('Database connection failed', {
error: error.message,
attempts: 3
});
// Child logger with additional context
const requestLogger = logger.child({
requestId: 'req-123',
userId: 'user:default/john'
});
requestLogger.info('Processing request');
requestLogger.debug('Query executed', {
sql: 'SELECT * FROM entities',
duration: 45
});Configuration Secret Enumeration:
import { createConfigSecretEnumerator } from "@backstage/backend-defaults/rootConfig";
const secretEnumerator = createConfigSecretEnumerator({
substitute: true
});
const secrets = secretEnumerator(backstageConfig, {
visibility: ['frontend', 'backend']
});
// Process detected secrets
secrets.forEach(secret => {
console.log(`Found secret at key: ${secret.key}`);
if (secret.value) {
console.log(`Value: ${secret.value.substring(0, 4)}...`);
}
});interface Logger {
info(message: string, meta?: LogMeta): void;
warn(message: string, meta?: LogMeta): void;
error(message: string, meta?: LogMeta): void;
debug(message: string, meta?: LogMeta): void;
child(fields: LogMeta): Logger;
}
interface DiscoveryService {
getBaseUrl(serviceId: string): Promise<string>;
getExternalBaseUrl(serviceId: string): Promise<string>;
}
interface SchedulerService {
scheduleTask(
schedule: ScheduleTaskScheduleDefinition,
fn: ScheduleTaskFunction,
options?: ScheduleTaskOptions
): Promise<ScheduledTask>;
triggerTask(id: string): Promise<void>;
getScheduledTask(id: string): Promise<ScheduledTask>;
}
interface Config {
get(key?: string): JsonValue;
getOptional(key?: string): JsonValue | undefined;
has(key: string): boolean;
keys(): string[];
}
interface ConfigVisibility {
[key: string]: unknown;
}
type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
interface JsonObject { [key: string]: JsonValue; }
interface JsonArray extends Array<JsonValue> {}
type Duration = {
as(unit: string): number;
toISO(): string;
};