Skip to content

Monitoring ​

Lifecycle Events ​

Audit hooks are plain callbacks in the plugin options — fire-and-forget, failures are logged and never break a request:

typescript
import { Module } from '@nestjs/common';
import { RedisModule } from '@nestjs-redisx/core';
import { SessionPlugin } from '@nestjs-redisx/session';

@Module({
  imports: [
    RedisModule.forRoot({
      clients: { host: 'localhost', port: 6379 },
      plugins: [
        new SessionPlugin({
          // Audit hooks: fire-and-forget, failures are logged and never break
          // the request. Ship them to your audit log / SIEM.
          events: {
            onCreated: ({ sessionId, userId }) => console.log('session created', sessionId, userId),
            onDestroyed: ({ sessionId, userId }) => console.log('logout', sessionId, userId),
            onRevoked: ({ sessionId, userId }) => console.log('revoked/evicted', sessionId, userId),
            onExpiredByCap: ({ sessionId, userId }) => console.log('lifetime cap hit', sessionId, userId),
          },
        }),
      ],
    }),
  ],
})
export class AppModule {}
EventFires when
onCreatedA session is written for the first time
onDestroyedA session ends through the middleware (logout)
onRevokedA session is revoked via the service API or evicted by a seat limit
onExpiredByCapThe absolute lifetime cap catches a live session on access

Each callback receives { sessionId, userId? }. The audit log itself is your application's job — these hooks are the wiring point (write to your SIEM, publish via the Pub/Sub plugin, etc.).

Natural expiry

Sessions that expire by TTL simply vanish from Redis — there is no callback for them (Redis has no reliable expiry hooks). Counts stay accurate because indexes are swept by expiry score on read.

Prometheus Metrics ​

When MetricsPlugin is registered, the session store increments counters automatically (soft dependency — nothing to configure):

MetricLabelsMeaning
redisx_session_created_total—Sessions written for the first time
redisx_session_destroyed_totalreason: destroyed | revoked | expired-by-capSessions removed, by cause
redisx_session_limit_rejections_total—Logins refused by the reject seat-limit policy

An active-sessions gauge is deliberately not emitted — it would drift as sessions expire server-side. For dashboards, expose count() from your own endpoint:

typescript
@Get('metrics/sessions')
async sessionCount() {
  return { active: await this.sessions.count() };
}

Example PromQL ​

promql
# Logins per minute
rate(redisx_session_created_total[1m]) * 60

# Forced logouts (revocations + evictions) per hour
increase(redisx_session_destroyed_total{reason="revoked"}[1h])

# Seat-limit pressure
rate(redisx_session_limit_rejections_total[5m])

Released under the MIT License.