* feat: add LiteLLM LLM provider for Bedrock and 100+ providers Add a new `litellm` LLM provider that uses the LiteLLM SDK for chat completions and tool calling, enabling AWS Bedrock and 100+ other providers for Hindsight's core engine (retain, recall, reflect). - New LiteLLMLLM provider in engine/providers/litellm_llm.py - Registered in factory, valid providers list, and no-api-key set - Refactored API key validation to use requires_api_key() helper - Added boto3 dependency for Bedrock auth - Updated docs: configuration, models, monitoring, providers grid * feat: add bedrock as first-class LLM provider alias Add `bedrock` as a dedicated provider name that auto-prepends the `bedrock/` prefix to model names and delegates to LiteLLMLLM under the hood. This makes Bedrock support more discoverable — users set `HINDSIGHT_API_LLM_PROVIDER=bedrock` with plain Bedrock model IDs. * test: add Bedrock to CI provider tests - Add bedrock/us.amazon.nova-lite-v1:0 to MODEL_MATRIX in test_llm_provider.py - Add AWS credential check in should_skip_provider() - Pass AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION_NAME secrets to test-api job - Update default bedrock model to amazon.nova-2-lite-v1:0 * fix: regenerate docs skill files and bump memory test timeout - Regenerate skills/hindsight-docs references after docs changes - Bump test_llm_provider_memory_operations timeout to 600s for slower providers like Bedrock via LiteLLM * test: skip bedrock lite models in memory operations test Nova Lite has a 10K output token limit which is too low for fact extraction (requires 64K). The api_methods test (completion, tools, structured output) already validates the provider works correctly. * test: use Nova Pro for bedrock CI tests to cover full memory pipeline Nova Lite only supports 10K output tokens, too low for fact extraction. Switch to Nova Pro which supports the full 64K output needed for retain/reflect operations. This ensures bedrock is tested on all Hindsight functionalities, not just basic API methods. * test: switch bedrock CI to Nova 2 Lite (supports 64K output tokens) Nova v1 models (Pro, Lite) have a 10K output token limit which is too low for fact extraction. Nova 2 Lite supports 64K+ output tokens, enabling full memory pipeline testing (retain + reflect).
270 lines
9.5 KiB
Markdown
270 lines
9.5 KiB
Markdown
# Monitoring
|
|
|
|
Hindsight provides comprehensive observability through Prometheus metrics, OpenTelemetry distributed tracing, and pre-built Grafana dashboards.
|
|
|
|
## Local Development
|
|
|
|
For local observability, use the Grafana LGTM (Loki, Grafana, Tempo, Mimir) all-in-one stack:
|
|
|
|
```bash
|
|
./scripts/dev/start-monitoring.sh
|
|
```
|
|
|
|
This starts a single Docker container providing:
|
|
- **Grafana UI**: http://localhost:3000 (anonymous admin access)
|
|
- **Traces (Tempo)**: OTLP endpoint at http://localhost:4318 (HTTP) and http://localhost:4317 (gRPC)
|
|
- **Metrics (Prometheus/Mimir)**: Scrapes http://localhost:8888/metrics automatically
|
|
- **Logs (Loki)**: Available for log aggregation
|
|
- **Pre-built Dashboards**: Hindsight Operations, LLM Metrics, API Service
|
|
|
|
**Enable tracing in your API:**
|
|
```bash
|
|
export HINDSIGHT_API_OTEL_TRACES_ENABLED=true
|
|
export HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
```
|
|
|
|
:::note Production Deployment
|
|
The local monitoring stack is for development only. In production, deploy Grafana LGTM separately or use commercial platforms (Grafana Cloud, DataDog, New Relic, etc.).
|
|
:::
|
|
|
|
## Grafana Dashboards
|
|
|
|
Pre-built dashboards are available in [`monitoring/grafana/dashboards/`](https://github.com/anthropics/hindsight/tree/main/monitoring/grafana/dashboards). Import these JSON files into your Grafana instance:
|
|
|
|
| Dashboard | Description |
|
|
|-----------|-------------|
|
|
| **Hindsight Operations** | Operation rates, latency percentiles, per-bank metrics |
|
|
| **Hindsight LLM Metrics** | LLM calls, token usage, latency by scope/provider |
|
|
| **Hindsight API Service** | HTTP requests, error rates, DB pool, process metrics |
|
|
|
|
The dashboards are automatically provisioned when using the monitoring stack script.
|
|
|
|
## Metrics Endpoint
|
|
|
|
Hindsight exposes Prometheus metrics at `/metrics`:
|
|
|
|
```bash
|
|
curl http://localhost:8888/metrics
|
|
```
|
|
|
|
## Available Metrics
|
|
|
|
### Operation Metrics
|
|
|
|
| Metric | Type | Labels | Description |
|
|
|--------|------|--------|-------------|
|
|
| `hindsight.operation.duration` | Histogram | operation, bank_id, source, budget, max_tokens, success | Duration of operations in seconds |
|
|
| `hindsight.operation.total` | Counter | operation, bank_id, source, budget, max_tokens, success | Total number of operations executed |
|
|
|
|
**Labels:**
|
|
- `operation`: Operation type (`retain`, `recall`, `reflect`)
|
|
- `bank_id`: Memory bank identifier
|
|
- `source`: Where the operation was triggered from (`api`, `reflect`, `internal`)
|
|
- `budget`: Budget level if specified (`low`, `mid`, `high`)
|
|
- `max_tokens`: Max tokens if specified
|
|
- `success`: Whether the operation succeeded (`true`, `false`)
|
|
|
|
The `source` label allows distinguishing between:
|
|
- `api`: Direct API calls from clients
|
|
- `reflect`: Internal recall calls made during reflect operations
|
|
- `internal`: Other internal operations
|
|
|
|
### LLM Metrics
|
|
|
|
| Metric | Type | Labels | Description |
|
|
|--------|------|--------|-------------|
|
|
| `hindsight.llm.duration` | Histogram | provider, model, scope, success | Duration of LLM API calls in seconds |
|
|
| `hindsight.llm.calls.total` | Counter | provider, model, scope, success | Total number of LLM API calls |
|
|
| `hindsight.llm.tokens.input` | Counter | provider, model, scope, success, token_bucket | Input tokens for LLM calls |
|
|
| `hindsight.llm.tokens.output` | Counter | provider, model, scope, success, token_bucket | Output tokens from LLM calls |
|
|
|
|
**Labels:**
|
|
- `provider`: LLM provider (`openai`, `anthropic`, `gemini`, `groq`, `ollama`, `lmstudio`, `bedrock`, `litellm`)
|
|
- `model`: Model name (e.g., `gpt-4`, `claude-3-sonnet`)
|
|
- `scope`: What the LLM call is for (`memory`, `reflect`, `consolidation`, `answer`)
|
|
- `success`: Whether the call succeeded (`true`, `false`)
|
|
- `token_bucket`: Token count bucket for cardinality control (`0-100`, `100-500`, `500-1k`, `1k-5k`, `5k-10k`, `10k-50k`, `50k+`)
|
|
|
|
### HTTP Request Metrics
|
|
|
|
| Metric | Type | Labels | Description |
|
|
|--------|------|--------|-------------|
|
|
| `hindsight.http.duration` | Histogram | method, endpoint, status_code, status_class | Duration of HTTP requests in seconds |
|
|
| `hindsight.http.requests.total` | Counter | method, endpoint, status_code, status_class | Total number of HTTP requests |
|
|
| `hindsight.http.requests.in_progress` | UpDownCounter | method, endpoint | Number of HTTP requests currently being processed |
|
|
|
|
**Labels:**
|
|
- `method`: HTTP method (`GET`, `POST`, `PUT`, `DELETE`)
|
|
- `endpoint`: Request path (normalized to reduce cardinality - UUIDs replaced with `{id}`)
|
|
- `status_code`: HTTP status code (`200`, `400`, `500`, etc.)
|
|
- `status_class`: Status code class (`2xx`, `4xx`, `5xx`)
|
|
|
|
### Database Pool Metrics
|
|
|
|
| Metric | Type | Labels | Description |
|
|
|--------|------|--------|-------------|
|
|
| `hindsight.db.pool.size` | Gauge | - | Current number of connections in the pool |
|
|
| `hindsight.db.pool.idle` | Gauge | - | Number of idle connections in the pool |
|
|
| `hindsight.db.pool.min` | Gauge | - | Minimum pool size |
|
|
| `hindsight.db.pool.max` | Gauge | - | Maximum pool size |
|
|
|
|
### Process Metrics
|
|
|
|
| Metric | Type | Labels | Description |
|
|
|--------|------|--------|-------------|
|
|
| `hindsight.process.cpu.seconds` | Gauge | type | Process CPU time in seconds |
|
|
| `hindsight.process.memory.bytes` | Gauge | type | Process memory usage in bytes |
|
|
| `hindsight.process.open_fds` | Gauge | - | Number of open file descriptors |
|
|
| `hindsight.process.threads` | Gauge | - | Number of active threads |
|
|
|
|
**Labels:**
|
|
- `type` (CPU): `user` or `system`
|
|
- `type` (Memory): `rss_max` (maximum resident set size)
|
|
|
|
### Histogram Buckets
|
|
|
|
Custom bucket boundaries are configured for better percentile accuracy:
|
|
|
|
**Operation Duration Buckets (seconds):**
|
|
```
|
|
0.1, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 5.0, 7.5, 10.0, 15.0, 20.0, 30.0, 60.0, 120.0
|
|
```
|
|
|
|
**LLM Duration Buckets (seconds):**
|
|
```
|
|
0.1, 0.25, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0, 15.0, 30.0, 60.0, 120.0
|
|
```
|
|
|
|
**HTTP Duration Buckets (seconds):**
|
|
```
|
|
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 30.0
|
|
```
|
|
|
|
## Prometheus Configuration
|
|
|
|
```yaml
|
|
scrape_configs:
|
|
- job_name: 'hindsight'
|
|
static_configs:
|
|
- targets: ['localhost:8888']
|
|
```
|
|
|
|
## Example Queries
|
|
|
|
### Average operation latency by type
|
|
```promql
|
|
rate(hindsight_operation_duration_sum[5m]) / rate(hindsight_operation_duration_count[5m])
|
|
```
|
|
|
|
### LLM calls per minute by provider
|
|
```promql
|
|
rate(hindsight_llm_calls_total[1m]) * 60
|
|
```
|
|
|
|
### P95 LLM latency
|
|
```promql
|
|
histogram_quantile(0.95, rate(hindsight_llm_duration_bucket[5m]))
|
|
```
|
|
|
|
### Total tokens consumed by model
|
|
```promql
|
|
sum by (model) (hindsight_llm_tokens_input_total + hindsight_llm_tokens_output_total)
|
|
```
|
|
|
|
### Internal vs API recall operations
|
|
```promql
|
|
sum by (source) (rate(hindsight_operation_total{operation="recall"}[5m]))
|
|
```
|
|
|
|
### HTTP requests per second by endpoint
|
|
```promql
|
|
sum by (endpoint) (rate(hindsight_http_requests_total[1m]))
|
|
```
|
|
|
|
### HTTP error rate (5xx)
|
|
```promql
|
|
sum(rate(hindsight_http_requests_total{status_class="5xx"}[5m])) / sum(rate(hindsight_http_requests_total[5m]))
|
|
```
|
|
|
|
### P95 HTTP latency
|
|
```promql
|
|
histogram_quantile(0.95, sum by (le) (rate(hindsight_http_duration_seconds_bucket[5m])))
|
|
```
|
|
|
|
### Database pool utilization
|
|
```promql
|
|
hindsight_db_pool_size / hindsight_db_pool_max
|
|
```
|
|
|
|
### Active database connections
|
|
```promql
|
|
hindsight_db_pool_size - hindsight_db_pool_idle
|
|
```
|
|
|
|
### CPU usage rate
|
|
```promql
|
|
rate(hindsight_process_cpu_seconds{type="user"}[1m])
|
|
```
|
|
|
|
---
|
|
|
|
## Distributed Tracing
|
|
|
|
Hindsight supports OpenTelemetry distributed tracing for memory operations and LLM calls, following GenAI semantic conventions v1.37+.
|
|
|
|
### Configuration
|
|
|
|
See [Configuration - OpenTelemetry Tracing](./configuration#opentelemetry-tracing) for environment variables.
|
|
|
|
**Quick Start:**
|
|
```bash
|
|
# Enable tracing
|
|
export HINDSIGHT_API_OTEL_TRACES_ENABLED=true
|
|
export HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
|
|
# View traces with Grafana LGTM (local dev)
|
|
./scripts/dev/start-monitoring.sh
|
|
# Open http://localhost:3000 → Explore → Tempo
|
|
```
|
|
|
|
Supports any OTLP-compatible backend (Grafana LGTM, Langfuse, OpenLIT, DataDog, New Relic, Honeycomb, etc.).
|
|
|
|
### Span Hierarchy
|
|
|
|
**Parent Spans (Operations):**
|
|
- `hindsight.retain` - Memory ingestion
|
|
- `hindsight.recall` - Memory retrieval
|
|
- `hindsight.recall_embedding` - Query embedding
|
|
- `hindsight.recall_retrieval` - Parallel search (semantic, BM25, graph, temporal)
|
|
- `hindsight.recall_fusion` - Reciprocal Rank Fusion
|
|
- `hindsight.recall_rerank` - Cross-encoder reranking
|
|
- `hindsight.reflect` - Agentic reasoning
|
|
- `hindsight.reflect_tool_call` - Tool execution (recall, lookup, etc.)
|
|
- `hindsight.consolidation` - Observation synthesis
|
|
- `hindsight.mental_model_refresh` - Mental model updates
|
|
|
|
**Child Spans (LLM Calls):**
|
|
- Named by scope (e.g., `hindsight.memory`, `hindsight.reflect`)
|
|
- Contain full prompts/completions as events
|
|
- Follow GenAI semantic conventions for attributes
|
|
|
|
### Span Attributes
|
|
|
|
**Operation Spans:**
|
|
- `hindsight.operation` - Operation type
|
|
- `hindsight.bank_id` - Memory bank ID
|
|
- `hindsight.query` - Query text (truncated to 100 chars)
|
|
- `hindsight.fact_types` - Fact types for recall
|
|
- `hindsight.thinking_budget` - Budget allocation
|
|
- `hindsight.max_tokens` - Token limit
|
|
|
|
**LLM Spans (GenAI Semantic Conventions):**
|
|
- `gen_ai.operation.name` - Always `"chat"`
|
|
- `gen_ai.provider.name` - Provider (`openai`, `anthropic`, `google`, etc.)
|
|
- `gen_ai.request.model` - Model name
|
|
- `gen_ai.usage.input_tokens` - Input tokens
|
|
- `gen_ai.usage.output_tokens` - Output tokens
|
|
- `hindsight.scope` - LLM call purpose (`memory`, `reflect`, `consolidation`, etc.)
|
|
|
|
**Events:**
|
|
- `gen_ai.client.inference.operation.details` - Full prompts and completions
|