Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ihfaz297/MND/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Monitoring the MND system ensures reliability, tracks API quota usage, and helps identify issues before they affect users.

Health Check Endpoint

The backend exposes a health check endpoint for uptime monitoring.

Endpoint

GET /api/health

Response

{
  "status": "ok",
  "uptime": 12345.67,
  "timestamp": "2026-03-05T10:30:00.000Z"
}

Implementation

In src/api/routesController.ts:
export function healthCheck(req: Request, res: Response) {
  res.json({
    status: 'ok',
    uptime: process.uptime(),
    timestamp: new Date().toISOString()
  });
}

Monitoring Services

Use these services to ping /api/health periodically: UptimeRobot (Free tier):
  • Monitor up to 50 endpoints
  • 5-minute interval checks
  • Email/SMS alerts
Setup:
  1. Go to uptimerobot.com
  2. Add New Monitor
  3. Type: HTTP(s)
  4. URL: https://yourdomain.com/api/health
  5. Interval: 5 minutes
  6. Add alert contacts
Better Uptime:
  • 3-minute interval
  • Incident management
  • Status page
Pingdom:
  • 1-minute interval
  • Performance monitoring
  • Real user monitoring

API Usage Tracking

The Distance Matrix client includes built-in usage tracking.

Usage Statistics

Access stats via the singleton instance:
import { distanceMatrixClient } from './infra/distanceMatrixClient';

const stats = distanceMatrixClient.getStats();
console.log(stats);
Output:
{
  monthlyCount: 45,
  dailyCount: 12,
  lastReset: '2026-03-05',
  cacheHits: 234,
  cacheMisses: 45
}
distanceMatrixClient.printStats();
Console output:
📊 Distance Matrix Usage:
  Monthly: 45/700
  Daily: 12/50
  Cache hits: 234
  Cache misses: 45
  Cache size: 156 entries

Usage Limits

Configured in src/infra/distanceMatrixClient.ts:
private readonly MONTHLY_LIMIT = 700;
private readonly DAILY_LIMIT = 50;
private readonly CACHE_TTL_DAYS = 7;

Quota Warnings

The client logs warnings when approaching limits:
if (this.usageStats.monthlyCount >= this.MONTHLY_LIMIT) {
  console.warn(`⚠️  Monthly limit reached (${this.MONTHLY_LIMIT})`);
  return {
    ok: false,
    errorMessage: 'Monthly API quota exceeded'
  };
}

Distance Matrix Quota Management

Google Distance Matrix API has strict quota limits.

Free Tier Limits

  • $200 free credit/month = ~700 requests
  • After that: $5-10 per 1000 requests

Quota Monitoring Endpoint

Create an endpoint to expose quota stats:
// src/api/routesController.ts
export function getQuotaStats(req: Request, res: Response) {
  const stats = distanceMatrixClient.getStats();
  
  res.json({
    quota: {
      monthly: {
        used: stats.monthlyCount,
        limit: 700,
        remaining: 700 - stats.monthlyCount,
        percentage: Math.round((stats.monthlyCount / 700) * 100)
      },
      daily: {
        used: stats.dailyCount,
        limit: 50,
        remaining: 50 - stats.dailyCount
      },
      cache: {
        hits: stats.cacheHits,
        misses: stats.cacheMisses,
        hitRate: stats.cacheHits / (stats.cacheHits + stats.cacheMisses)
      }
    },
    lastReset: stats.lastReset
  });
}

// Add to server.ts
app.get('/api/quota', getQuotaStats);
Response:
{
  "quota": {
    "monthly": {
      "used": 45,
      "limit": 700,
      "remaining": 655,
      "percentage": 6
    },
    "daily": {
      "used": 12,
      "limit": 50,
      "remaining": 38
    },
    "cache": {
      "hits": 234,
      "misses": 45,
      "hitRate": 0.84
    }
  },
  "lastReset": "2026-03-05"
}

Quota Alerts

Set up alerts when quota exceeds thresholds:
function checkQuotaAlerts() {
  const stats = distanceMatrixClient.getStats();
  
  const monthlyUsage = (stats.monthlyCount / 700) * 100;
  
  if (monthlyUsage >= 90) {
    sendAlert('CRITICAL: 90% of monthly Distance Matrix quota used!');
  } else if (monthlyUsage >= 75) {
    sendAlert('WARNING: 75% of monthly Distance Matrix quota used');
  }
}

// Run daily
setInterval(checkQuotaAlerts, 24 * 60 * 60 * 1000);

Caching Strategy

The client caches results for 7 days to minimize API calls. Cache configuration:
private cache: Map<string, CacheEntry> = new Map();
private readonly CACHE_TTL_DAYS = 7;

private isCacheValid(entry: CacheEntry): boolean {
  const ageMs = Date.now() - entry.timestamp;
  const ageDays = ageMs / (1000 * 60 * 60 * 24);
  return ageDays < this.CACHE_TTL_DAYS;
}
Cache key format:
const cacheKey = `${originNodeId}|${destNodeId}|${mode}`;
Pre-warm cache to reduce API calls:
const commonRoutes = [
  ['TILAGOR', 'CAMPUS', 'driving'],
  ['CAMPUS', 'TILAGOR', 'driving'],
  ['NAIORPUL', 'CAMPUS', 'driving'],
  // ...
];

await distanceMatrixClient.prewarmCache(commonRoutes);

Error Logging

Request Logging

The server logs all requests:
app.use((req: Request, res: Response, next: NextFunction) => {
  console.log(`${new Date().toISOString()} ${req.method} ${req.path}`);
  next();
});
Output:
2026-03-05T10:30:15.123Z GET /api/health
2026-03-05T10:30:20.456Z GET /api/routes?from=TILAGOR&to=CAMPUS&time=08:30
2026-03-05T10:30:25.789Z POST /api/auth/send-link

Error Handler

Global error handler catches unhandled errors:
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
  console.error('Unhandled error:', err);
  res.status(500).json({
    error: 'Internal server error',
    message: err.message
  });
});

Structured Logging

For production, use a logging library like Winston:
npm install winston
import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple()
  }));
}

// Usage
logger.info('Server started', { port: PORT });
logger.error('Distance Matrix API error', { error: err.message });

Performance Metrics

Request Duration

Track API response times:
app.use((req: Request, res: Response, next: NextFunction) => {
  const start = Date.now();
  
  res.on('finish', () => {
    const duration = Date.now() - start;
    console.log(`${req.method} ${req.path} - ${res.statusCode} - ${duration}ms`);
  });
  
  next();
});

Route Planning Performance

Log route calculation times:
export async function planRoute(req: Request, res: Response) {
  const start = Date.now();
  
  // ... route planning logic ...
  
  const duration = Date.now() - start;
  console.log(`Route planning: ${from}${to} took ${duration}ms`);
  
  res.json({ ...result, computeTimeMs: duration });
}

PM2 Monitoring

PM2 provides built-in monitoring.

Real-time Monitoring

pm2 monit
Shows:
  • CPU usage
  • Memory usage
  • Logs (stdout/stderr)

Process List

pm2 list
Output:
┌─────┬──────────────┬─────────┬─────────┬─────────┬──────────┐
│ id  │ name         │ mode    │ ↺       │ status  │ cpu      │
├─────┼──────────────┼─────────┼─────────┼─────────┼──────────┤
│ 0   │ mnd-backend  │ fork    │ 0       │ online  │ 0.3%     │
└─────┴──────────────┴─────────┴─────────┴─────────┴──────────┘

PM2 Plus (Cloud Monitoring)

Free tier:
  • Real-time monitoring
  • Exception tracking
  • Custom metrics
Setup:
pm2 link <secret_key> <public_key>
Get keys from pm2.io

Log Management

View logs:
pm2 logs mnd-backend
Log rotation: Install PM2 log rotate:
pm2 install pm2-logrotate
Configure:
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 30
pm2 set pm2-logrotate:compress true

Database Monitoring

The backend uses JSON file-based storage.

Monitor Data Files

Track file sizes:
du -h src/data/*.json
Output:
4.0K src/data/nodes.json
60K src/data/edges.json
24K src/data/routes.json

User Data

Monitor user database size:
du -h src/data/users.json
If growing too large, consider migrating to a real database (SQLite, PostgreSQL).

Alerting

Email Alerts

Send email alerts for critical events:
import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: process.env.EMAIL_SMTP_HOST,
  port: Number(process.env.EMAIL_SMTP_PORT),
  auth: {
    user: process.env.EMAIL_SMTP_USER,
    pass: process.env.EMAIL_SMTP_PASSWORD
  }
});

async function sendAlert(message: string) {
  await transporter.sendMail({
    from: process.env.EMAIL_FROM,
    to: 'admin@yourdomain.com',
    subject: 'MND Alert',
    text: message
  });
}

// Usage
if (monthlyQuota >= 90) {
  await sendAlert('Distance Matrix quota at 90%!');
}

Slack Alerts

npm install @slack/webhook
import { IncomingWebhook } from '@slack/webhook';

const webhook = new IncomingWebhook(process.env.SLACK_WEBHOOK_URL);

async function sendSlackAlert(message: string) {
  await webhook.send({
    text: message,
    username: 'MND Monitor',
    icon_emoji: ':bus:'
  });
}

Metrics Dashboard

Create a simple metrics endpoint:
app.get('/api/metrics', (req: Request, res: Response) => {
  const stats = distanceMatrixClient.getStats();
  
  res.json({
    server: {
      uptime: process.uptime(),
      memory: process.memoryUsage(),
      nodeVersion: process.version
    },
    distanceMatrix: {
      monthlyUsed: stats.monthlyCount,
      monthlyLimit: 700,
      dailyUsed: stats.dailyCount,
      cacheHitRate: stats.cacheHits / (stats.cacheHits + stats.cacheMisses)
    },
    graph: {
      nodes: graph.getNodes().length,
      edges: graph.getEdges().length
    }
  });
});
Response:
{
  "server": {
    "uptime": 12345.67,
    "memory": {
      "rss": 52428800,
      "heapTotal": 20971520,
      "heapUsed": 15728640
    },
    "nodeVersion": "v18.16.0"
  },
  "distanceMatrix": {
    "monthlyUsed": 45,
    "monthlyLimit": 700,
    "dailyUsed": 12,
    "cacheHitRate": 0.84
  },
  "graph": {
    "nodes": 19,
    "edges": 542
  }
}

Monitoring Checklist

  • Health check endpoint configured
  • Uptime monitoring service added (UptimeRobot, etc.)
  • Distance Matrix quota tracking enabled
  • Quota alerts configured (75%, 90%)
  • Request logging enabled
  • Error logging configured
  • PM2 monitoring active
  • Log rotation configured
  • Performance metrics tracked
  • Alert notifications configured (email/Slack)
  • Metrics dashboard accessible

Next Steps

Build docs developers (and LLMs) love