Observability Examples
Observability workflow examples for the Loopstack automation framework.
Workflow examples for tracking and enforcing operational limits.
Use in Your App
Copy this directory into your app, then install what it imports:
npm install @loopstack/common @loopstack/quotaRegister the module:
import { Module } from '@nestjs/common';import { LoopstackModule } from '@loopstack/loopstack-module';import { ObservabilityExamplesModule } from './observability/observability-examples.module';
@Module({ imports: [LoopstackModule.forRoot(), ObservabilityExamplesModule],})export class AppModule {}Examples
| Example | Studio title | Description |
|---|---|---|
| Quota | Observability - Quota Example |
Manual check + report usage with @loopstack/quota, Redis-backed when enabled |
| Tracing Interceptor | Observability - Tracing Interceptor Example |
Custom ToolInterceptor measuring every tool execution app-wide |
| Custom Quota Calculator | Observability - Custom Quota Calculator Example |
Custom ToolQuotaCalculator metering a tool automatically via QuotaInterceptor |
| Audit Log | Observability - Audit Log Example |
@OnEvent listener recording workflow & document lifecycle events |
Quota
Demonstrates the manual quota API of @loopstack/quota:
quotaClient.checkQuota(userId, quotaType)— verify available budget- Perform the (placeholder) operation if allowed
quotaClient.report(userId, quotaType, amount)— charge against the quota
When QuotaModule.forRoot({ enabled: false }), both calls no-op. Set enabled: true plus Redis connection options to enforce real limits. Note: with quota enabled, a user without a limit key in Redis is blocked by default.
Built-in quota types: llm-cost (LLM token cost in microcents) and processing-time-ms (tool execution time).
Files
quota-example.workflow.ts— workflow class
Tracing Interceptor
Demonstrates writing a custom ToolInterceptor:
@UseToolInterceptor({ priority: 10 })registers the class app-wide — the framework discovers it via NestJSDiscoveryService, no manual wiring- The interceptor wraps every tool call (all modules), measures duration, and records entries in an injectable
ToolTraceService - The workflow runs a few
SimulateWorkToolcalls, then filters the trace by its ownworkflowIdand renders a markdown table
Interceptors follow a chain pattern like NestJS interceptors: run logic before/after next(), transform results, short-circuit (caching), or catch errors. Lower priority runs first (outermost).
Files
tracing-example.workflow.ts— workflow classinterceptors/tracing.interceptor.ts— the customToolInterceptorservices/tool-trace.service.ts— injectable trace storetools/simulate-work.tool.ts— demo tool that sleeps for a configurable duration
Custom Quota Calculator
Demonstrates extending the quota system with a custom ToolQuotaCalculator:
WordsProcessedQuotaCalculatordefines quota typewords-processedand derives the charged amount from the tool result (word count)- The module registers it for
AnalyzeTextToolinonModuleInitviaQuotaCalculatorRegistry - The built-in
QuotaInterceptorthen checks the quota before and reports usage after everyAnalyzeTextToolexecution — the workflow just calls the tool, no manual check/report
This is the recommended pattern for metering tools: the workflow stays clean, enforcement lives in the interceptor.
Files
custom-calculator-example.workflow.ts— workflow classcalculators/words-processed.calculator.ts— the customToolQuotaCalculatortools/analyze-text.tool.ts— demo tool whose usage is metered
Audit Log
Demonstrates subscribing to framework events for monitoring:
- The framework dispatches lifecycle events on the
client.messagechannel — e.g.workflow.created,workflow.updated,document.created AuditListeneruses@OnEvent('client.message')to capture every event into an injectableAuditLogService(bounded in-memory store)- The workflow saves a few documents to generate events, then renders its own audit trail filtered by
workflowId
This is the event-driven counterpart to the tracing interceptor: interceptors wrap tool calls, event listeners observe workflow and document lifecycle. Swap the in-memory store for a database or metrics exporter in production.
Files
audit-log-example.workflow.ts— workflow classlisteners/audit.listener.ts— the@OnEventlistenerservices/audit-log.service.ts— injectable audit store
About
Author: Jakob Klippel
License: MIT