fleet-memory/hindsight-api/tests
Nicolò Boschi 69dec8ec34
feat: add otel traceability (#330)
* feat: add comprehensive OpenTelemetry tracing

- Add tool execution spans for reflect operations
- Add tool call information (names, params) to spans
- Change verification scope from 'test' to 'verification'
- Add hindsight.reflect_generation span for done() processing
- Implement no-op tracer for improved code readability
- Update documentation for OTEL configuration
- Resolve merge conflicts from rebase

* fix: properly serialize Pydantic models in span recording

- Add _serialize_for_span() helper to handle Pydantic models
- Update all providers to use the helper function
- Fixes test failures with 'Object of type X is not JSON serializable'

* feat: add Grafana LGTM stack for unified local observability

Add Grafana LGTM (Loki, Grafana, Tempo, Mimir) as the recommended
local development observability stack. This provides traces, metrics,
and logs in a single Docker container instead of separate tools.

Changes:
- Add scripts/dev/grafana/ with docker-compose and README
- Add scripts/dev/start-grafana.sh startup script
- Update .env.example to reference Grafana LGTM
- Update configuration docs to emphasize Grafana LGTM as primary option
- Reorder OTLP backend list to show Grafana LGTM first

Benefits:
- Single container vs multiple separate tools (Jaeger, SigNoz, etc.)
- ~515MB image with full observability stack
- Compatible with existing OTLP configuration
- Simpler local development setup

* chore: remove SigNoz scripts and references

Remove SigNoz observability stack in favor of Grafana LGTM as the
sole recommended local development tracing solution.

Changes:
- Delete scripts/dev/signoz/ directory and all SigNoz configurations
- Delete scripts/dev/start-signoz.sh startup script
- Remove SigNoz references from .env.example
- Remove SigNoz from OTLP backends list in configuration docs

Grafana LGTM provides the same capabilities (traces, metrics, logs)
in a simpler single-container setup.

* feat: add consolidation span hierarchy for tracing

Add parent-child span structure for consolidation operations:
- hindsight.consolidation: Parent span for each memory being processed
- hindsight.consolidation_recall: Child span for finding related observations
- LLM call span: Automatically created by LLM provider (scope="consolidation")

This enables detailed timing breakdown in Grafana Tempo:
- Total consolidation time per memory
- Time spent in recall
- Time spent in LLM call
- Time spent executing actions (create/update)

All consolidation tests pass (31/31).

* feat: add Prometheus metrics and GenAI dashboard to Grafana stack

Add comprehensive metrics and dashboarding to the Grafana LGTM stack:

Metrics Collection:
- Configure Prometheus to scrape Hindsight API /metrics endpoint
- Scrape interval: 10 seconds
- Targets hindsight-api on host.docker.internal:8888

GenAI Dashboard:
- Pre-configured dashboard with 6 panels:
  - LLM call rate (by provider/model)
  - LLM call duration (p50/p95 by scope)
  - Token usage - input tokens/sec by scope
  - Token usage - output tokens/sec by scope
  - Operations rate (retain/recall/reflect/consolidation)
  - Operation duration p95 by operation type

Configuration:
- Mount prometheus.yml for metrics scraping
- Mount dashboards directory for auto-provisioning
- Add host.docker.internal mapping for container->host access
- Dashboard provisioning with auto-reload every 10s

Documentation:
- Updated README with metrics viewing instructions
- Added PromQL query examples
- Documented dashboard access and navigation

This provides full observability: traces (Tempo) + metrics (Prometheus/Mimir) + dashboards (Grafana)

* refactor: merge Grafana setup into existing monitoring stack

Consolidate the separate scripts/dev/grafana/ setup into the existing
scripts/dev/monitoring/ stack, using Grafana LGTM (Loki, Grafana, Tempo, Mimir).

Changes:
- Remove separate scripts/dev/grafana/ directory and start-grafana.sh
- Rewrite scripts/dev/monitoring/start.sh to use Docker + Grafana LGTM
  (was: download native Prometheus/Grafana binaries)
- Add docker-compose.yaml for Grafana LGTM container
- Add prometheus.yml for scraping Hindsight API metrics
- Mount existing dashboards from monitoring/grafana/dashboards/
- Add comprehensive README.md

Benefits:
- Single unified monitoring command: ./scripts/dev/start-monitoring.sh
- Uses existing dashboard files (hindsight-operations, hindsight-llm, hindsight-api-service)
- Simpler setup: Docker-based vs downloading/running native binaries
- Full observability: traces + metrics + logs + dashboards in one container
- Standard ports: Grafana on 3000, OTLP on 4317/4318

Architecture:
- Grafana LGTM container (~515MB) provides all components
- Dashboards auto-provisioned from monitoring/grafana/dashboards/
- Prometheus scrapes host.docker.internal:8888/metrics
- Shared hindsight-network for future service-to-service tracing

* fix: run monitoring stack in foreground for easy Ctrl+C stop

Change docker-compose from detached (-d) to foreground mode.
Users can now stop the stack with Ctrl+C instead of needing
to run docker-compose down separately.

* fix: remove invalid home dashboard path and obsolete version field

- Remove GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH environment variable
  (was pointing to wrong path causing 'Failed to load home dashboard' error)
- Remove obsolete 'version' field from docker-compose.yaml
  (docker-compose v2+ doesn't require version field)

* fix: load Hindsight dashboards in Grafana LGTM

Mount Hindsight dashboard JSON files and custom provisioning config
to make dashboards visible in Grafana.

Changes:
- Mount hindsight-operations.json, hindsight-llm.json, hindsight-api-service.json to /otel-lgtm/
- Create grafana-dashboards.yaml with all dashboard providers (default + Hindsight)
- Mount custom provisioning config to override LGTM default

All 3 Hindsight dashboards now appear in Grafana UI with metrics
from Prometheus scraping the Hindsight API /metrics endpoint.

* fix: configure Prometheus to scrape Hindsight API metrics

Update prometheus.yml to include both OTLP receiver config (from LGTM)
and scrape_configs for pulling metrics from Hindsight API.

Changes:
- Mount prometheus.yml to /otel-lgtm/prometheus.yaml (where LGTM reads it)
- Add scrape_configs section to pull from host.docker.internal:8888/metrics
- Keep OTLP receiver configuration for trace metrics
- Set scrape_interval to 5s

Verified: Prometheus now successfully scrapes hindsight_llm_calls_total
and other Hindsight metrics. Dashboards now show live data!

* feat: add comprehensive tracing for recall and improve reflect/mental_model_refresh spans

- Add recall operation tracing with parent-child span hierarchy
  - Parent: hindsight.recall with attributes (bank_id, query, fact_types, etc.)
  - Children: recall_embedding, recall_retrieval, recall_fusion, recall_rerank
  - Fixed context propagation using start_as_current_span()

- Improve reflect tracing spans
  - Remove reflect_generation spans, use reflect instead
  - Change done() tool processing to hindsight.reflect_tool_call

- Fix mental_model_refresh span nesting
  - Add _skip_span parameter to reflect_async to avoid duplicate hindsight.reflect spans
  - Mental model refresh now has clean span hierarchy without nested reflect parent

- Add comprehensive tracing verification tests
  - Test span hierarchy and attributes for all operations
  - Verify parent-child relationships
  - 5 passing tests covering recall, reflect, consolidation, and mental_model_refresh

* refactor: remove redundant is_tracing_enabled() checks

- Remove all is_tracing_enabled() conditional checks before tracing calls
- NoOpTracer/NoOpSpan handle disabled tracing automatically
- Simplify code by always calling tracer methods directly
- Fix NoOpTracer.start_as_current_span() to yield NoOpSpan instead of None

Changes:
- memory_engine.py: Remove 5 is_tracing_enabled checks in recall spans
- agent.py: Remove 2 is_tracing_enabled checks in reflect tool spans
- tracing.py: Fix NoOpTracer context manager to yield proper NoOpSpan

This eliminates ~50 lines of redundant conditional code while maintaining
identical behavior.

* docs: simplify distributed tracing section in monitoring.md

- Make tracing documentation more concise
- Focus on span hierarchy and attributes
- Remove verbose troubleshooting and performance sections
- Keep configuration.md for env vars only
2026-02-10 12:20:48 +01:00
..
fixtures rename to hindsight (#2) 2025-11-25 19:28:26 +01:00
__init__.py rename to hindsight (#2) 2025-11-25 19:28:26 +01:00
conftest.py fix: improve claude code and codex for /reflect (#285) 2026-02-04 13:34:45 +01:00
test_admin_backup_restore.py feat: run db migrations offline (optionally) (#114) 2026-01-07 15:49:51 +01:00
test_agents_api.py feat: introduce mental models (#132) 2026-01-16 11:16:41 +01:00
test_batch_chunking.py feat: extensions (#54) 2025-12-22 11:05:23 +01:00
test_causal_relations.py fix: duplicated causal relationships and token optimization (#126) 2026-01-08 14:43:48 +01:00
test_causal_relationships.py fix: duplicated causal relationships and token optimization (#126) 2026-01-08 14:43:48 +01:00
test_chunking.py improve retain performances, caching and tests 2025-12-08 18:21:56 +01:00
test_combined_scoring.py feat: extensions (#54) 2025-12-22 11:05:23 +01:00
test_config_validation.py fix: hindsight-embed profiles are not loaded correctly (#316) 2026-02-06 17:13:54 +01:00
test_consolidation.py fix: deadlock in worker polling (#250) 2026-01-30 11:09:29 +01:00
test_custom_embedding_dimension.py fix: improve mental model consolidation (#197) 2026-01-26 09:54:25 +01:00
test_document_tracking.py feat: extensions (#54) 2025-12-22 11:05:23 +01:00
test_extensions.py fix: improve mental model consolidation (#197) 2026-01-26 09:54:25 +01:00
test_fact_extraction_analysis.py chore: remove dead code (#245) 2026-01-30 09:16:32 +01:00
test_fact_extraction_output_ratio.py fix: misc perf improvements (#133) 2026-01-08 22:49:04 +01:00
test_fact_extraction_quality.py feat: introduce mental models (#132) 2026-01-16 11:16:41 +01:00
test_fact_ordering.py feat: introduce mental models (#132) 2026-01-16 11:16:41 +01:00
test_http_api_integration.py fix: retain async with timestamp might fails (#253) 2026-01-30 14:54:32 +01:00
test_link_expansion_retrieval.py fix: misc fixes for observations and mental models (#209) 2026-01-27 15:37:57 +01:00
test_link_utils.py prepare for release 2025-12-03 11:52:25 +01:00
test_llm_provider.py fix(ci): resolve flaky test failures in api tests (#311) 2026-02-06 13:56:59 +01:00
test_llm_token_metrics.py feat: support for codex and claude-code as llm (#276) 2026-02-02 12:54:44 +01:00
test_llm_tools.py chore: internal renames (#204) 2026-01-27 09:53:28 +01:00
test_load_large_batch.py feat: new 'worker' service (#176) 2026-01-20 10:17:56 +01:00
test_main_module.py fix: improve mental model consolidation (#197) 2026-01-26 09:54:25 +01:00
test_mcp_endpoint_routing.py feat: improve mcp tools based on endpoint (#318) 2026-02-08 09:28:59 +01:00
test_mcp_extension.py feat: add TenantExtension auth to MCP endpoint (#286) 2026-02-06 12:28:05 -07:00
test_mcp_local.py feat(mcp): add timestamp to retain (#190) 2026-01-23 16:00:43 +01:00
test_mcp_routing.py Fix MCP operations not tracked for usage metering (#334) 2026-02-10 09:38:15 +01:00
test_mcp_tools.py feat(mcp): add timestamp to retain (#190) 2026-01-23 16:00:43 +01:00
test_mental_model_hooks.py Add extension hooks for mental model operations (#260) 2026-01-31 09:30:53 -05:00
test_mental_models.py doc: prepare doc for 0.4.10 (#325) 2026-02-09 11:42:37 +01:00
test_metrics.py chore: remove dead code (#245) 2026-01-30 09:16:32 +01:00
test_mpfp_retrieval.py fix: improve mpfp retrieval (#146) 2026-01-12 18:58:05 +01:00
test_multilingual.py chore: remove dead code (#245) 2026-01-30 09:16:32 +01:00
test_observations.py chore: remove dead code (#245) 2026-01-30 09:16:32 +01:00
test_per_operation_llm_config.py feat: add more config options for llm retries (#234) 2026-01-29 17:50:43 +01:00
test_provider_default_models.py feat: support for codex and claude-code as llm (#276) 2026-02-02 12:54:44 +01:00
test_query_analyzer.py fix: ci and ui build (#9) 2025-12-03 15:47:53 +01:00
test_reflect_agent.py fix: graph endpoint not showing links for observations (#214) 2026-01-28 14:51:25 +01:00
test_reflect_tracing.py feat: add otel traceability (#330) 2026-02-10 12:20:48 +01:00
test_reflections.py feat: improve mental models ux on control plane (#297) 2026-02-04 15:49:03 +01:00
test_retain.py feat: ai sdk integration (#299) 2026-02-04 20:25:59 +01:00
test_schema_isolation.py fix: improve mental model consolidation (#197) 2026-01-26 09:54:25 +01:00
test_search_trace.py feat: extensions (#54) 2025-12-22 11:05:23 +01:00
test_server_module.py fix: improve mental model consolidation (#197) 2026-01-26 09:54:25 +01:00
test_sql_schema_safety.py chore: internal renames (#204) 2026-01-27 09:53:28 +01:00
test_supabase_tenant.py Add Supabase tenant extension as built-in (#267) 2026-02-09 10:16:47 +01:00
test_tags_visibility.py chore: cleanup benchmarks runner with old flags (#212) 2026-01-28 13:22:48 +01:00
test_tei_cross_encoder.py fix: add defensive error handling to PyTorch device detection (#221) 2026-01-28 18:14:54 +01:00
test_temporal_ranges.py feat(mcp): add timestamp to retain (#190) 2026-01-23 16:00:43 +01:00
test_think.py chore: remove dead code (#245) 2026-01-30 09:16:32 +01:00
test_tracing.py feat: add otel traceability (#330) 2026-02-10 12:20:48 +01:00
test_tracing_integration.py feat: add otel traceability (#330) 2026-02-10 12:20:48 +01:00
test_tracing_spans_verification.py feat: add otel traceability (#330) 2026-02-10 12:20:48 +01:00
test_vertexai_provider.py Switch Vertex AI provider to native genai SDK (#242) 2026-01-30 08:35:59 +01:00
test_worker.py fix: worker doesn't pick up correct default schema (#259) 2026-01-31 09:15:59 +01:00