npm package: @sagatechbrasildev/argus-metrics-adonis
Description: Professional metrics collection library for AdonisJS v6
Latest version: 1.0.8

# AdonisJS Metrics Library

> 📊 Biblioteca profissional de coleta de métricas para AdonisJS v6

## 🚀 Recursos

- ✅ **Coleta Automática de Métricas** - Requests, queries SQL, jobs, eventos e erros
- 📈 **Agregação Inteligente** - Dados agregados por endpoint, status code e intervalo de tempo
- 🔒 **Sanitização de Dados Sensíveis** - Remove automaticamente passwords, tokens e headers sensíveis
- 📊 **Percentis de Performance** - P50, P95, P99 para análise detalhada
- 🔄 **Flush Automático** - Envia métricas periodicamente para seu backend
- 💾 **Buffer com Retry** - Queue local com exponential backoff em caso de falha
- 🎯 **Sampling Rate** - Controle a porcentagem de requests monitoradas
- 🚦 **Health Checks** - Monitora uptime, memória e CPU
- 🔍 **Consumer Tracking** - Rastreio de API keys e usuários
- ⚡ **Zero Dependencies** - Apenas peer dependencies do AdonisJS

## 📦 Instalação

```bash
npm install @sagatechbrasildev/argus-metrics-adonis
# ou
yarn add @sagatechbrasildev/argus-metrics-adonis
```

## ⚙️ Configuração

### 1. Configurar a Biblioteca

Execute o comando de configuração para registrar automaticamente o comando e o provider:

```bash
node ace configure @sagatechbrasildev/argus-metrics-adonis
```

Depois, publique o arquivo de configuração:

```bash
node ace metrics:publish-config
```

Isso criará o arquivo `config/metrics.ts` no seu projeto com todas as opções disponíveis.

### 2. Registrar o Provider (Manual)

Se preferir configurar manualmente, adicione ao arquivo `adonisrc.ts`:

```typescript
export default defineConfig({
  // ...
  providers: [
    () => import("@adonisjs/core/providers/app_provider"),
    () =>
      import("@sagatechbrasildev/argus-metrics-adonis/providers/adonis-provider"),
  ],
});
```

### 3. Adicionar Middleware

No arquivo `start/kernel.ts`:

```typescript
import { metricsMiddleware } from "@sagatechbrasildev/argus-metrics-adonis";

router.use([metricsMiddleware()]);
```

### 4. Configurar Variáveis de Ambiente

Crie ou edite o arquivo `.env`:

```env
# Habilitar coleta de métricas
METRICS_ENABLED=true

# API Key para autenticação
METRICS_API_KEY=your-api-key-here

# Endpoint do backend que receberá as métricas
METRICS_ENDPOINT=https://your-backend.com/api/metrics

# Intervalo de envio (em segundos)
METRICS_FLUSH_INTERVAL=60

# Taxa de amostragem (0.0 a 1.0)
METRICS_SAMPLE_RATE=1.0

# Paths excluídos
METRICS_EXCLUDE_PATHS=/health,/metrics

# Capturar payloads (cuidado com dados sensíveis)
METRICS_CAPTURE_PAYLOADS=false

# Capturar queries SQL
METRICS_CAPTURE_QUERIES=true

# Tamanho máximo do buffer
METRICS_MAX_BUFFER_SIZE=1000

# Threshold para queries lentas (ms)
METRICS_SLOW_QUERY_THRESHOLD=100
```

### 5. Configuração Customizada (Opcional)

Crie o arquivo `config/metrics.ts`:

```typescript
import { defineConfig } from "@adonisjs/core/app";
import type { MetricsConfig } from "@sagatechbrasildev/argus-metrics-adonis";

export default defineConfig<MetricsConfig>({
  enabled: true,
  apiKey: "your-api-key",
  endpoint: "https://your-backend.com/api/metrics",
  flushInterval: 60,
  aggregationInterval: 60,
  sampleRate: 1.0,
  excludePaths: ["/health", "/metrics"],
  excludeHeaders: ["authorization", "cookie"],
  capturePayloads: false,
  captureQueries: true,
  maxBufferSize: 1000,
  slowQueryThreshold: 100,
});
```

## 📖 Uso Avançado

### Acessar o Collector Manualmente

```typescript
import { getMetricsCollector } from "@sagatechbrasildev/argus-metrics-adonis";

export default class UsersController {
  async index({ app }) {
    const collector = await getMetricsCollector(app);

    // Coletar métrica customizada
    collector.collectEvent("user.login", { userId: 123 }, 1);

    // Ver métricas atuais
    const metrics = collector.getMetrics();
    console.log(metrics);
  }
}
```

### Coletar Erros Manualmente

```typescript
try {
  // código que pode falhar
} catch (error) {
  const collector = await getMetricsCollector(app);
  collector.collectError(error, ctx);
  throw error;
}
```

### Health Check Endpoint

```typescript
import { getMetricsCollector } from "@sagatechbrasildev/argus-metrics-adonis";

router.get("/health", async ({ app }) => {
  const collector = await getMetricsCollector(app);
  const health = collector.collectHealth();

  return {
    status: "ok",
    uptime: health.uptime,
    memory: health.memoryUsage,
    cpu: health.cpuUsage,
  };
});
```

## 📊 Formato de Dados Enviados

A biblioteca envia dados agregados no seguinte formato:

```typescript
{
  "timestamp": "2025-12-17T10:00:00Z",
  "interval": 60, // segundos
  "requests": [
    {
      "method": "GET",
      "path": "/api/users",
      "statusCode": 200,
      "count": 150,
      "avgDuration": 45.2,
      "minDuration": 12.1,
      "maxDuration": 156.8,
      "p50": 42.0,
      "p95": 89.5,
      "p99": 145.2,
      "totalRequestSize": 15000,
      "totalResponseSize": 450000,
      "errors": 0
    }
  ],
  "queries": [
    {
      "sql": "SELECT * FROM users WHERE id = ?",
      "count": 150,
      "avgDuration": 3.5,
      "minDuration": 1.2,
      "maxDuration": 12.8,
      "slowQueries": 2
    }
  ],
  "jobs": [
    {
      "name": "SendEmailJob",
      "duration": 1250,
      "status": "success",
      "timestamp": "2025-12-17T10:00:15Z"
    }
  ],
  "events": [
    {
      "name": "user.login",
      "payload": { "userId": 123 },
      "listeners": 1,
      "timestamp": "2025-12-17T10:00:30Z"
    }
  ]
}
```

## 🔒 Segurança e Privacidade

### Dados Automaticamente Sanitizados

- **Headers**: `authorization`, `cookie`, `set-cookie`, `x-api-key`
- **Body Fields**: `password`, `token`, `secret`, `api_key`, `credit_card`, `cvv`, `ssn`

### Adicionar Campos Customizados

```typescript
import { DataSanitizer } from "@sagatechbrasildev/argus-metrics-adonis";

// Customizar sanitizador
const sanitized = DataSanitizer.sanitizeBody({
  email: "user@example.com",
  password: "secret123", // será [REDACTED]
  cpf: "123.456.789-00", // adicione à lista se necessário
});
```

## 📈 Backend de Métricas

Você precisará criar um backend para receber as métricas. Exemplo simples:

```typescript
// Endpoint no seu backend
app.post("/api/metrics", async (req, res) => {
  const metrics = req.body;

  // Validar API Key
  if (req.headers["x-api-key"] !== process.env.METRICS_API_KEY) {
    return res.status(401).json({ error: "Unauthorized" });
  }

  // Salvar no banco de dados
  await db.insert("metrics").values(metrics);

  // Ou enviar para serviço de analytics
  await analytics.track(metrics);

  res.json({ success: true });
});
```

## 🛠️ API Reference

### MetricsCollector

```typescript
class MetricsCollector {
  collectRequest(ctx: HttpContext, startTime: number): void;
  collectQuery(sql: string, duration: number, bindings?: any[]): void;
  collectJob(
    name: string,
    startTime: number,
    status: "success" | "failed",
  ): void;
  collectEvent(name: string, payload: any, listeners: number): void;
  collectError(error: Error, ctx?: HttpContext): void;
  collectHealth(): HealthMetrics;
  flush(): Promise<boolean>;
  getMetrics(): AggregatedMetrics;
  shutdown(): Promise<void>;
}
```

### MetricsConfig

```typescript
interface MetricsConfig {
  enabled: boolean;
  apiKey: string;
  endpoint: string;
  flushInterval: number;
  aggregationInterval: number;
  sampleRate: number;
  excludePaths: string[];
  excludeHeaders: string[];
  capturePayloads: boolean;
  captureQueries: boolean;
  maxBufferSize: number;
  slowQueryThreshold: number;
}
```

## 🤝 Contribuindo

Contribuições são bem-vindas! Por favor:

1. Fork o projeto
2. Crie uma branch para sua feature (`git checkout -b feature/amazing-feature`)
3. Commit suas mudanças (`git commit -m 'Add amazing feature'`)
4. Push para a branch (`git push origin feature/amazing-feature`)
5. Abra um Pull Request

**Desenvolvido com ❤️ para a comunidade AdonisJS**