-
Notifications
You must be signed in to change notification settings - Fork 0
observability_tracing
Stand: 22. Dezember 2025
Version: v1.3.0
Kategorie: 🔍 Observability
Themis unterstützt verteiltes Tracing via OpenTelemetry für Production-Debugging und Performance-Analyse.
- OTLP HTTP Exporter: Sendet Traces an Jaeger, Grafana Tempo oder andere OTLP-kompatible Backends
- RAII Span Management: Automatisches Span-Lifetime-Management via C++ RAII
- Conditional Compilation: Tracing kann zur Build-Zeit deaktiviert werden (kein Runtime-Overhead)
-
Flexible Configuration: Runtime-Konfiguration via
config.json
-
Tracer Wrapper (
utils/tracing.h/.cpp)- Initialisierung des OTLP HTTP Exporters
- TracerProvider mit Resource Attributes (service.name, version)
- SimpleSpanProcessor für sofortigen Export
-
Span RAII Wrapper
-
Tracer::Span: Move-only Span mit automatischemend()im Destruktor -
ScopedSpan: Convenience-Wrapper für lokale Spans - Attribute-Support:
setAttribute(key, value)für string, int64, double, bool
-
-
No-Op Fallback
- Wenn
THEMIS_ENABLE_TRACINGnicht definiert, sind alle Methoden No-Ops - Kein Linking gegen OpenTelemetry-Libraries notwendig
- Wenn
HTTP Request → ScopedSpan("handleAqlQuery")
↓
QueryEngine::executeQuery() → ScopedSpan("executeQuery")
↓
Index Scans → Child Spans
↓
OTLP HTTP Exporter → Jaeger/Tempo/Collector
In CMakeLists.txt:
option(THEMIS_ENABLE_TRACING "Enable OpenTelemetry distributed tracing" ON)Deaktivieren:
cmake -DTHEMIS_ENABLE_TRACING=OFF ..In config/config.json:
{
"tracing": {
"enabled": true,
"service_name": "themis-server",
"otlp_endpoint": "http://localhost:4318"
}
}Wichtig: otlp_endpoint ist der Base-URL des OTLP HTTP Receivers. Der Tracer fügt automatisch /v1/traces hinzu.
-
GET /entities/:key:
entity.key,entity.size_bytes -
PUT /entities/:key:
entity.key,entity.table,entity.pk,entity.size_bytes,entity.cdc_recorded -
DELETE /entities/:key:
entity.key,entity.table,entity.pk,entity.cdc_recorded -
POST /query:
query.table,query.predicates_count,query.exec_mode,query.result_count -
POST /query/aql:
aql.query,aql.explain,aql.optimize,aql.allow_full_scan,aql.result_count -
POST /graph/traverse:
graph.start_vertex,graph.max_depth,graph.visited_count -
POST /vector/search:
vector.dimension,vector.k,vector.results_count
-
QueryEngine.executeAndKeys:
query.table,query.eq_count,query.range_count,query.order_by,query.result_count -
QueryEngine.executeAndEntities:
query.table,query.entities_count -
QueryEngine.executeOrKeys:
query.table,query.disjuncts,query.result_count -
QueryEngine.executeOrEntities:
query.table,query.entities_count -
QueryEngine.executeAndKeysSequential:
query.table,query.eq_count,query.result_count -
QueryEngine.executeAndEntitiesSequential:
query.table,query.entities_count -
QueryEngine.fullScan:
query.table,query.eq_count,query.range_count,fullscan.scanned,query.result_count -
QueryEngine.executeAndKeysWithFallback:
query.table,query.exec_mode(full_scan, range_aware, index_optimized, index_parallel, full_scan_fallback),query.result_count -
QueryEngine.executeAndEntitiesWithFallback:
query.table,query.entities_count -
QueryEngine.executeAndKeysRangeAware:
query.table,query.range_count,query.result_countoderquery.ordered_count -
QueryEngine.executeAndEntitiesRangeAware:
query.table,query.entities_count
-
aql.parse:
aql.query_length- Parsen der AQL-Query in AST - aql.translate - Übersetzung des AST in ConjunctiveQuery oder TraversalQuery
-
aql.for:
for.table,for.predicates_count,for.range_predicates_count,for.order_by,for.order_desc,for.result_count,for.exec_mode- Iteriert über Collection (scan oder traversal)
-
aql.filter - Filterung der Ergebnisse (innerhalb von Traversal/FOR)
- Bei Traversal:
filter.evaluations_total,filter.short_circuits
- Bei Traversal:
-
aql.limit:
limit.offset,limit.count,limit.input_count,limit.output_count- Begrenzt Ergebnismenge (LIMIT offset, count)
-
aql.collect:
collect.input_count,collect.group_by_count,collect.aggregates_count,collect.group_count- Gruppierung und Aggregation (GROUP BY, SUM, AVG, COUNT, MIN, MAX)
-
aql.return:
return.input_count- Finalisiert Ausgabe und serialisiert Entities
-
aql.traversal:
traversal.start_vertex,traversal.min_depth,traversal.max_depth,traversal.direction,traversal.result_count- Child-Span: aql.traversal.bfs:
traversal.max_frontier_size_limit,traversal.max_results_limit,traversal.visited_count,traversal.edges_expanded,traversal.filter_evaluations
- Child-Span: aql.traversal.bfs:
-
index.scanEqual:
index.table,index.column,index.result_count -
index.scanRange:
index.table,index.column,index.result_count,range.has_lower,range.has_upper,range.includeLower,range.includeUpper -
or.disjunct.execute:
disjunct.eq_count,disjunct.range_count,disjunct.result_count
Diese Spans erlauben die Analyse von Ausführungsmodus, Cardinalities und Hotspots pro Prädikat/Operator.
#include "utils/tracing.h"
void handleAqlQuery(const Request& req, Response& res) {
auto span = Tracer::ScopedSpan("handleAqlQuery");
span.setAttribute("http.method", "POST");
span.setAttribute("http.path", "/aql");
try {
// ... query execution ...
span.setAttribute("query.table", tableName);
span.setStatus(true);
} catch (const std::exception& e) {
span.recordError(e.what());
span.setStatus(false, e.what());
throw;
}
}void QueryEngine::executeQuery(...) {
auto parentSpan = Tracer::ScopedSpan("executeQuery");
{
auto childSpan = Tracer::startSpan("loadIndexes");
childSpan.setAttribute("index.count", indexCount);
// ... index loading ...
} // childSpan endet automatisch
// ... weiter mit parentSpan ...
}try {
// ... operation ...
} catch (const std::exception& e) {
span.recordError(e.what());
span.setStatus(false, errorMessage);
throw;
}docker run -d --name jaeger \
-p 4318:4318 \
-p 16686:16686 \
jaegertracing/all-in-one:latestPorts:
-
4318: OTLP HTTP receiver (für Themis) -
16686: Jaeger UI
{
"tracing": {
"enabled": true,
"service_name": "themis-dev",
"otlp_endpoint": "http://localhost:4318"
}
}.\build\Release\themis_server.exe- Öffne http://localhost:16686 (Jaeger UI)
- Wähle Service "themis-dev"
- Klicke "Find Traces"
version: '3'
services:
tempo:
image: grafana/tempo:latest
command: ["-config.file=/etc/tempo.yaml"]
volumes:
- ./tempo.yaml:/etc/tempo.yaml
ports:
- "4318:4318" # OTLP HTTP
- "3200:3200" # Tempo API
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_AUTH_ANONYMOUS_ENABLED=truetempo.yaml:
server:
http_listen_port: 3200
distributor:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
storage:
trace:
backend: local
local:
path: /tmp/tempo/traces- Öffne http://localhost:3000
- Configuration → Data Sources → Add data source
- Wähle "Tempo"
- URL:
http://tempo:3200 - Save & Test
- Mit Tracing aktiviert: ~5-10 µs pro Span (inkl. Attribut-Serialisierung)
- Ohne Tracing (THEMIS_ENABLE_TRACING=OFF): 0 µs (inline no-ops)
- Granularität: Erstelle Spans für HTTP-Requests, Query-Execution, Index-Scans
- Attribute: Füge relevante Metadaten hinzu (table, index_type, row_count)
- Sampling (zukünftig): Für High-Throughput-Szenarien Sampling verwenden
- Batch Processor (zukünftig): SimpleSpanProcessor → BatchSpanProcessor für bessere Performance
bool Tracer::initialize(const std::string& serviceName,
const std::string& endpoint);Initialisiert den OpenTelemetry Tracer mit OTLP HTTP Exporter.
Parameter:
-
serviceName: Name des Services (erscheint in Jaeger/Tempo) -
endpoint: OTLP HTTP Receiver URL (z.B.http://localhost:4318)
Returns: true bei Erfolg, false bei Fehler
Tracer::Span Tracer::startSpan(const std::string& name);Erstellt einen neuen Span mit dem gegebenen Namen.
Returns: Move-only Span Objekt
Tracer::ScopedSpan span("operationName");
span.setAttribute("key", "value");RAII-Wrapper für automatisches Span-Lifetime-Management.
void setAttribute(const std::string& key, const std::string& value);
void setAttribute(const std::string& key, int64_t value);
void setAttribute(const std::string& key, double value);
void setAttribute(const std::string& key, bool value);Fügt Attribute zum Span hinzu.
void recordError(const std::string& errorMessage);Zeichnet einen Fehler auf und setzt den Span-Status auf kError.
void setStatus(StatusCode code);Setzt den Span-Status (kOk, kError, kUnset).
Symptom: Log-Meldung "Tracer not initialized, call Tracer::initialize() first"
Lösung: Stelle sicher, dass Tracer::initialize() vor dem ersten startSpan() aufgerufen wird.
Prüfe:
- Läuft Jaeger?
docker ps | grep jaeger - Ist Tracing aktiviert?
"tracing.enabled": truein config.json - Richtiger Endpoint?
http://localhost:4318(nicht 4317 für gRPC!) - Firewall/Network-Einstellungen
Debug:
# Log-Level auf DEBUG setzen in config.json
"log_level": "debug"
# Themis-Logs prüfen
grep -i "telemetry\|tracer\|span" themis.logSymptom: error: opentelemetry/... not found
Lösung:
# vcpkg-Cache löschen und neu installieren
rm -rf build/vcpkg_installed
.\build.ps1- ✅ Infrastruktur: Tracer-Wrapper, OTLP HTTP Exporter
- ✅ Configuration: config.json + CMake-Option
- ✅ Build: Kompiliert mit opentelemetry-cpp v1.23.0
- ✅ Tests: 303/303 Tests bestanden
⚠️ Instrumentierung: HTTP-Handler noch nicht instrumentiert⚠️ Dokumentation: Deployment-Guide für Production
-
HTTP-Handler instrumentieren: Spans für alle
/aql,/vector,/graphEndpoints - Query-Engine instrumentieren: Child Spans für Index-Scans, Filter-Operationen
- Sampling implementieren: Probabilistic Sampling für High-Throughput
- BatchSpanProcessor: Performance-Optimierung für Production
- Context Propagation: W3C Trace Context für verteilte Systeme
ThemisDB v1.3.4 | GitHub | Documentation | Discussions | License
Last synced: January 02, 2026 | Commit: 6add659
Version: 1.3.0 | Stand: Dezember 2025
- Übersicht
- Home
- Dokumentations-Index
- Quick Reference
- Sachstandsbericht 2025
- Features
- Roadmap
- Ecosystem Overview
- Strategische Übersicht
- Geo/Relational Storage
- RocksDB Storage
- MVCC Design
- Transaktionen
- Time-Series
- Memory Tuning
- Chain of Thought Storage
- Query Engine & AQL
- AQL Syntax
- Explain & Profile
- Rekursive Pfadabfragen
- Temporale Graphen
- Zeitbereichs-Abfragen
- Semantischer Cache
- Hybrid Queries (Phase 1.5)
- AQL Hybrid Queries
- Hybrid Queries README
- Hybrid Query Benchmarks
- Subquery Quick Reference
- Subquery Implementation
- Content Pipeline
- Architektur-Details
- Ingestion
- JSON Ingestion Spec
- Enterprise Ingestion Interface
- Geo-Processor Design
- Image-Processor Design
- Hybrid Search Design
- Fulltext API
- Hybrid Fusion API
- Stemming
- Performance Tuning
- Migration Guide
- Future Work
- Pagination Benchmarks
- Enterprise README
- Scalability Features
- HTTP Client Pool
- Build Guide
- Implementation Status
- Final Report
- Integration Analysis
- Enterprise Strategy
- Verschlüsselungsstrategie
- Verschlüsselungsdeployment
- Spaltenverschlüsselung
- Encryption Next Steps
- Multi-Party Encryption
- Key Rotation Strategy
- Security Encryption Gap Analysis
- Audit Logging
- Audit & Retention
- Compliance Audit
- Compliance
- Extended Compliance Features
- Governance-Strategie
- Compliance-Integration
- Governance Usage
- Security/Compliance Review
- Threat Model
- Security Hardening Guide
- Security Audit Checklist
- Security Audit Report
- Security Implementation
- Development README
- Code Quality Pipeline
- Developers Guide
- Cost Models
- Todo Liste
- Tool Todo
- Core Feature Todo
- Priorities
- Implementation Status
- Roadmap
- Future Work
- Next Steps Analysis
- AQL LET Implementation
- Development Audit
- Sprint Summary (2025-11-17)
- WAL Archiving
- Search Gap Analysis
- Source Documentation Plan
- Changefeed README
- Changefeed CMake Patch
- Changefeed OpenAPI
- Changefeed OpenAPI Auth
- Changefeed SSE Examples
- Changefeed Test Harness
- Changefeed Tests
- Dokumentations-Inventar
- Documentation Summary
- Documentation TODO
- Documentation Gap Analysis
- Documentation Consolidation
- Documentation Final Status
- Documentation Phase 3
- Documentation Cleanup Validation
- API
- Authentication
- Cache
- CDC
- Content
- Geo
- Governance
- Index
- LLM
- Query
- Security
- Server
- Storage
- Time Series
- Transaction
- Utils
Vollständige Dokumentation: https://makr-code.github.io/ThemisDB/