drtrace 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -4
- package/agents/CONTRIBUTING.md +296 -0
- package/agents/README.md +174 -0
- package/agents/daemon-method-selection.md +370 -0
- package/agents/integration-guides/cpp-best-practices.md +218 -0
- package/agents/integration-guides/cpp-ros-integration.md +88 -0
- package/agents/log-analysis.md +218 -0
- package/agents/log-help.md +226 -0
- package/agents/log-init.md +933 -0
- package/agents/log-it.md +1126 -0
- package/bin/init.js +4 -4
- package/dist/bin/init.js +31 -0
- package/dist/browser.d.ts +28 -0
- package/dist/browser.js +91 -0
- package/dist/config-schema.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/init.d.ts +44 -2
- package/dist/init.js +460 -30
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +30 -4
- package/dist/node.d.ts +13 -0
- package/dist/node.js +67 -0
- package/dist/resources/agents/CONTRIBUTING.md +296 -0
- package/dist/resources/agents/README.md +174 -0
- package/dist/resources/agents/daemon-method-selection.md +370 -0
- package/dist/resources/agents/integration-guides/cpp-best-practices.md +218 -0
- package/dist/resources/agents/integration-guides/cpp-ros-integration.md +88 -0
- package/dist/resources/agents/log-analysis.md +218 -0
- package/dist/resources/agents/log-help.md +226 -0
- package/dist/resources/agents/log-init.md +933 -0
- package/dist/resources/agents/log-it.md +1126 -0
- package/dist/resources/cpp/drtrace_sink.hpp +1249 -0
- package/dist/transport.js +5 -1
- package/dist/types.d.ts +8 -2
- package/package.json +28 -4
- package/.eslintrc.js +0 -20
- package/jest.config.js +0 -11
- package/src/client.ts +0 -68
- package/src/config-schema.ts +0 -115
- package/src/config.ts +0 -326
- package/src/index.ts +0 -3
- package/src/init.ts +0 -451
- package/src/logger.ts +0 -56
- package/src/queue.ts +0 -105
- package/src/transport.ts +0 -60
- package/src/types.ts +0 -20
- package/tests/client.test.ts +0 -66
- package/tests/config-schema.test.ts +0 -198
- package/tests/config.test.ts +0 -456
- package/tests/queue.test.ts +0 -72
- package/tests/transport.test.ts +0 -52
- package/tsconfig.json +0 -18
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
# Daemon Method Selection Guide
|
|
2
|
+
|
|
3
|
+
**Purpose**: Guide for AI agents to choose the right method for daemon interaction.
|
|
4
|
+
|
|
5
|
+
**Key Principle**: For AI agents, prefer **HTTP/curl first** (simpler, no dependencies), then Python, then CLI.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Priority Order for AI Agents
|
|
10
|
+
|
|
11
|
+
| Priority | Method | When to Use |
|
|
12
|
+
|----------|--------|-------------|
|
|
13
|
+
| **1st** | HTTP/curl | Default - works without dependencies |
|
|
14
|
+
| **2nd** | Python code | When rich SDK features needed |
|
|
15
|
+
| **3rd** | CLI commands | Last resort - requires subprocess |
|
|
16
|
+
|
|
17
|
+
### Why HTTP-First for AI Agents?
|
|
18
|
+
|
|
19
|
+
- **No dependencies**: Just HTTP requests - works in any environment
|
|
20
|
+
- **Simpler**: curl commands are self-contained and portable
|
|
21
|
+
- **Faster**: No import overhead or Python interpreter startup
|
|
22
|
+
- **Universal**: Works from any language or tool
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Discovery First: OpenAPI Schema
|
|
27
|
+
|
|
28
|
+
**CRITICAL**: Before making any API call, fetch `/openapi.json` to discover:
|
|
29
|
+
- Available endpoints
|
|
30
|
+
- Correct field names (e.g., `ts` not `timestamp`)
|
|
31
|
+
- Request/response schemas
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Always fetch schema first
|
|
35
|
+
curl http://localhost:8001/openapi.json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import requests
|
|
40
|
+
|
|
41
|
+
base_url = "http://localhost:8001"
|
|
42
|
+
|
|
43
|
+
# Fetch schema to discover endpoints and field names
|
|
44
|
+
schema = requests.get(f"{base_url}/openapi.json", timeout=5).json()
|
|
45
|
+
paths = schema.get("paths", {})
|
|
46
|
+
components = schema.get("components", {}).get("schemas", {})
|
|
47
|
+
|
|
48
|
+
# Use discovered field names, not hardcoded ones
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Why this matters**: API field names can change between versions. Using OpenAPI ensures compatibility.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Method 1: HTTP/curl (Preferred)
|
|
56
|
+
|
|
57
|
+
### Check Daemon Status
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
curl http://localhost:8001/status
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Query Logs
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Get logs from last 5 minutes
|
|
67
|
+
START_TS=$(python3 -c "import time; print(time.time() - 300)")
|
|
68
|
+
END_TS=$(python3 -c "import time; print(time.time())")
|
|
69
|
+
|
|
70
|
+
curl "http://localhost:8001/logs/query?start_ts=${START_TS}&end_ts=${END_TS}&application_id=myapp&limit=100"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Root Cause Analysis
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
curl "http://localhost:8001/analysis/why?application_id=myapp&start_ts=${START_TS}&end_ts=${END_TS}&min_level=ERROR"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Python requests (HTTP method)
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import requests
|
|
83
|
+
import time
|
|
84
|
+
|
|
85
|
+
base_url = "http://localhost:8001"
|
|
86
|
+
|
|
87
|
+
# Step 1: Check daemon status
|
|
88
|
+
try:
|
|
89
|
+
status = requests.get(f"{base_url}/status", timeout=2)
|
|
90
|
+
if status.status_code != 200:
|
|
91
|
+
print("Daemon not available")
|
|
92
|
+
except requests.exceptions.RequestException:
|
|
93
|
+
print("Daemon not reachable")
|
|
94
|
+
|
|
95
|
+
# Step 2: Query logs
|
|
96
|
+
now = time.time()
|
|
97
|
+
params = {
|
|
98
|
+
"start_ts": now - 300, # 5 minutes ago
|
|
99
|
+
"end_ts": now,
|
|
100
|
+
"application_id": "myapp",
|
|
101
|
+
"limit": 100
|
|
102
|
+
}
|
|
103
|
+
response = requests.get(f"{base_url}/logs/query", params=params, timeout=10)
|
|
104
|
+
logs = response.json().get("results", [])
|
|
105
|
+
|
|
106
|
+
# Step 3: Process using field names from OpenAPI schema
|
|
107
|
+
for log in logs:
|
|
108
|
+
ts = log.get("ts") # Use 'ts' not 'timestamp' (from schema)
|
|
109
|
+
level = log.get("level")
|
|
110
|
+
message = log.get("message")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Method 2: Python Code (Fallback)
|
|
116
|
+
|
|
117
|
+
Use when you need rich SDK features or the HTTP method fails.
|
|
118
|
+
|
|
119
|
+
### Log Analysis
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from drtrace_service.agent_interface import process_agent_query, check_daemon_status
|
|
123
|
+
import asyncio
|
|
124
|
+
|
|
125
|
+
# Check daemon first
|
|
126
|
+
status = await check_daemon_status()
|
|
127
|
+
if not status.get("available"):
|
|
128
|
+
print("Daemon not available")
|
|
129
|
+
|
|
130
|
+
# Process query - returns formatted markdown
|
|
131
|
+
response = await process_agent_query("explain error from 9:00 to 10:00 for app myapp")
|
|
132
|
+
print(response)
|
|
133
|
+
|
|
134
|
+
# Non-async context
|
|
135
|
+
response = asyncio.run(process_agent_query("show logs from last 5 minutes"))
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Setup Help
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from drtrace_service.help_agent_interface import (
|
|
142
|
+
start_setup_guide,
|
|
143
|
+
get_current_step,
|
|
144
|
+
complete_step,
|
|
145
|
+
troubleshoot,
|
|
146
|
+
)
|
|
147
|
+
from pathlib import Path
|
|
148
|
+
import asyncio
|
|
149
|
+
|
|
150
|
+
project_root = Path(".")
|
|
151
|
+
|
|
152
|
+
# Start setup guide
|
|
153
|
+
guide = await start_setup_guide(language="python", project_root=project_root)
|
|
154
|
+
|
|
155
|
+
# Get current step
|
|
156
|
+
current = await get_current_step(project_root=project_root)
|
|
157
|
+
|
|
158
|
+
# Mark step complete
|
|
159
|
+
next_step = await complete_step(step_number=1, project_root=project_root)
|
|
160
|
+
|
|
161
|
+
# Troubleshoot
|
|
162
|
+
help_text = await troubleshoot("daemon not connecting", project_root=project_root)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Setup Suggestions
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from drtrace_service.setup_agent_interface import analyze_and_suggest, suggest_for_language
|
|
169
|
+
from pathlib import Path
|
|
170
|
+
import asyncio
|
|
171
|
+
|
|
172
|
+
project_root = Path(".")
|
|
173
|
+
|
|
174
|
+
# Get setup suggestions
|
|
175
|
+
suggestions = await analyze_and_suggest(project_root)
|
|
176
|
+
|
|
177
|
+
# Language-specific suggestions
|
|
178
|
+
python_suggestions = await suggest_for_language("python", project_root)
|
|
179
|
+
cpp_suggestions = await suggest_for_language("cpp", project_root)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Method 3: CLI Commands (Last Resort)
|
|
185
|
+
|
|
186
|
+
Use only when HTTP and Python methods are unavailable.
|
|
187
|
+
|
|
188
|
+
### Check Status
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
python -m drtrace_service status
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Analyze Errors
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
python -m drtrace_service why --application-id myapp --since 5m --min-level ERROR
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Setup Help
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
python -m drtrace_service help guide start --language python --project-root /path/to/project
|
|
204
|
+
python -m drtrace_service help guide current --project-root /path/to/project
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Error Handling and Fallback Chain
|
|
210
|
+
|
|
211
|
+
```python
|
|
212
|
+
import requests
|
|
213
|
+
|
|
214
|
+
def interact_with_daemon(query: str) -> str:
|
|
215
|
+
"""Try methods in order: HTTP -> Python -> CLI"""
|
|
216
|
+
base_url = "http://localhost:8001"
|
|
217
|
+
|
|
218
|
+
# Method 1: HTTP (Preferred)
|
|
219
|
+
try:
|
|
220
|
+
# Check status first
|
|
221
|
+
status = requests.get(f"{base_url}/status", timeout=2)
|
|
222
|
+
if status.status_code == 200:
|
|
223
|
+
# Make actual request...
|
|
224
|
+
return "Success via HTTP"
|
|
225
|
+
except requests.exceptions.RequestException:
|
|
226
|
+
pass # Fall through to Python
|
|
227
|
+
|
|
228
|
+
# Method 2: Python (Fallback)
|
|
229
|
+
try:
|
|
230
|
+
from drtrace_service.agent_interface import process_agent_query
|
|
231
|
+
import asyncio
|
|
232
|
+
response = asyncio.run(process_agent_query(query))
|
|
233
|
+
return response
|
|
234
|
+
except ImportError:
|
|
235
|
+
pass # Fall through to CLI
|
|
236
|
+
|
|
237
|
+
# Method 3: CLI (Last Resort)
|
|
238
|
+
import subprocess
|
|
239
|
+
result = subprocess.run(
|
|
240
|
+
["python", "-m", "drtrace_service", "status"],
|
|
241
|
+
capture_output=True,
|
|
242
|
+
text=True
|
|
243
|
+
)
|
|
244
|
+
if result.returncode == 0:
|
|
245
|
+
return result.stdout
|
|
246
|
+
|
|
247
|
+
# All methods failed
|
|
248
|
+
return """
|
|
249
|
+
Daemon is not available.
|
|
250
|
+
|
|
251
|
+
Next Steps:
|
|
252
|
+
1. Start daemon: python -m drtrace_service
|
|
253
|
+
2. Verify: curl http://localhost:8001/status
|
|
254
|
+
"""
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## When to Use Each Method
|
|
260
|
+
|
|
261
|
+
| Scenario | Recommended Method |
|
|
262
|
+
|----------|-------------------|
|
|
263
|
+
| Simple queries (status, logs) | HTTP/curl |
|
|
264
|
+
| Complex analysis | HTTP or Python |
|
|
265
|
+
| Rich markdown output needed | Python SDK |
|
|
266
|
+
| Running outside Python | HTTP/curl |
|
|
267
|
+
| Setup guide interaction | Python SDK |
|
|
268
|
+
| Debugging integration | CLI commands |
|
|
269
|
+
| Script automation | HTTP/curl |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Quick Reference: Common Endpoints
|
|
274
|
+
|
|
275
|
+
**Note**: Always verify via `/openapi.json` - this list is for reference only.
|
|
276
|
+
|
|
277
|
+
| Endpoint | Method | Purpose |
|
|
278
|
+
|----------|--------|---------|
|
|
279
|
+
| `/status` | GET | Health check |
|
|
280
|
+
| `/openapi.json` | GET | API schema |
|
|
281
|
+
| `/logs/query` | GET | Query logs |
|
|
282
|
+
| `/logs/ingest` | POST | Ingest logs |
|
|
283
|
+
| `/analysis/why` | GET | Root cause analysis |
|
|
284
|
+
| `/analysis/time-range` | GET | Time range analysis |
|
|
285
|
+
| `/help/guide/start` | POST | Start setup guide |
|
|
286
|
+
| `/help/guide/current` | GET | Current setup step |
|
|
287
|
+
| `/help/troubleshoot` | POST | Troubleshooting help |
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Important: Timestamps Are UTC
|
|
292
|
+
|
|
293
|
+
All timestamps in DrTrace API are **UTC Unix timestamps**:
|
|
294
|
+
|
|
295
|
+
| Field/Param | Format | Timezone |
|
|
296
|
+
|-------------|--------|----------|
|
|
297
|
+
| `ts` (in logs) | Unix float | UTC |
|
|
298
|
+
| `start_ts`, `end_ts` | Unix float | UTC |
|
|
299
|
+
| `since`, `until` | Relative or ISO 8601 | UTC |
|
|
300
|
+
|
|
301
|
+
**Key Rules**:
|
|
302
|
+
- ISO 8601 without timezone (e.g., `2025-12-31T02:44:03`) is interpreted as **UTC**, not local time
|
|
303
|
+
- Relative times (`5m`, `1h`) are relative to server's current UTC time
|
|
304
|
+
- To query with local time, include timezone offset: `2025-12-31T09:44:03+07:00`
|
|
305
|
+
|
|
306
|
+
### Converting Local Time to UTC
|
|
307
|
+
|
|
308
|
+
**Python:**
|
|
309
|
+
```python
|
|
310
|
+
from datetime import datetime, timezone, timedelta
|
|
311
|
+
|
|
312
|
+
# Local time (e.g., 2025-12-31 09:44:03 in GMT+7)
|
|
313
|
+
local_time = datetime(2025, 12, 31, 9, 44, 3)
|
|
314
|
+
|
|
315
|
+
# Method 1: If you know your timezone offset
|
|
316
|
+
local_tz = timezone(timedelta(hours=7)) # GMT+7
|
|
317
|
+
local_aware = local_time.replace(tzinfo=local_tz)
|
|
318
|
+
utc_time = local_aware.astimezone(timezone.utc)
|
|
319
|
+
unix_ts = utc_time.timestamp()
|
|
320
|
+
print(f"UTC Unix timestamp: {unix_ts}")
|
|
321
|
+
|
|
322
|
+
# Method 2: Using system timezone
|
|
323
|
+
import time
|
|
324
|
+
unix_ts = time.mktime(local_time.timetuple())
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Bash:**
|
|
328
|
+
```bash
|
|
329
|
+
# Convert local time to Unix timestamp
|
|
330
|
+
date -d "2025-12-31 09:44:03" +%s
|
|
331
|
+
|
|
332
|
+
# Convert with explicit timezone
|
|
333
|
+
TZ=UTC date -d "2025-12-31T02:44:03" +%s
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### API Query Examples with Timezone
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Option 1: Include timezone in ISO 8601 (recommended for local time)
|
|
340
|
+
curl "http://localhost:8001/logs/query?since=2025-12-31T09:44:03%2B07:00"
|
|
341
|
+
|
|
342
|
+
# Option 2: Use relative time (always relative to server UTC time)
|
|
343
|
+
curl "http://localhost:8001/logs/query?since=5m"
|
|
344
|
+
|
|
345
|
+
# Option 3: Convert to UTC Unix timestamp first
|
|
346
|
+
UTC_TS=$(TZ=UTC date -d "2025-12-31T02:44:03" +%s)
|
|
347
|
+
curl "http://localhost:8001/logs/query?start_ts=$UTC_TS"
|
|
348
|
+
|
|
349
|
+
# Option 4: Use ISO 8601 in UTC (note: no timezone = UTC)
|
|
350
|
+
curl "http://localhost:8001/logs/query?since=2025-12-31T02:44:03"
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Common Timezone Pitfalls
|
|
354
|
+
|
|
355
|
+
1. **ISO 8601 Without Timezone**: Interpreted as UTC, not local time. If you pass `2025-12-31T09:44:03` thinking it's local 9:44 AM, it will be treated as 9:44 AM UTC.
|
|
356
|
+
|
|
357
|
+
2. **Server vs Client Timezone**: If your server is in a different timezone than your client, always use explicit UTC timestamps or include timezone offsets.
|
|
358
|
+
|
|
359
|
+
3. **Relative Times**: `since=5m` means 5 minutes before server's current UTC time, regardless of your local timezone.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Related Documentation
|
|
364
|
+
|
|
365
|
+
- `docs/daemon-interaction-guide.md` - OpenAPI discovery details
|
|
366
|
+
- `docs/api-reference.md` - Complete API reference
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
**Last Updated**: 2025-12-31
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# C++ DrTrace Best Practices
|
|
2
|
+
|
|
3
|
+
This guide provides best practices for configuring DrTrace in C++ applications.
|
|
4
|
+
|
|
5
|
+
## Crash-Safe Logging
|
|
6
|
+
|
|
7
|
+
For applications where crash logs are critical (robotics, autonomous systems, safety-critical software):
|
|
8
|
+
|
|
9
|
+
### Configuration Options
|
|
10
|
+
|
|
11
|
+
| Configuration | Crash Safety | Network Overhead | Use Case |
|
|
12
|
+
|---------------|--------------|------------------|----------|
|
|
13
|
+
| `batch_size=1` | Highest | Highest | Safety-critical systems |
|
|
14
|
+
| `batch_size=5`, `flush=1s` | Medium | Medium | Important crash debugging |
|
|
15
|
+
| `batch_size=10`, `flush=5s` (default) | Lower | Lowest | General applications |
|
|
16
|
+
|
|
17
|
+
### Example: Safety-Critical Configuration
|
|
18
|
+
|
|
19
|
+
```cpp
|
|
20
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
21
|
+
|
|
22
|
+
// For safety-critical applications: immediate send
|
|
23
|
+
config.batch_size = 1; // Each log sent immediately
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Example: Balanced Configuration
|
|
27
|
+
|
|
28
|
+
```cpp
|
|
29
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
30
|
+
|
|
31
|
+
// Balanced approach
|
|
32
|
+
config.batch_size = 5;
|
|
33
|
+
config.flush_interval = std::chrono::milliseconds(1000); // 1 second
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Recommendation
|
|
37
|
+
|
|
38
|
+
For most applications, the default configuration is appropriate. Only reduce batch size if:
|
|
39
|
+
- Crash debugging is a primary concern
|
|
40
|
+
- You're willing to accept higher network overhead
|
|
41
|
+
- The application is safety-critical
|
|
42
|
+
|
|
43
|
+
**Note:** Signal handlers are inherently unsafe in C++. Rather than implementing partial solutions, we recommend configuring `batch_size=1` for applications where crash logs are critical.
|
|
44
|
+
|
|
45
|
+
## Log Level Filtering
|
|
46
|
+
|
|
47
|
+
Filter logs at the client to reduce network overhead in production:
|
|
48
|
+
|
|
49
|
+
```cpp
|
|
50
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
51
|
+
|
|
52
|
+
// Only send WARN and above in production
|
|
53
|
+
config.min_level = drtrace::core::LogLevel::WARN;
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Or via environment variable:
|
|
57
|
+
```bash
|
|
58
|
+
export DRTRACE_MIN_LEVEL=warn
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Available Levels
|
|
62
|
+
|
|
63
|
+
| Level | Value | Description |
|
|
64
|
+
|-------|-------|-------------|
|
|
65
|
+
| DEBUG | 0 | Detailed debugging information |
|
|
66
|
+
| INFO | 1 | General operational messages |
|
|
67
|
+
| WARN | 2 | Warning conditions |
|
|
68
|
+
| ERROR | 3 | Error conditions |
|
|
69
|
+
| CRITICAL | 4 | Critical failures |
|
|
70
|
+
|
|
71
|
+
## Buffer Size Limits
|
|
72
|
+
|
|
73
|
+
Prevent memory issues when daemon is unavailable:
|
|
74
|
+
|
|
75
|
+
```cpp
|
|
76
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
77
|
+
|
|
78
|
+
// Limit buffer to 10000 logs (drop oldest when full)
|
|
79
|
+
config.max_buffer_size = 10000;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or via environment variable:
|
|
83
|
+
```bash
|
|
84
|
+
export DRTRACE_MAX_BUFFER_SIZE=10000
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Behavior
|
|
88
|
+
|
|
89
|
+
- When buffer is full, **oldest logs are dropped** to make room for new ones
|
|
90
|
+
- Set to `0` for unlimited buffer (not recommended for production)
|
|
91
|
+
- Default: 10000 logs
|
|
92
|
+
|
|
93
|
+
### Memory Estimation
|
|
94
|
+
|
|
95
|
+
Each log record is approximately 200-500 bytes in memory. With default 10000 buffer:
|
|
96
|
+
- Minimum: ~2 MB
|
|
97
|
+
- Maximum: ~5 MB
|
|
98
|
+
|
|
99
|
+
## Circuit Breaker Behavior
|
|
100
|
+
|
|
101
|
+
The DrTrace client uses a circuit breaker pattern to maintain consistent performance:
|
|
102
|
+
|
|
103
|
+
### How It Works
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
CLOSED (normal) ──[failure]──> OPEN (fast-fail)
|
|
107
|
+
^ │
|
|
108
|
+
│ [cooldown expires]
|
|
109
|
+
│ v
|
|
110
|
+
└────[success]───────── HALF-OPEN (probe)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
- **CLOSED**: Normal operation, requests go through
|
|
114
|
+
- **OPEN**: After failure, all requests fast-fail (< 1us) for 30 seconds
|
|
115
|
+
- **HALF-OPEN**: After cooldown, one probe request to check recovery
|
|
116
|
+
|
|
117
|
+
### Configuration
|
|
118
|
+
|
|
119
|
+
```cpp
|
|
120
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
121
|
+
|
|
122
|
+
// Probe every 60 seconds instead of default 30
|
|
123
|
+
config.circuit_reset_interval = std::chrono::milliseconds(60000);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Or via environment variable:
|
|
127
|
+
```bash
|
|
128
|
+
export DRTRACE_CIRCUIT_RESET_MS=60000
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Performance Impact
|
|
132
|
+
|
|
133
|
+
| Scenario | Network Calls | Latency |
|
|
134
|
+
|----------|---------------|---------|
|
|
135
|
+
| Daemon UP | 1 (normal) | ~10ms |
|
|
136
|
+
| Daemon DOWN (circuit open) | 0 | < 1us |
|
|
137
|
+
| Daemon DOWN (probe) | 1-3 | ~3s |
|
|
138
|
+
|
|
139
|
+
This ensures your application's logging performance is not affected by daemon availability.
|
|
140
|
+
|
|
141
|
+
## Configurable Timeouts
|
|
142
|
+
|
|
143
|
+
Fine-tune network behavior for your environment:
|
|
144
|
+
|
|
145
|
+
```cpp
|
|
146
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
147
|
+
|
|
148
|
+
// Increase timeout for slow networks
|
|
149
|
+
config.http_timeout = std::chrono::milliseconds(5000); // 5 seconds
|
|
150
|
+
|
|
151
|
+
// Increase backoff for high-latency networks
|
|
152
|
+
config.retry_backoff = std::chrono::milliseconds(500); // 500ms base
|
|
153
|
+
|
|
154
|
+
// Reduce retries for faster failure detection
|
|
155
|
+
config.max_retries = 2;
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Environment Variables
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
export DRTRACE_HTTP_TIMEOUT_MS=5000
|
|
162
|
+
export DRTRACE_RETRY_BACKOFF_MS=500
|
|
163
|
+
export DRTRACE_MAX_RETRIES=2
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Defaults
|
|
167
|
+
|
|
168
|
+
| Setting | Default | Description |
|
|
169
|
+
|---------|---------|-------------|
|
|
170
|
+
| `http_timeout` | 1000ms | HTTP request timeout |
|
|
171
|
+
| `retry_backoff` | 100ms | Base backoff between retries |
|
|
172
|
+
| `max_retries` | 3 | Maximum retry attempts |
|
|
173
|
+
|
|
174
|
+
### Retry Behavior
|
|
175
|
+
|
|
176
|
+
Total worst-case delay = `http_timeout * max_retries + backoff * (1+2+...+(max_retries-1))`
|
|
177
|
+
|
|
178
|
+
With defaults: `1000*3 + 100*(1+2)` = 3300ms per batch
|
|
179
|
+
|
|
180
|
+
## Complete Configuration Example
|
|
181
|
+
|
|
182
|
+
```cpp
|
|
183
|
+
#include "drtrace_sink.hpp"
|
|
184
|
+
|
|
185
|
+
int main() {
|
|
186
|
+
// Load from environment with overrides
|
|
187
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
188
|
+
|
|
189
|
+
// Safety-critical application settings
|
|
190
|
+
config.batch_size = 1;
|
|
191
|
+
config.min_level = drtrace::core::LogLevel::INFO;
|
|
192
|
+
config.max_buffer_size = 5000;
|
|
193
|
+
config.circuit_reset_interval = std::chrono::milliseconds(10000);
|
|
194
|
+
config.http_timeout = std::chrono::milliseconds(2000);
|
|
195
|
+
config.max_retries = 2;
|
|
196
|
+
|
|
197
|
+
drtrace::DrtraceClient client(config);
|
|
198
|
+
|
|
199
|
+
client.info("Application started");
|
|
200
|
+
// ... application code ...
|
|
201
|
+
|
|
202
|
+
return 0;
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Environment Variable Reference
|
|
207
|
+
|
|
208
|
+
| Variable | Default | Description |
|
|
209
|
+
|----------|---------|-------------|
|
|
210
|
+
| `DRTRACE_ENABLED` | true | Enable/disable logging |
|
|
211
|
+
| `DRTRACE_DAEMON_URL` | http://localhost:8001/logs/ingest | Daemon endpoint |
|
|
212
|
+
| `DRTRACE_APPLICATION_ID` | my-app | Application identifier |
|
|
213
|
+
| `DRTRACE_MIN_LEVEL` | debug | Minimum log level |
|
|
214
|
+
| `DRTRACE_MAX_BUFFER_SIZE` | 10000 | Maximum buffer size |
|
|
215
|
+
| `DRTRACE_CIRCUIT_RESET_MS` | 30000 | Circuit breaker reset interval |
|
|
216
|
+
| `DRTRACE_HTTP_TIMEOUT_MS` | 1000 | HTTP request timeout |
|
|
217
|
+
| `DRTRACE_RETRY_BACKOFF_MS` | 100 | Base retry backoff |
|
|
218
|
+
| `DRTRACE_MAX_RETRIES` | 3 | Maximum retry attempts |
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# C++ ROS Integration Guide
|
|
2
|
+
|
|
3
|
+
This guide shows how to integrate DrTrace with ROS (Robot Operating System) projects using Pattern 2 (Direct API).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
DrTrace Direct API works alongside ROS logging without requiring spdlog. This allows you to:
|
|
8
|
+
- Keep using ROS logging (`ROS_INFO`, `ROS_ERROR`, etc.) for ROS-specific messages
|
|
9
|
+
- Use DrTrace for application-level structured logging
|
|
10
|
+
- No need to add spdlog or create bridges/adapters
|
|
11
|
+
|
|
12
|
+
## Integration Pattern
|
|
13
|
+
|
|
14
|
+
**Pattern Used:** Pattern 2 (Direct API - no spdlog required)
|
|
15
|
+
|
|
16
|
+
### CMake Setup
|
|
17
|
+
|
|
18
|
+
```cmake
|
|
19
|
+
# Add after cmake_minimum_required and project(...) definition.
|
|
20
|
+
# Header file should already be copied to third_party/drtrace/drtrace_sink.hpp
|
|
21
|
+
|
|
22
|
+
# Include the third_party/drtrace directory so the header can be found:
|
|
23
|
+
target_include_directories(your_target PRIVATE
|
|
24
|
+
${CMAKE_CURRENT_SOURCE_DIR}/third_party/drtrace
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
# spdlog NOT detected - using direct API (no spdlog required):
|
|
28
|
+
# Link required dependencies:
|
|
29
|
+
# - CURL::libcurl (system dependency - must be installed)
|
|
30
|
+
target_link_libraries(your_target PRIVATE
|
|
31
|
+
CURL::libcurl
|
|
32
|
+
)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Note:** No spdlog setup needed - only `CURL::libcurl` is required.
|
|
36
|
+
|
|
37
|
+
### C++ Code Integration
|
|
38
|
+
|
|
39
|
+
```cpp
|
|
40
|
+
#include "third_party/drtrace/drtrace_sink.hpp"
|
|
41
|
+
#include <ros/ros.h>
|
|
42
|
+
#include <cstdlib>
|
|
43
|
+
|
|
44
|
+
int main(int argc, char** argv) {
|
|
45
|
+
ros::init(argc, argv, "my_ros_node");
|
|
46
|
+
ros::NodeHandle nh;
|
|
47
|
+
|
|
48
|
+
// Load configuration from environment (reads DRTRACE_APPLICATION_ID or _drtrace/config.json)
|
|
49
|
+
drtrace::DrtraceConfig config = drtrace::DrtraceConfig::from_env();
|
|
50
|
+
|
|
51
|
+
// Create DrTrace client (no spdlog required - works alongside ROS logging)
|
|
52
|
+
drtrace::DrtraceClient drtrace_client(config, "my_ros_node");
|
|
53
|
+
|
|
54
|
+
// Use ROS logging for ROS-specific messages
|
|
55
|
+
ROS_INFO("ROS node starting");
|
|
56
|
+
ROS_DEBUG("Debug information");
|
|
57
|
+
|
|
58
|
+
// Use DrTrace client for application-level logging
|
|
59
|
+
drtrace_client.info("Application starting with DrTrace");
|
|
60
|
+
drtrace_client.error("Error occurred", __FILE__, __LINE__);
|
|
61
|
+
|
|
62
|
+
// Both logging systems work independently
|
|
63
|
+
ros::spin();
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Key Points
|
|
69
|
+
|
|
70
|
+
1. **No spdlog required**: DrTrace Direct API works without spdlog
|
|
71
|
+
2. **Coexistence**: ROS logging and DrTrace logging work side-by-side
|
|
72
|
+
3. **No bridges needed**: No need to create adapters between ROS and spdlog
|
|
73
|
+
4. **Simple setup**: Only requires `CURL::libcurl` in CMake
|
|
74
|
+
|
|
75
|
+
## Detection
|
|
76
|
+
|
|
77
|
+
The log-init agent will automatically detect ROS projects by looking for:
|
|
78
|
+
- `#include <ros/ros.h>` in source files
|
|
79
|
+
- ROS logging macros (`ROS_INFO`, `ROS_DEBUG`, `ROS_ERROR`, etc.)
|
|
80
|
+
- `.launch` files in the project
|
|
81
|
+
|
|
82
|
+
When ROS is detected and spdlog is not found, the agent will suggest Pattern 2 (Direct API).
|
|
83
|
+
|
|
84
|
+
## Related Documentation
|
|
85
|
+
|
|
86
|
+
- [C++ Client README](../../packages/cpp/drtrace-client/README.md): Complete C++ client documentation
|
|
87
|
+
- [Log-Init Agent Guide](../../docs/log-init-agent-guide.md): How to use the log-init agent for setup suggestions
|
|
88
|
+
|