Examples
This page provides practical examples of using Sentinel Guard in various scenarios and environments.
Basic Examples
Simple Application Monitoring
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
// Start monitoring
sentinel.startMonitoring({
interval: 30000,
maxConsecutiveErrors: 5,
});
console.log("Application monitoring started");
// Graceful shutdown
process.on("SIGINT", () => {
sentinel.stopMonitoring();
process.exit(0);
});
Manual Heartbeat
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
async function sendCustomHeartbeat() {
try {
const response = await sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
service: "user-service",
version: "2.1.0",
environment: process.env.NODE_ENV,
uptime: process.uptime(),
},
});
if (response.success) {
console.log("Heartbeat sent successfully");
} else {
console.error("Heartbeat failed");
}
} catch (error) {
console.error("Error sending heartbeat:", error);
}
}
// Send heartbeat every 60 seconds
setInterval(sendCustomHeartbeat, 60000);
Web Framework Integration
Express.js Application
import express from "express";
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const app = express();
const PORT = process.env.PORT || 3000;
// Initialize monitoring
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
// Middleware for health checks
app.use((req, res, next) => {
// Track request timing
const start = Date.now();
res.on("finish", () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.path} - ${duration}ms`);
});
next();
});
// Health check endpoint
app.get("/health", (req, res) => {
const isMonitoring = sentinel.isMonitoringActive();
const errorCount = sentinel.getErrorCount();
res.json({
status: "healthy",
monitoring: isMonitoring,
errors: errorCount,
uptime: process.uptime(),
timestamp: new Date().toISOString(),
});
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
// Start monitoring after server is ready
sentinel.startMonitoring({
interval: 45000,
maxConsecutiveErrors: 3,
});
console.log("Server monitoring started");
});
// Graceful shutdown
process.on("SIGTERM", () => {
console.log("Received SIGTERM, shutting down gracefully");
sentinel.stopMonitoring();
process.exit(0);
});
Fastify Application
import Fastify from "fastify";
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const fastify = Fastify({ logger: true });
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
// Health check route
fastify.get("/health", async (request, reply) => {
return {
status: "healthy",
monitoring: sentinel.isMonitoringActive(),
errors: sentinel.getErrorCount(),
uptime: process.uptime(),
};
});
// Start server
const start = async () => {
try {
await fastify.listen({ port: 3000 });
sentinel.startMonitoring({
interval: 30000,
maxConsecutiveErrors: 5,
});
console.log("Fastify server and monitoring started");
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
Database Integration
Prisma Integration
import { PrismaClient } from "@prisma/client";
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const prisma = new PrismaClient();
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
// Set up database monitoring
sentinel.setPrismaClient(prisma);
// Start monitoring with database latency tracking
sentinel.startMonitoring({
interval: 30000,
maxConsecutiveErrors: 5,
});
// Example API endpoint with database operation
async function getUserById(id: string) {
try {
const user = await prisma.user.findUnique({
where: { id },
});
// Send heartbeat with operation status
await sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
operation: "getUserById",
userId: id,
found: !!user,
},
});
return user;
} catch (error) {
// Send error heartbeat
await sentinel.sendHeartbeat({
status: "ERROR",
metadata: {
operation: "getUserById",
error: error.message,
},
});
throw error;
}
}
// Cleanup on shutdown
process.on("SIGINT", async () => {
await prisma.$disconnect();
sentinel.stopMonitoring();
process.exit(0);
});
Redis Integration
import { createClient } from "redis";
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const redis = createClient({
url: process.env.REDIS_URL,
});
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
async function initializeServices() {
// Connect to Redis
await redis.connect();
console.log("Redis connected");
// Set up Redis monitoring
sentinel.setRedisClient(redis);
// Start monitoring
sentinel.startMonitoring({
interval: 30000,
maxConsecutiveErrors: 5,
});
console.log("Services initialized with monitoring");
}
// Example cache operation with monitoring
async function getCachedData(key: string) {
try {
const data = await redis.get(key);
await sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
operation: "cache_get",
key,
hit: !!data,
},
});
return data;
} catch (error) {
await sentinel.sendHeartbeat({
status: "ERROR",
metadata: {
operation: "cache_get",
error: error.message,
},
});
throw error;
}
}
initializeServices();
Full Database Stack
import { PrismaClient } from "@prisma/client";
import { createClient } from "redis";
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const prisma = new PrismaClient();
const redis = createClient({ url: process.env.REDIS_URL });
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
class DatabaseService {
async initialize() {
await redis.connect();
console.log("Database services connected");
// Configure monitoring for both databases
sentinel.setPrismaClient(prisma);
sentinel.setRedisClient(redis);
sentinel.startMonitoring({
interval: 30000,
maxConsecutiveErrors: 3,
});
}
async getUserWithCache(id: string) {
const cacheKey = `user:${id}`;
try {
// Try cache first
const cached = await redis.get(cacheKey);
if (cached) {
await sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
operation: "getUserWithCache",
source: "cache",
userId: id,
},
});
return JSON.parse(cached);
}
// Fallback to database
const user = await prisma.user.findUnique({
where: { id },
});
if (user) {
// Cache the result
await redis.setex(cacheKey, 300, JSON.stringify(user));
}
await sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
operation: "getUserWithCache",
source: "database",
userId: id,
found: !!user,
},
});
return user;
} catch (error) {
await sentinel.sendHeartbeat({
status: "ERROR",
metadata: {
operation: "getUserWithCache",
error: error.message,
},
});
throw error;
}
}
async cleanup() {
await prisma.$disconnect();
await redis.disconnect();
sentinel.stopMonitoring();
}
}
const dbService = new DatabaseService();
dbService.initialize();
Error Handling
Comprehensive Error Handling
import {
SentinelGuard,
NetworkError,
AuthenticationError,
RateLimitError,
SentinelGuardError,
} from "@uptimebeacon/sentinel-guard";
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
retryConfig: {
maxRetries: 5,
baseDelay: 2000,
backoffMultiplier: 2,
},
});
async function robustHeartbeat(status: string, metadata?: any) {
try {
const response = await sentinel.sendHeartbeat({
status: status as any,
metadata,
});
return response;
} catch (error) {
if (error instanceof AuthenticationError) {
console.error("Authentication failed:", error.message);
// Handle authentication issues
process.exit(1);
} else if (error instanceof NetworkError) {
console.error("Network error:", error.message);
// Network issues - might be temporary
setTimeout(() => robustHeartbeat(status, metadata), 10000);
} else if (error instanceof RateLimitError) {
console.error("Rate limit exceeded:", error.message);
// Back off and retry later
setTimeout(() => robustHeartbeat(status, metadata), 60000);
} else if (error instanceof SentinelGuardError) {
console.error("Sentinel Guard error:", error.message);
} else {
console.error("Unknown error:", error);
}
throw error;
}
}
// Monitor error rates
let errorCount = 0;
let successCount = 0;
setInterval(async () => {
try {
await robustHeartbeat("ONLINE", {
errorRate: errorCount / (errorCount + successCount),
totalRequests: errorCount + successCount,
});
successCount++;
} catch (error) {
errorCount++;
}
}, 30000);
Retry Logic Example
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
const sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
class RetryableService {
private maxRetries = 3;
private retryDelay = 1000;
async sendHeartbeatWithRetry(data: any, attempt = 1): Promise<any> {
try {
return await sentinel.sendHeartbeat(data);
} catch (error) {
if (attempt < this.maxRetries) {
console.log(`Heartbeat failed (attempt ${attempt}), retrying...`);
await new Promise((resolve) =>
setTimeout(resolve, this.retryDelay * attempt),
);
return this.sendHeartbeatWithRetry(data, attempt + 1);
}
throw error;
}
}
}
const service = new RetryableService();
Advanced Use Cases
Microservices Architecture
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
class MicroserviceMonitor {
private sentinel: SentinelGuard;
private serviceName: string;
private serviceVersion: string;
constructor(serviceName: string, serviceVersion: string) {
this.serviceName = serviceName;
this.serviceVersion = serviceVersion;
this.sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
}
async startMonitoring() {
this.sentinel.startMonitoring({
interval: 30000,
maxConsecutiveErrors: 5,
});
// Send initial heartbeat with service info
await this.sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
service: this.serviceName,
version: this.serviceVersion,
environment: process.env.NODE_ENV,
instance: process.env.INSTANCE_ID,
startup: new Date().toISOString(),
},
});
}
async reportOperation(operation: string, success: boolean, duration: number) {
await this.sentinel.sendHeartbeat({
status: success ? "ONLINE" : "ERROR",
metadata: {
service: this.serviceName,
operation,
success,
duration,
timestamp: new Date().toISOString(),
},
});
}
async reportHealthCheck(checks: Record<string, boolean>) {
const allHealthy = Object.values(checks).every(Boolean);
await this.sentinel.sendHeartbeat({
status: allHealthy ? "ONLINE" : "ERROR",
metadata: {
service: this.serviceName,
healthChecks: checks,
overallHealth: allHealthy,
},
});
}
}
// Usage
const monitor = new MicroserviceMonitor("user-service", "1.2.3");
monitor.startMonitoring();
Background Job Processing
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
class JobProcessor {
private sentinel: SentinelGuard;
private activeJobs = new Map<string, Date>();
constructor() {
this.sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
this.sentinel.startMonitoring({
interval: 60000, // Check every minute
maxConsecutiveErrors: 3,
});
}
async processJob(jobId: string, jobData: any) {
const startTime = new Date();
this.activeJobs.set(jobId, startTime);
try {
// Simulate job processing
await this.doWork(jobData);
const duration = Date.now() - startTime.getTime();
await this.sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
jobId,
duration,
status: "completed",
activeJobs: this.activeJobs.size,
},
});
this.activeJobs.delete(jobId);
} catch (error) {
await this.sentinel.sendHeartbeat({
status: "ERROR",
metadata: {
jobId,
error: error.message,
status: "failed",
activeJobs: this.activeJobs.size,
},
});
this.activeJobs.delete(jobId);
throw error;
}
}
private async doWork(data: any) {
// Simulate work
await new Promise((resolve) => setTimeout(resolve, 1000));
}
async reportQueueStatus(queueSize: number) {
await this.sentinel.sendHeartbeat({
status: queueSize > 100 ? "HIGH_LATENCY" : "ONLINE",
metadata: {
queueSize,
activeJobs: this.activeJobs.size,
processingRate: this.calculateProcessingRate(),
},
});
}
private calculateProcessingRate(): number {
// Calculate jobs processed per minute
return 0; // Simplified
}
}
Scheduled Tasks
import { SentinelGuard } from "@uptimebeacon/sentinel-guard";
import cron from "node-cron";
class ScheduledTaskMonitor {
private sentinel: SentinelGuard;
constructor() {
this.sentinel = new SentinelGuard({
apiKey: process.env.SENTINEL_API_KEY!,
baseUrl: process.env.SENTINEL_API_URL!,
monitorApiKey: process.env.SENTINEL_MONITOR_API_KEY!,
});
this.sentinel.startMonitoring({
interval: 120000, // 2 minutes
maxConsecutiveErrors: 2,
});
}
setupTasks() {
// Daily backup task
cron.schedule("0 2 * * *", async () => {
await this.runTask("daily-backup", this.performBackup);
});
// Hourly cleanup task
cron.schedule("0 * * * *", async () => {
await this.runTask("hourly-cleanup", this.performCleanup);
});
// Health check every 5 minutes
cron.schedule("*/5 * * * *", async () => {
await this.runTask("health-check", this.performHealthCheck);
});
}
private async runTask(taskName: string, taskFn: () => Promise<void>) {
const startTime = Date.now();
try {
await taskFn();
const duration = Date.now() - startTime;
await this.sentinel.sendHeartbeat({
status: "ONLINE",
metadata: {
task: taskName,
duration,
status: "completed",
timestamp: new Date().toISOString(),
},
});
} catch (error) {
await this.sentinel.sendHeartbeat({
status: "ERROR",
metadata: {
task: taskName,
error: error.message,
status: "failed",
timestamp: new Date().toISOString(),
},
});
}
}
private async performBackup() {
// Backup logic
console.log("Performing backup...");
}
private async performCleanup() {
// Cleanup logic
console.log("Performing cleanup...");
}
private async performHealthCheck() {
// Health check logic
console.log("Performing health check...");
}
}
const taskMonitor = new ScheduledTaskMonitor();
taskMonitor.setupTasks();
Docker Integration
Docker Compose Example
version: "3.8"
services:
app:
build: .
environment:
- SENTINEL_API_KEY=${SENTINEL_API_KEY}
- SENTINEL_API_URL=${SENTINEL_API_URL}
- SENTINEL_MONITOR_API_KEY=${SENTINEL_MONITOR_API_KEY}
- NODE_ENV=production
depends_on:
- postgres
- redis
ports:
- "3000:3000"
postgres:
image: postgres:15
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
redis:
image: redis:7-alpine
ports:
- "6379:6379"
Dockerfile with Monitoring
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Build the application
RUN npm run build
# Health check endpoint
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["npm", "start"]
Next Steps
- Performance Monitoring - Learn about database monitoring
- Troubleshooting - Resolve common issues
- Configuration - Advanced configuration options