<!--
hoody-proxyLogs Subskill (sdk)
Auto-generated by Hoody Skills Generator
Generated: 2026-05-06T20:05:33.685Z
Model: mimo-v2.5-pro
Mode: sdk


Tokens: 5903

DO NOT EDIT MANUALLY - Changes will be overwritten on next generation
-->

# hoody-proxyLogs Subskill

## Overview

The `hoody-proxyLogs` service provides centralized logging infrastructure for all Hoody Kit container services. It captures, stores, and streams request/response logs and system events across your entire Hoody project ecosystem.

### When to Use

- **Debugging**: Search historical request/response logs to diagnose issues in container services
- **Monitoring**: Stream live logs in real-time to observe system behavior as it happens
- **Analytics**: Retrieve log statistics to understand traffic patterns and error rates
- **Auditing**: Query logs filtered by project, container, service, level, or method

### How It Fits Into Hoody Philosophy

Hoody Proxy Logs embodies the "zero configuration" philosophy — all container services automatically emit logs without manual instrumentation. The service provides:

- **Automatic collection**: Every proxied request generates structured log entries
- **Multi-tenant isolation**: Logs are scoped by project and container identifiers
- **Standardized access**: A single service handles all log operations across your infrastructure
- **Real-time capability**: SSE streaming enables live-tail monitoring without polling

### Service Architecture

```
Container Services → Hoody Proxy → proxyLogs Service → Log Storage
                                              ↓
                                    Query API (/_logs)
                                    Stats API (/_logs/stats)
                                    Stream API (/_logs/stream)
```

---

## Common Workflows

### Workflow 1: Query Historical Logs

Search and filter through stored request/response and event logs.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Basic log query with pagination
const logs = await client.proxyLogs.logs.list({
  limit: 50,
  offset: 0
})

console.log(`Retrieved ${logs.items.length} log entries`)
```

### Workflow 2: Filter Logs by Project and Container

Narrow down logs to a specific project or container for targeted debugging.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Filter logs for a specific project and container
const filteredLogs = await client.proxyLogs.logs.list({
  projectId: 'proj_abc123',
  containerId: 'cnt_xyz789',
  limit: 100
})

console.log(`Found ${filteredLogs.items.length} logs for container`)
```

### Workflow 3: Filter by Log Level and Method

Isolate errors or specific HTTP methods for debugging.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Get only error-level logs from POST requests
const errorLogs = await client.proxyLogs.logs.list({
  level: 'error',
  method: 'POST',
  limit: 25
})

for (const entry of errorLogs.items) {
  console.log(`Error: ${entry.timestamp} - ${entry.message}`)
}
```

### Workflow 4: Include Request/Response Bodies

Retrieve full request and response payloads for detailed analysis.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Get logs with full request and response bodies
const detailedLogs = await client.proxyLogs.logs.list({
  includeRequestBody: true,
  includeResponseBody: true,
  limit: 10
})

for (const entry of detailedLogs.items) {
  console.log(`Request: ${entry.requestBody}`)
  console.log(`Response: ${entry.responseBody}`)
}
```

### Workflow 5: Collect All Pages Automatically

Use `listAll` to automatically paginate through all matching logs.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Automatically collect all pages of logs
const allLogs = await client.proxyLogs.logs.listAll({
  projectId: 'proj_abc123',
  kind: 'request',
  level: 'warn'
})

console.log(`Total logs collected: ${allLogs.length}`)
```

### Workflow 6: Async Iterator for Large Datasets

Process logs incrementally without loading everything into memory.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Use async iterator for memory-efficient processing
const iterator = client.proxyLogs.logs.listIterator({
  projectId: 'proj_abc123',
  limit: 100
})

for await (const page of iterator) {
  for (const entry of page.items) {
    await processLogEntry(entry)
  }
}
```

### Workflow 7: Stream Live Logs via SSE

Open a persistent Server-Sent Events connection for real-time log monitoring.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Stream live logs with filters
const stream = await client.proxyLogs.logs.streamLogs({
  projectId: 'proj_abc123',
  containerId: 'cnt_xyz789',
  kind: 'request',
  level: 'error'
})

// Process incoming log entries
stream.on('data', (entry) => {
  console.log(`Live log: ${entry.timestamp} - ${entry.message}`)
})
```

### Workflow 8: Resume Stream After Disconnect

Use the `Last-Event-ID` header to resume streaming from where you left off.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Resume stream from a specific event ID
const resumedStream = await client.proxyLogs.logs.streamLogs({
  projectId: 'proj_abc123',
  'Last-Event-ID': '12345'
})

resumedStream.on('data', (entry) => {
  console.log(`Resumed log: ${entry.id} - ${entry.message}`)
})
```

**SSE Frame Format**: Each frame carries an `id: <ringSeq>` line for reconnection:

```
id: 12345
data: {"timestamp":"2025-01-15T10:30:00Z","level":"info","message":"Request processed"}
```

### Workflow 9: Get Log Statistics

Retrieve aggregate statistics about your log data.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Get log statistics
const stats = await client.proxyLogs.logs.getStats()

console.log(`Total logs: ${stats.total}`)
console.log(`Error count: ${stats.errors}`)
console.log(`Log size: ${stats.sizeBytes} bytes`)
```

---

## Advanced Operations

### Advanced Workflow 1: Cursor-Based Pagination

Use cursor-based pagination for consistent results when logs are being written concurrently.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// First page
let currentPage = await client.proxyLogs.logs.list({
  limit: 50,
  cursor: undefined
})

while (currentPage.items.length > 0) {
  await processLogs(currentPage.items)
  
  // Get next page using cursor
  if (currentPage.nextCursor) {
    currentPage = await client.proxyLogs.logs.list({
      limit: 50,
      cursor: currentPage.nextCursor
    })
  } else {
    break
  }
}
```

### Advanced Workflow 2: Recent Logs with `last` Parameter

Retrieve the most recent N log entries without scanning the entire dataset.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Get the last 100 log entries
const recentLogs = await client.proxyLogs.logs.list({
  last: 100,
  projectId: 'proj_abc123'
})

console.log(`Most recent ${recentLogs.items.length} logs retrieved`)
```

### Advanced Workflow 3: Resume Query After Specific Log ID

Use `afterId` to fetch logs that occurred after a specific log entry.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Get logs after a specific ID
const newerLogs = await client.proxyLogs.logs.list({
  afterId: 98765,
  limit: 50
})

console.log(`Found ${newerLogs.items.length} logs after ID 98765`)
```

### Advanced Workflow 4: Multi-Service Log Correlation

Correlate logs across multiple services by querying with service name filters.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

// Get logs from a specific service
const serviceLogs = await client.proxyLogs.logs.list({
  projectId: 'proj_abc123',
  serviceName: 'my-api-service',
  kind: 'request',
  limit: 200
})

// Group by container for analysis
const byContainer = serviceLogs.items.reduce((acc, log) => {
  const key = log.containerId
  if (!acc[key]) acc[key] = []
  acc[key].push(log)
  return acc
}, {})

for (const [containerId, logs] of Object.entries(byContainer)) {
  console.log(`Container ${containerId}: ${logs.length} logs`)
}
```

### Advanced Workflow 5: Error Recovery Pattern

Handle stream disconnections gracefully with automatic reconnection.

```
import { HoodyClient } from '@hoody-ai/hoody-sdk'

const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: 'TOKEN' })

let lastEventId: string | undefined

async function connectStream() {
  const stream = await client.proxyLogs.logs.streamLogs({
    projectId: 'proj_abc123',
    'Last-Event-ID': lastEventId
  })

  stream.on('data', (entry) => {
    lastEventId = entry.id
    console.log(`Log: ${entry.message}`)
  })

  stream.on('error', async (error) => {
    console.error('Stream error, reconnecting in 5s:', error.message)
    await new Promise(resolve => setTimeout(resolve, 5000))
    await connectStream()
  })
}

await connectStream()
```

### Performance Considerations

| Operation | Performance Tip |
|-----------|-----------------|
| `list` | Use `limit` to control response size; default may return large payloads |
| `listAll` | Avoid for datasets > 10k entries; use `listIterator` instead |
| `listIterator` | Best for processing large datasets; streams pages on demand |
| `streamLogs` | Use filters (`kind`, `level`) to reduce noise and bandwidth |
| `getStats` | Lightweight operation; safe to call frequently for dashboards |
| `afterId` | More efficient than offset-based pagination for incremental polling |

---

## Quick Reference

### Endpoint Summary

| Method | Path | SDK Method | Description |
|--------|------|------------|-------------|
| GET | `/_logs` | `client.proxyLogs.logs.list()` | Query centralized logs |
| GET | `/_logs/stats` | `client.proxyLogs.logs.getStats()` | Get log statistics |
| GET | `/_logs/stream` | `client.proxyLogs.logs.streamLogs()` | Live-tail logs via SSE |

### Essential Parameters for `/_logs`

| Parameter | Type | Description |
|-----------|------|-------------|
| `limit` | integer | Maximum entries to return |
| `offset` | integer | Skip N entries (pagination) |
| `cursor` | string | Cursor for consistent pagination |
| `last` | integer | Get the N most recent entries |
| `afterId` | integer | Get entries after this log ID |
| `projectId` | string | Filter by project |
| `containerId` | string | Filter by container |
| `serviceName` | string | Filter by service name |
| `level` | string | Filter by log level |
| `kind` | string | Filter by log kind |
| `method` | string | Filter by HTTP method |
| `source` | string | Filter by source |
| `includeRequestBody` | boolean | Include request payloads |
| `includeResponseBody` | boolean | Include response payloads |

### Essential Parameters for `/_logs/stream`

| Parameter | Type | Description |
|-----------|------|-------------|
| `projectId` | string | Filter by project |
| `containerId` | string | Filter by container |
| `kind` | string | Filter by log kind |
| `level` | string | Filter by log level |
| `Last-Event-ID` | string | Resume from specific event ID |

### Typical Response Formats

**Log Query Result** (`/_logs`):

```
{
  "items": [
    {
      "id": 12345,
      "timestamp": "2025-01-15T10:30:00Z",
      "level": "info",
      "kind": "request",
      "method": "GET",
      "path": "/api/users",
      "statusCode": 200,
      "duration": 45,
      "projectId": "proj_abc123",
      "containerId": "cnt_xyz789",
      "serviceName": "my-api",
      "message": "GET /api/users 200 45ms"
    }
  ],
  "total": 1500,
  "nextCursor": "eyJpZCI6MTIzNDV9"
}
```

**Log Statistics** (`/_logs/stats`):

```
{
  "total": 15000,
  "errors": 234,
  "warnings": 1023,
  "sizeBytes": 52428800,
  "oldestEntry": "2025-01-01T00:00:00Z",
  "newestEntry": "2025-01-15T10:30:00Z"
}
```

**SSE Stream Frame** (`/_logs/stream`):

```
id: 12345
data: {"id":12345,"timestamp":"2025-01-15T10:30:00Z","level":"info","message":"Request processed"}
```

### Base URL Pattern

```
https://{projectId}-{containerId}-proxy-logs-{serviceId}.{node}.containers.hoody.icu
```

**Important**: Use SDK methods directly — the SDK handles URL construction and authentication automatically. Do not construct URLs manually unless using the routing helpers.