|
1 | 1 | # SessionRecorder CLI Example |
2 | 2 |
|
3 | | -This example demonstrates how to use the SessionRecorder in a command-line application with OpenTelemetry integration. It's based on the TypeScript example from `@multiplayer-app/session-recorder-node`. |
4 | | - |
5 | | -## 🚀 Features |
6 | | - |
7 | | -- **Session Management**: Start, manage, and stop debug sessions |
8 | | -- **OpenTelemetry Integration**: Full integration with OpenTelemetry tracing and logging |
9 | | -- **Custom Trace ID Generation**: Uses SessionRecorder's custom trace ID generator |
10 | | -- **Custom Sampling**: Implements trace ID ratio-based sampling |
11 | | -- **Simulated Work**: Demonstrates various types of operations with tracing |
12 | | -- **Graceful Shutdown**: Handles interrupts and cleanup properly |
13 | | - |
14 | | -## 📋 Prerequisites |
15 | | - |
16 | | -- Ruby 3.0 or higher |
17 | | -- Bundler |
18 | | -- Multiplayer API key (optional for testing) |
19 | | - |
20 | | -## 🛠️ Installation |
21 | | - |
22 | | -1. **Navigate to the example directory:** |
23 | | - ```bash |
24 | | - cd examples/cli/examples |
25 | | - ``` |
26 | | - |
27 | | -2. **Install dependencies:** |
28 | | - ```bash |
29 | | - bundle install |
30 | | - ``` |
31 | | - |
32 | | -3. **Set environment variables (optional):** |
33 | | - ```bash |
34 | | - export MULTIPLAYER_OTLP_KEY="your-api-key-here" |
35 | | - export MULTIPLAYER_TRACES_ENDPOINT="https://your-endpoint.com/v1/traces" |
36 | | - export MULTIPLAYER_LOGS_ENDPOINT="https://your-endpoint.com/v1/logs" |
37 | | - export ENVIRONMENT="production" |
38 | | - export COMPONENT_NAME="my-cli-app" |
39 | | - export COMPONENT_VERSION="2.0.0" |
40 | | - export DEBUG="true" |
41 | | - export LOG_LEVEL="DEBUG" |
42 | | - ``` |
43 | | - |
44 | | -## 🏃♂️ Running the Example |
45 | | - |
46 | | -### Basic Usage |
47 | | -```bash |
48 | | -ruby main.rb |
49 | | -``` |
50 | | - |
51 | | -### With Environment Variables |
52 | | -```bash |
53 | | -MULTIPLAYER_OTLP_KEY="your-key" ENVIRONMENT="staging" ruby main.rb |
54 | | -``` |
55 | | - |
56 | | -### Debug Mode |
57 | | -```bash |
58 | | -DEBUG=true LOG_LEVEL=DEBUG ruby main.rb |
59 | | -``` |
60 | | - |
61 | | -## 🔧 Configuration |
62 | | - |
63 | | -### Environment Variables |
64 | | - |
65 | | -| Variable | Default | Description | |
66 | | -|----------|---------|-------------| |
67 | | -| `MULTIPLAYER_OTLP_KEY` | `your-api-key-here` | Multiplayer API key | |
68 | | -| `ENVIRONMENT` | `development` | Environment name | |
69 | | -| `COMPONENT_NAME` | `ruby-cli-example` | Component name | |
70 | | -| `COMPONENT_VERSION` | `1.0.0` | Component version | |
71 | | -| `MULTIPLAYER_TRACES_ENDPOINT` | `nil` | Custom traces endpoint | |
72 | | -| `MULTIPLAYER_LOGS_ENDPOINT` | `nil` | Custom logs endpoint | |
73 | | -| `DEBUG` | `false` | Enable debug mode | |
74 | | -| `LOG_LEVEL` | `INFO` | Logging level | |
75 | | - |
76 | | -### Configuration File |
77 | | - |
78 | | -The `config.rb` file centralizes all configuration: |
79 | | - |
80 | | -```ruby |
81 | | -module Config |
82 | | - MULTIPLAYER_OTLP_KEY = ENV['MULTIPLAYER_OTLP_KEY'] || 'your-api-key-here' |
83 | | - ENVIRONMENT = ENV['ENVIRONMENT'] || 'development' |
84 | | - COMPONENT_NAME = ENV['COMPONENT_NAME'] || 'ruby-cli-example' |
85 | | - COMPONENT_VERSION = ENV['COMPONENT_VERSION'] || '1.0.0' |
86 | | - # ... more configuration |
87 | | -end |
88 | | -``` |
89 | | - |
90 | | -## 📊 OpenTelemetry Integration |
91 | | - |
92 | | -### Components Used |
93 | | - |
94 | | -1. **Custom Trace ID Generator**: `SessionRecorderIdGenerator` |
95 | | - - Generates trace IDs with session-specific prefixes |
96 | | - - Supports both plain and continuous session types |
97 | | - |
98 | | -2. **Custom Sampler**: `TraceIdRatioBasedSampler` |
99 | | - - Always samples traces with debug prefixes |
100 | | - - Applies ratio-based sampling for other traces |
101 | | - |
102 | | -3. **HTTP Exporters**: |
103 | | - - `SessionRecorderHttpTraceExporter` |
104 | | - - `SessionRecorderHttpLogsExporter` |
105 | | - |
106 | | -4. **Attribute Wrappers**: |
107 | | - - Filters out multiplayer-specific attributes |
108 | | - - Ensures clean trace data |
109 | | - |
110 | | -### Configuration |
111 | | - |
112 | | -```ruby |
113 | | -# Setup OpenTelemetry |
114 | | -opentelemetry_components = OpenTelemetryConfig.setup |
115 | | - |
116 | | -# Initialize SessionRecorder |
117 | | -@session_recorder.init({ |
118 | | - api_key: Config::MULTIPLAYER_OTLP_KEY, |
119 | | - trace_id_generator: opentelemetry_components[:id_generator], |
120 | | - resource_attributes: { |
121 | | - component_name: Config::COMPONENT_NAME, |
122 | | - component_version: Config::COMPONENT_VERSION, |
123 | | - environment: Config::ENVIRONMENT |
124 | | - } |
125 | | -}) |
126 | | -``` |
127 | | - |
128 | | -## 🎬 Session Management |
129 | | - |
130 | | -### Starting a Session |
131 | | - |
132 | | -```ruby |
133 | | -@session_recorder.start( |
134 | | - Multiplayer::SessionRecorder::Trace::SessionType::PLAIN, |
135 | | - { |
136 | | - name: Config::SESSION_NAME, |
137 | | - resource_attributes: { |
138 | | - version: Config::SESSION_VERSION |
139 | | - } |
140 | | - } |
141 | | -) |
142 | | -``` |
143 | | - |
144 | | -### Stopping a Session |
145 | | - |
146 | | -```ruby |
147 | | -@session_recorder.stop({ |
148 | | - comment: "CLI application completed successfully", |
149 | | - metadata: { |
150 | | - completion_time: Time.now.iso8601, |
151 | | - work_performed: true |
152 | | - } |
153 | | -}) |
154 | | -``` |
155 | | - |
156 | | -### Cancelling a Session |
157 | | - |
158 | | -```ruby |
159 | | -@session_recorder.cancel |
160 | | -``` |
161 | | - |
162 | | -## 🔍 Tracing and Observability |
163 | | - |
164 | | -### Creating Spans |
165 | | - |
166 | | -```ruby |
167 | | -OpenTelemetry::Trace.current_span.in_span("file_operations") do |span| |
168 | | - span.set_attribute("operation.type", "file_operations") |
169 | | - span.set_attribute("operation.count", 3) |
170 | | - |
171 | | - # Add events |
172 | | - span.add_event("file.read", { filename: "config.json", size: 1024 }) |
173 | | -end |
174 | | -``` |
175 | | - |
176 | | -### Simulated Operations |
177 | | - |
178 | | -The example includes three types of simulated work: |
179 | | - |
180 | | -1. **File Operations**: Reading configuration files |
181 | | -2. **Network Calls**: API calls and database queries |
182 | | -3. **Data Processing**: Data transformation and validation |
183 | | - |
184 | | -Each operation creates spans with relevant attributes and events. |
185 | | - |
186 | | -## 🛡️ Error Handling |
187 | | - |
188 | | -### Graceful Shutdown |
189 | | - |
190 | | -```ruby |
191 | | -Signal.trap("INT") do |
192 | | - puts "\n🛑 Received interrupt signal, shutting down gracefully..." |
193 | | - app.stop_session if app.instance_variable_get(:@running) |
194 | | - OpenTelemetryConfig.cleanup |
195 | | - exit(0) |
196 | | -end |
197 | | -``` |
198 | | - |
199 | | -### Session Cleanup |
200 | | - |
201 | | -```ruby |
202 | | -# Try to stop session if it's running |
203 | | -if @running |
204 | | - @logger.info("🔄 Attempting to stop session...") |
205 | | - begin |
206 | | - @session_recorder.cancel |
207 | | - @logger.info("✅ Session cancelled") |
208 | | - rescue => cancel_error |
209 | | - @logger.error("❌ Failed to cancel session: #{cancel_error.message}") |
210 | | - end |
211 | | -end |
212 | | -``` |
213 | | - |
214 | | -## 🧪 Testing Different Scenarios |
215 | | - |
216 | | -### Test with Real API Key |
217 | | -```bash |
218 | | -MULTIPLAYER_OTLP_KEY="your-real-key" ruby main.rb |
219 | | -``` |
220 | | - |
221 | | -### Test in Different Environment |
222 | | -```bash |
223 | | -ENVIRONMENT="staging" COMPONENT_NAME="staging-cli" ruby main.rb |
224 | | -``` |
225 | | - |
226 | | -### Test with Custom Endpoints |
227 | | -```bash |
228 | | -MULTIPLAYER_TRACES_ENDPOINT="https://custom.com/v1/traces" \ |
229 | | -MULTIPLAYER_LOGS_ENDPOINT="https://custom.com/v1/logs" \ |
230 | | -ruby main.rb |
231 | | -``` |
232 | | - |
233 | | -### Test Debug Mode |
234 | | -```bash |
235 | | -DEBUG=true LOG_LEVEL=DEBUG ruby main.rb |
236 | | -``` |
237 | | - |
238 | | -## 🔧 Customization |
239 | | - |
240 | | -### Add Custom Work |
241 | | - |
242 | | -```ruby |
243 | | -def simulate_custom_work |
244 | | - @logger.info("🔧 Simulating custom work...") |
245 | | - |
246 | | - OpenTelemetry::Trace.current_span.in_span("custom_work") do |span| |
247 | | - span.set_attribute("operation.type", "custom_work") |
248 | | - |
249 | | - # Your custom logic here |
250 | | - sleep(0.1) |
251 | | - span.add_event("custom.operation", { detail: "Custom operation completed" }) |
252 | | - end |
253 | | -end |
254 | | -``` |
255 | | - |
256 | | -### Modify Session Configuration |
257 | | - |
258 | | -```ruby |
259 | | -@session_recorder.start( |
260 | | - Multiplayer::SessionRecorder::Trace::SessionType::CONTINUOUS, # Change to continuous |
261 | | - { |
262 | | - name: "Custom Session Name", |
263 | | - resource_attributes: { |
264 | | - version: 2, |
265 | | - custom_field: "custom_value" |
266 | | - } |
267 | | - } |
268 | | -) |
269 | | -``` |
270 | | - |
271 | | -### Add Custom Resource Attributes |
272 | | - |
273 | | -```ruby |
274 | | -@session_recorder.init({ |
275 | | - api_key: Config::MULTIPLAYER_OTLP_KEY, |
276 | | - trace_id_generator: opentelemetry_components[:id_generator], |
277 | | - resource_attributes: { |
278 | | - component_name: Config::COMPONENT_NAME, |
279 | | - component_version: Config::COMPONENT_VERSION, |
280 | | - environment: Config::ENVIRONMENT, |
281 | | - custom_attribute: "custom_value", |
282 | | - deployment_id: ENV['DEPLOYMENT_ID'] |
283 | | - } |
284 | | -}) |
285 | | -``` |
286 | | - |
287 | | -## 🐛 Troubleshooting |
288 | | - |
289 | | -### Common Issues |
290 | | - |
291 | | -1. **Missing Dependencies** |
| 3 | +## Install dependencies |
292 | 4 | ```bash |
293 | 5 | bundle install |
294 | 6 | ``` |
295 | 7 |
|
296 | | -2. **Invalid API Key** |
297 | | - - Check that `MULTIPLAYER_OTLP_KEY` is set correctly |
298 | | - - Verify the API key has proper permissions |
299 | | - |
300 | | -3. **Network Issues** |
301 | | - - Check firewall settings |
302 | | - - Verify endpoint URLs are accessible |
303 | | - - Check SSL certificate validity |
304 | | - |
305 | | -4. **OpenTelemetry Configuration Errors** |
306 | | - - Enable debug mode: `DEBUG=true` |
307 | | - - Check log level: `LOG_LEVEL=DEBUG` |
308 | | - - Verify all required gems are installed |
309 | | - |
310 | | -### Debug Mode |
311 | | - |
312 | | -Enable debug mode to see detailed information: |
313 | | - |
| 8 | +### Launch |
314 | 9 | ```bash |
315 | | -DEBUG=true LOG_LEVEL=DEBUG ruby main.rb |
| 10 | +MULTIPLAYER_OTLP_KEY="your-key" ENVIRONMENT="staging" bundle exec ruby main.rb |
316 | 11 | ``` |
317 | | - |
318 | | -This will show: |
319 | | -- Detailed OpenTelemetry configuration |
320 | | -- Session initialization details |
321 | | -- Trace ID generation information |
322 | | -- Error stack traces |
323 | | - |
324 | | -## 📚 Related Documentation |
325 | | - |
326 | | -- [SessionRecorder Main README](../../../README.md) |
327 | | -- [OpenTelemetry Ruby SDK](https://github.com/open-telemetry/opentelemetry-ruby) |
328 | | -- [Multiplayer SessionRecorder](https://multiplayer.app) |
329 | | - |
330 | | -## 🤝 Contributing |
331 | | - |
332 | | -Feel free to modify this example to suit your needs. Common modifications include: |
333 | | - |
334 | | -- Adding more types of simulated work |
335 | | -- Implementing real file operations |
336 | | -- Adding database connectivity |
337 | | -- Implementing real API calls |
338 | | -- Adding configuration file support |
339 | | -- Implementing command-line arguments |
340 | | - |
341 | | -## 📄 License |
342 | | - |
343 | | -This example is part of the Multiplayer SessionRecorder project and follows the same license terms. |
0 commit comments