1use axum::http::StatusCode;
2
3#[utoipa::path(
5 get,
6 path = "/api/help",
7 responses(
8 (status = 200, description = "Plain-text API reference")
9 ),
10 tag = "help"
11)]
12pub async fn api_help() -> (StatusCode, &'static str) {
13 (StatusCode::OK, HELP_TEXT)
14}
15
16const HELP_TEXT: &str = r#"Otelite API Quick Reference
17
18Base URL: http://localhost:3000/api
19
20=== Health ===
21GET /health
22 Returns service health status
23
24=== Logs ===
25GET /logs?severity=ERROR&search=timeout&limit=100&offset=0
26 Query parameters:
27 - severity: Filter by severity (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
28 - resource: Filter by resource attribute (format: key=value)
29 - search: Full-text search in log body
30 - query: Structured predicate; join several with '&&', e.g. 'body contains "timeout" && attributes.session.id = "abc"'. Returns 400 if malformed.
31 - start_time: Start time (Unix timestamp in nanoseconds)
32 - end_time: End time (Unix timestamp in nanoseconds)
33 - limit: Maximum results (default: 100, max: 1000)
34 - offset: Pagination offset (default: 0)
35
36GET /logs/{timestamp}
37 Get a specific log entry by timestamp
38
39GET /logs/export?format=json&severity=ERROR
40 Export logs in JSON or CSV format
41 Query parameters: same as /logs plus format (json or csv)
42
43=== Traces ===
44GET /traces?trace_id=abc123&service=my-service&limit=100
45 Query parameters:
46 - trace_id: Filter by trace ID
47 - service: Filter by service name
48 - search: Full-text search in span names
49 - query: Structured predicate; join several with '&&', e.g. 'name = "claude_code.llm_request" && attributes.attempt >= 2'. Returns 400 if malformed.
50 - start_time: Start time (Unix timestamp in nanoseconds)
51 - end_time: End time (Unix timestamp in nanoseconds)
52 - limit: Maximum results (default: 100, max: 1000)
53 - offset: Pagination offset (default: 0)
54
55GET /traces/{trace_id}
56 Get detailed trace with all spans
57
58GET /traces/export?format=json
59 Export traces in JSON format
60 Query parameters: same as /traces
61
62=== Metrics ===
63GET /metrics?name=http_requests&limit=100
64 Query parameters:
65 - name: Filter by metric name (partial match)
66 - resource: Filter by resource attribute (format: key=value)
67 - start_time: Start time (Unix timestamp in nanoseconds)
68 - end_time: End time (Unix timestamp in nanoseconds)
69 - limit: Maximum results (default: 100)
70 - offset: Pagination offset (default: 0)
71
72GET /metrics/names
73 Get list of unique metric names
74
75GET /metrics/aggregate?name=http_requests&function=sum&bucket_size=60
76 Aggregate metrics by function
77 Query parameters:
78 - name: Metric name to aggregate (required)
79 - function: Aggregation function (sum, avg, min, max) (required)
80 - bucket_size: Time bucket size in seconds (optional, for time-series)
81 - start_time: Start time (Unix timestamp in nanoseconds)
82 - end_time: End time (Unix timestamp in nanoseconds)
83
84GET /metrics/export?name=http_requests
85 Export metrics in JSON format
86 Query parameters: same as /metrics
87
88=== Documentation ===
89GET /api/openapi.json
90 OpenAPI 3.0 specification in JSON format
91
92GET /help
93 This plain-text reference guide
94
95=== Response Format ===
96All endpoints return JSON (except /help and exports)
97Error responses have format:
98{
99 "error": "Human-readable message",
100 "code": "ERROR_CODE",
101 "details": "Optional additional information"
102}
103
104=== Common Error Codes ===
105- BAD_REQUEST: Invalid query parameters
106- NOT_FOUND: Resource not found
107- INTERNAL_ERROR: Server error
108- STORAGE_ERROR: Database operation failed
109
110=== Time Format ===
111All timestamps are Unix nanoseconds (e.g., 1713628800000000000)
112To convert from seconds: multiply by 1_000_000_000
113"#;