Skip to content

Commit 56e794d

Browse files
committed
WIP
1 parent f9b5fff commit 56e794d

File tree

6 files changed

+507
-37
lines changed

6 files changed

+507
-37
lines changed

.github/workflows/release.yml

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,21 @@ jobs:
118118
119119
- name: Configure RubyGems credentials
120120
run: |
121-
# Create .gemrc file with API key
121+
# Create .gemrc file with correct API key format
122122
cat > ~/.gemrc << EOF
123123
---
124124
:rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}
125+
:backtrace: false
126+
:bulk_threshold: 1000
127+
:sources:
128+
- https://rubygems.org/
129+
:update_sources: true
130+
:verbose: true
125131
EOF
126-
echo "RubyGems credentials configured"
132+
echo "RubyGems configuration created"
133+
134+
# Also set the API key via environment variable
135+
echo "RUBYGEMS_API_KEY=${{ secrets.RUBYGEMS_API_KEY }}" >> $GITHUB_ENV
127136
128137
- name: Publish to RubyGems
129138
env:
@@ -135,38 +144,15 @@ jobs:
135144
exit 1
136145
fi
137146
147+
echo "API key length: ${#RUBYGEMS_API_KEY}"
138148
echo "Publishing gem: ${{ steps.gem_file.outputs.gem_path }}"
139-
gem push "${{ steps.gem_file.outputs.gem_path }}" --key "$RUBYGEMS_API_KEY"
140-
141-
- name: Create GitHub Release
142-
uses: actions/create-release@v1
143-
env:
144-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
145-
with:
146-
tag_name: ${{ github.ref }}
147-
release_name: Release ${{ steps.version.outputs.version }}
148-
body: |
149-
## What's Changed
150-
151-
Release version ${{ steps.version.outputs.version }}
152-
153-
### Installation
154-
155-
```bash
156-
gem install multiplayer-session-recorder
157-
```
158-
159-
### Usage
160-
161-
```ruby
162-
require 'session-recorder'
163-
164-
# Create exporter
165-
exporter = SessionRecorder::Exporters.create_http_trace_exporter(
166-
api_key: 'your-api-key'
167-
)
168-
```
169-
170-
See [README.md](README.md) for full documentation.
171-
draft: false
172-
prerelease: false
149+
150+
# Try multiple authentication methods
151+
if gem push "${{ steps.gem_file.outputs.gem_path }}" --key "$RUBYGEMS_API_KEY"; then
152+
echo "Gem published successfully using --key flag"
153+
elif gem push "${{ steps.gem_file.outputs.gem_path }}"; then
154+
echo "Gem published successfully using .gemrc configuration"
155+
else
156+
echo "Failed to publish gem with all authentication methods"
157+
exit 1
158+
fi

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
multiplayer-session-recorder (0.0.1)
4+
multiplayer-session-recorder (0.0.5)
55
opentelemetry-exporter-otlp (~> 0.29.1)
66
opentelemetry-sdk (~> 1.6)
77

examples/session_recorder_usage.rb

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# frozen_string_literal: true
2+
3+
require 'session-recorder'
4+
5+
# Example usage of the SessionRecorder class
6+
7+
# 1. Create a session recorder instance
8+
recorder = Multiplayer::SessionRecorder::SessionRecorder.new
9+
10+
# 2. Initialize with configuration
11+
recorder.init(
12+
api_key: 'your-multiplayer-api-key-here',
13+
trace_id_generator: Multiplayer::SessionRecorder::Trace::SessionRecorderIdGenerator.new,
14+
resource_attributes: {
15+
'service.name' => 'my-ruby-app',
16+
'service.version' => '1.0.0'
17+
},
18+
api_base_url: 'https://api.multiplayer.app' # Optional, uses default if not provided
19+
)
20+
21+
# 3. Start a debug session
22+
begin
23+
recorder.start(
24+
Multiplayer::SessionRecorder::Trace::SessionType::PLAIN,
25+
{
26+
name: 'User Login Debug Session',
27+
resource_attributes: {
28+
'user.id' => '12345',
29+
'action' => 'login'
30+
}
31+
}
32+
)
33+
34+
puts "Session started with ID: #{recorder.short_session_id}"
35+
36+
# 4. Your application logic here...
37+
puts "Recording session data..."
38+
sleep(2) # Simulate some work
39+
40+
# 5. Stop the session
41+
recorder.stop(
42+
{
43+
session_attributes: {
44+
comment: 'User successfully logged in',
45+
46+
}
47+
}
48+
)
49+
50+
puts "Session stopped successfully"
51+
52+
rescue StandardError => e
53+
puts "Error: #{e.message}"
54+
55+
# 6. Cancel session on error
56+
recorder.cancel
57+
puts "Session cancelled due to error"
58+
end
59+
60+
# 7. Example of continuous session
61+
puts "\n--- Continuous Session Example ---"
62+
63+
begin
64+
recorder.start(
65+
Multiplayer::SessionRecorder::Trace::SessionType::CONTINUOUS,
66+
{
67+
name: 'Continuous Monitoring Session',
68+
resource_attributes: {
69+
'monitoring.type' => 'performance',
70+
'environment' => 'production'
71+
}
72+
}
73+
)
74+
75+
puts "Continuous session started with ID: #{recorder.short_session_id}"
76+
77+
# Simulate some monitoring work
78+
puts "Monitoring application performance..."
79+
sleep(3)
80+
81+
# 8. Save the continuous session
82+
recorder.save(
83+
{
84+
name: 'Performance Monitoring Session',
85+
resource_attributes: {
86+
'metrics.cpu_usage' => '45%',
87+
'metrics.memory_usage' => '60%'
88+
}
89+
}
90+
)
91+
92+
puts "Continuous session saved successfully"
93+
94+
rescue StandardError => e
95+
puts "Error in continuous session: #{e.message}"
96+
recorder.cancel
97+
end
98+
99+
# 9. Example of remote session checking
100+
puts "\n--- Remote Session Check Example ---"
101+
102+
begin
103+
recorder.check_remote_continuous_session(
104+
{
105+
name: 'Remote Check Session',
106+
resource_attributes: {
107+
'check.type' => 'automated',
108+
'timestamp' => Time.now.iso8601
109+
}
110+
}
111+
)
112+
113+
puts "Remote session check completed"
114+
115+
rescue StandardError => e
116+
puts "Error in remote check: #{e.message}"
117+
end
118+
119+
puts "\nSession recorder example completed!"

lib/session-recorder.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
require "session_recorder/type"
55
require "session_recorder/constants"
66
require "session_recorder/version"
7+
require "session_recorder/session_recorder"
8+
require "session_recorder/api_service"
79

810
module Multiplayer
911
module SessionRecorder
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
# frozen_string_literal: true
2+
3+
require 'net/http'
4+
require 'json'
5+
require 'uri'
6+
require_relative '../constants'
7+
8+
module Multiplayer
9+
module SessionRecorder
10+
class ApiService
11+
attr_reader :config
12+
13+
def initialize
14+
@config = {
15+
api_base_url: Multiplayer::SessionRecorder::MULTIPLAYER_BASE_API_URL
16+
}
17+
end
18+
19+
# Initialize the API service
20+
# @param config [Hash] API service configuration
21+
# @option config [String] :api_key API key for authentication
22+
# @option config [String] :api_base_url Base URL for API endpoints
23+
# @option config [Boolean] :continuous_recording Whether continuous recording is enabled
24+
def init(config)
25+
api_base_url = config[:api_base_url] || Multiplayer::SessionRecorder::MULTIPLAYER_BASE_API_URL
26+
27+
@config = {
28+
**@config,
29+
**config,
30+
api_base_url: api_base_url
31+
}
32+
end
33+
34+
# Update the API service configuration
35+
# @param config [Hash] Partial configuration to update
36+
def update_configs(config)
37+
api_base_url = config[:api_base_url] || Multiplayer::SessionRecorder::MULTIPLAYER_BASE_API_URL
38+
39+
@config = {
40+
**@config,
41+
**config,
42+
api_base_url: api_base_url
43+
}
44+
end
45+
46+
# Get the current API base URL
47+
# @return [String] The current API base URL
48+
def get_api_base_url
49+
@config[:api_base_url] || Multiplayer::SessionRecorder::MULTIPLAYER_BASE_API_URL
50+
end
51+
52+
# Start a new debug session
53+
# @param request_body [Hash] Session start request data
54+
# @return [Hash] Session response
55+
def start_session(request_body)
56+
make_request('/debug-sessions/start', 'POST', request_body)
57+
end
58+
59+
# Stop an active debug session
60+
# @param session_id [String] ID of the session to stop
61+
# @param request_body [Hash] Session stop request data
62+
# @return [Hash] Response data
63+
def stop_session(session_id, request_body)
64+
make_request("/debug-sessions/#{session_id}/stop", 'PATCH', request_body)
65+
end
66+
67+
# Cancel an active session
68+
# @param session_id [String] ID of the session to cancel
69+
# @return [Hash] Response data
70+
def cancel_session(session_id)
71+
make_request("/debug-sessions/#{session_id}/cancel", 'DELETE')
72+
end
73+
74+
# Start a new continuous session
75+
# @param request_body [Hash] Session start request data
76+
# @return [Hash] Session response
77+
def start_continuous_session(request_body)
78+
make_request('/continuous-debug-sessions/start', 'POST', request_body)
79+
end
80+
81+
# Save a continuous session
82+
# @param session_id [String] ID of the session to save
83+
# @param request_body [Hash] Session save request data
84+
# @return [Hash] Response data
85+
def save_continuous_session(session_id, request_body)
86+
make_request("/continuous-debug-sessions/#{session_id}/save", 'POST', request_body)
87+
end
88+
89+
# Stop an active continuous debug session
90+
# @param session_id [String] ID of the session to stop
91+
# @return [Hash] Response data
92+
def stop_continuous_session(session_id)
93+
make_request("/continuous-debug-sessions/#{session_id}/cancel", 'DELETE')
94+
end
95+
96+
# Check if debug session should be started remotely
97+
# @param request_body [Hash] Session check request data
98+
# @return [Hash] Response with state information
99+
def check_remote_session(request_body)
100+
make_request('/remote-debug-session/check', 'POST', request_body)
101+
end
102+
103+
private
104+
105+
# Make a request to the session API
106+
# @param path [String] API endpoint path (relative to the base URL)
107+
# @param method [String] HTTP method (GET, POST, PATCH, etc.)
108+
# @param body [Hash] Request payload
109+
# @return [Hash] Response data
110+
def make_request(path, method, body = nil)
111+
url = "#{@config[:api_base_url]}/v0/radar#{path}"
112+
uri = URI(url)
113+
114+
http = Net::HTTP.new(uri.host, uri.port)
115+
http.use_ssl = uri.scheme == 'https'
116+
117+
request = case method.upcase
118+
when 'GET'
119+
Net::HTTP::Get.new(uri)
120+
when 'POST'
121+
Net::HTTP::Post.new(uri)
122+
when 'PATCH'
123+
Net::HTTP::Patch.new(uri)
124+
when 'DELETE'
125+
Net::HTTP::Delete.new(uri)
126+
else
127+
raise ArgumentError, "Unsupported HTTP method: #{method}"
128+
end
129+
130+
# Set headers
131+
request['Content-Type'] = 'application/json'
132+
request['X-Api-Key'] = @config[:api_key] if @config[:api_key]
133+
134+
# Set body for POST/PATCH requests
135+
if body && ['POST', 'PATCH'].include?(method.upcase)
136+
request.body = body.to_json
137+
end
138+
139+
# Make the request
140+
response = http.request(request)
141+
142+
unless response.is_a?(Net::HTTPSuccess)
143+
raise RuntimeError, "Network response was not ok: #{response.code} #{response.message}"
144+
end
145+
146+
# Return nil for 204 No Content responses
147+
return nil if response.code == '204'
148+
149+
# Parse JSON response
150+
JSON.parse(response.body, symbolize_names: true)
151+
rescue JSON::ParserError
152+
raise RuntimeError, 'Invalid JSON response from server'
153+
rescue StandardError => e
154+
raise RuntimeError, "Request failed: #{e.message}"
155+
end
156+
end
157+
end
158+
end

0 commit comments

Comments
 (0)