rapitapir 0.1.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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +57 -0
- data/CHANGELOG.md +94 -0
- data/CLEANUP_SUMMARY.md +155 -0
- data/CONTRIBUTING.md +280 -0
- data/LICENSE +21 -0
- data/README.md +485 -0
- data/debug_hash.rb +20 -0
- data/docs/EXTENSION_COMPARISON.md +388 -0
- data/docs/SINATRA_EXTENSION.md +467 -0
- data/docs/archive/PHASE_1_2_COMPLETE.md +77 -0
- data/docs/archive/PHASE_1_3_COMPLETE.md +152 -0
- data/docs/archive/PHASE_2_1_OBSERVABILITY_COMPLETED.md +203 -0
- data/docs/archive/PHASE_2_SUMMARY.md +209 -0
- data/docs/archive/REFACTORING_SUMMARY.md +184 -0
- data/docs/archive/phase_1_3_plan.md +136 -0
- data/docs/archive/sinatra_extension_summary.md +188 -0
- data/docs/archive/sinatra_working_solution.md +113 -0
- data/docs/archive/typescript-client-generator-summary.md +259 -0
- data/docs/auto-derivation.md +146 -0
- data/docs/blueprint.md +1091 -0
- data/docs/endpoint-definition.md +211 -0
- data/docs/github_pages_fix.md +52 -0
- data/docs/github_pages_setup.md +49 -0
- data/docs/implementation-status.md +357 -0
- data/docs/observability.md +647 -0
- data/docs/phase3-plan.md +108 -0
- data/docs/sinatra_rapitapir.md +87 -0
- data/docs/type_shortcuts.md +146 -0
- data/examples/README_ENTERPRISE.md +202 -0
- data/examples/authentication_example.rb +192 -0
- data/examples/auto_derivation_ruby_friendly.rb +163 -0
- data/examples/cli/user_api_endpoints.rb +56 -0
- data/examples/client/typescript_client_example.rb +102 -0
- data/examples/client/user-api-client.ts +193 -0
- data/examples/demo_api.rb +41 -0
- data/examples/docs/documentation_example.rb +112 -0
- data/examples/docs/user-api-docs.html +789 -0
- data/examples/docs/user-api-docs.md +403 -0
- data/examples/enhanced_auto_derivation_test.rb +83 -0
- data/examples/enterprise_extension_demo.rb +417 -0
- data/examples/enterprise_rapitapir_api.rb +662 -0
- data/examples/getting_started_extension.rb +218 -0
- data/examples/hello_world.rb +74 -0
- data/examples/oauth2/.env.example +19 -0
- data/examples/oauth2/README.md +205 -0
- data/examples/oauth2/generic_oauth2_api.rb +226 -0
- data/examples/oauth2/get_token.rb +72 -0
- data/examples/oauth2/songs_api_with_auth0.rb +320 -0
- data/examples/oauth2/test_api.sh +16 -0
- data/examples/oauth2/test_songs_api.sh +110 -0
- data/examples/observability/.env.example +35 -0
- data/examples/observability/README.md +230 -0
- data/examples/observability/README_HONEYCOMB.md +332 -0
- data/examples/observability/advanced_setup.rb +384 -0
- data/examples/observability/basic_setup.rb +192 -0
- data/examples/observability/complete_test.rb +121 -0
- data/examples/observability/honeycomb_example.rb +523 -0
- data/examples/observability/honeycomb_rapitapir_clean.rb +488 -0
- data/examples/observability/honeycomb_rapitapir_example.rb +523 -0
- data/examples/observability/honeycomb_working_example.rb +489 -0
- data/examples/observability/quick_test.rb +78 -0
- data/examples/observability/simple_test.rb +14 -0
- data/examples/observability/test_honeycomb_demo.rb +354 -0
- data/examples/observability/test_live_honeycomb.rb +111 -0
- data/examples/observability/test_validation.rb +78 -0
- data/examples/observability/test_working_validation.rb +66 -0
- data/examples/openapi/user_api_schema.rb +132 -0
- data/examples/production_ready_example.rb +105 -0
- data/examples/rails/users_controller.rb +146 -0
- data/examples/readme/basic_sinatra_example.rb +128 -0
- data/examples/server/user_api.rb +179 -0
- data/examples/simple_auto_derivation_demo.rb +44 -0
- data/examples/simple_demo_api.rb +18 -0
- data/examples/sinatra/user_app.rb +127 -0
- data/examples/t_shortcut_demo.rb +59 -0
- data/examples/user_api.rb +190 -0
- data/examples/working_getting_started.rb +184 -0
- data/examples/working_simple_example.rb +195 -0
- data/lib/rapitapir/auth/configuration.rb +129 -0
- data/lib/rapitapir/auth/context.rb +122 -0
- data/lib/rapitapir/auth/errors.rb +104 -0
- data/lib/rapitapir/auth/middleware.rb +324 -0
- data/lib/rapitapir/auth/oauth2.rb +350 -0
- data/lib/rapitapir/auth/schemes.rb +420 -0
- data/lib/rapitapir/auth.rb +113 -0
- data/lib/rapitapir/cli/command.rb +535 -0
- data/lib/rapitapir/cli/server.rb +243 -0
- data/lib/rapitapir/cli/validator.rb +373 -0
- data/lib/rapitapir/client/generator_base.rb +272 -0
- data/lib/rapitapir/client/typescript_generator.rb +350 -0
- data/lib/rapitapir/core/endpoint.rb +158 -0
- data/lib/rapitapir/core/enhanced_endpoint.rb +235 -0
- data/lib/rapitapir/core/input.rb +182 -0
- data/lib/rapitapir/core/output.rb +164 -0
- data/lib/rapitapir/core/request.rb +19 -0
- data/lib/rapitapir/core/response.rb +17 -0
- data/lib/rapitapir/docs/html_generator.rb +780 -0
- data/lib/rapitapir/docs/markdown_generator.rb +464 -0
- data/lib/rapitapir/dsl/endpoint_dsl.rb +116 -0
- data/lib/rapitapir/dsl/enhanced_endpoint_dsl.rb +62 -0
- data/lib/rapitapir/dsl/enhanced_input.rb +73 -0
- data/lib/rapitapir/dsl/enhanced_output.rb +63 -0
- data/lib/rapitapir/dsl/enhanced_structures.rb +393 -0
- data/lib/rapitapir/dsl/fluent_dsl.rb +72 -0
- data/lib/rapitapir/dsl/fluent_endpoint_builder.rb +316 -0
- data/lib/rapitapir/dsl/http_verbs.rb +77 -0
- data/lib/rapitapir/dsl/input_methods.rb +47 -0
- data/lib/rapitapir/dsl/observability_methods.rb +81 -0
- data/lib/rapitapir/dsl/output_methods.rb +43 -0
- data/lib/rapitapir/dsl/type_resolution.rb +43 -0
- data/lib/rapitapir/observability/configuration.rb +108 -0
- data/lib/rapitapir/observability/health_check.rb +236 -0
- data/lib/rapitapir/observability/logging.rb +270 -0
- data/lib/rapitapir/observability/metrics.rb +203 -0
- data/lib/rapitapir/observability/middleware.rb +243 -0
- data/lib/rapitapir/observability/tracing.rb +143 -0
- data/lib/rapitapir/observability.rb +28 -0
- data/lib/rapitapir/openapi/schema_generator.rb +403 -0
- data/lib/rapitapir/schema.rb +136 -0
- data/lib/rapitapir/server/enhanced_rack_adapter.rb +379 -0
- data/lib/rapitapir/server/middleware.rb +120 -0
- data/lib/rapitapir/server/path_matcher.rb +45 -0
- data/lib/rapitapir/server/rack_adapter.rb +215 -0
- data/lib/rapitapir/server/rails_adapter.rb +17 -0
- data/lib/rapitapir/server/rails_adapter_class.rb +53 -0
- data/lib/rapitapir/server/rails_controller.rb +72 -0
- data/lib/rapitapir/server/rails_input_processor.rb +73 -0
- data/lib/rapitapir/server/rails_response_handler.rb +29 -0
- data/lib/rapitapir/server/sinatra_adapter.rb +200 -0
- data/lib/rapitapir/server/sinatra_integration.rb +93 -0
- data/lib/rapitapir/sinatra/configuration.rb +91 -0
- data/lib/rapitapir/sinatra/extension.rb +214 -0
- data/lib/rapitapir/sinatra/oauth2_helpers.rb +236 -0
- data/lib/rapitapir/sinatra/resource_builder.rb +152 -0
- data/lib/rapitapir/sinatra/swagger_ui_generator.rb +166 -0
- data/lib/rapitapir/sinatra_rapitapir.rb +40 -0
- data/lib/rapitapir/types/array.rb +163 -0
- data/lib/rapitapir/types/auto_derivation.rb +265 -0
- data/lib/rapitapir/types/base.rb +146 -0
- data/lib/rapitapir/types/boolean.rb +46 -0
- data/lib/rapitapir/types/date.rb +92 -0
- data/lib/rapitapir/types/datetime.rb +98 -0
- data/lib/rapitapir/types/email.rb +32 -0
- data/lib/rapitapir/types/float.rb +134 -0
- data/lib/rapitapir/types/hash.rb +161 -0
- data/lib/rapitapir/types/integer.rb +143 -0
- data/lib/rapitapir/types/object.rb +156 -0
- data/lib/rapitapir/types/optional.rb +65 -0
- data/lib/rapitapir/types/string.rb +185 -0
- data/lib/rapitapir/types/uuid.rb +32 -0
- data/lib/rapitapir/types.rb +155 -0
- data/lib/rapitapir/version.rb +5 -0
- data/lib/rapitapir.rb +173 -0
- data/rapitapir.gemspec +66 -0
- metadata +387 -0
@@ -0,0 +1,354 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'net/http'
|
5
|
+
require 'json'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
# Test script to generate sample data for Honeycomb.io observability demo
|
9
|
+
class HoneycombDemoTester
|
10
|
+
def initialize(base_url = 'http://localhost:4567')
|
11
|
+
@base_url = base_url
|
12
|
+
@users = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def run_comprehensive_test
|
16
|
+
puts "๐ฏ Starting comprehensive Honeycomb.io observability test"
|
17
|
+
puts "๐ This will generate various traces to demonstrate RapiTapir + Honeycomb integration"
|
18
|
+
puts ""
|
19
|
+
|
20
|
+
# Test health checks
|
21
|
+
test_health_checks
|
22
|
+
|
23
|
+
# Create sample users
|
24
|
+
create_sample_users
|
25
|
+
|
26
|
+
# Test different query patterns
|
27
|
+
test_user_queries
|
28
|
+
|
29
|
+
# Test analytics endpoints
|
30
|
+
test_analytics
|
31
|
+
|
32
|
+
# Test error scenarios
|
33
|
+
test_error_scenarios
|
34
|
+
|
35
|
+
# Test performance scenarios
|
36
|
+
test_performance_scenarios
|
37
|
+
|
38
|
+
puts ""
|
39
|
+
puts "โ
Comprehensive test completed!"
|
40
|
+
puts "๐ Check your Honeycomb.io dashboard to see the traces"
|
41
|
+
puts "๐ Recommended queries to try in Honeycomb:"
|
42
|
+
puts " - WHERE business.operation EXISTS"
|
43
|
+
puts " - WHERE duration_ms > 50"
|
44
|
+
puts " - GROUP BY business.operation"
|
45
|
+
puts " - WHERE error.type EXISTS"
|
46
|
+
puts " - WHERE db.operation = 'SELECT'"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def test_health_checks
|
52
|
+
puts "๐ฅ Testing health checks..."
|
53
|
+
|
54
|
+
# Basic health check
|
55
|
+
make_request('GET', '/health')
|
56
|
+
|
57
|
+
# Multiple health checks to show consistency
|
58
|
+
3.times { make_request('GET', '/health') }
|
59
|
+
|
60
|
+
puts " โ Health checks completed"
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_sample_users
|
64
|
+
puts "๐ฅ Creating sample users..."
|
65
|
+
|
66
|
+
sample_users = [
|
67
|
+
{
|
68
|
+
name: 'Alice Johnson',
|
69
|
+
email: 'alice.johnson@techcorp.com',
|
70
|
+
age: 28,
|
71
|
+
department: 'engineering'
|
72
|
+
},
|
73
|
+
{
|
74
|
+
name: 'Bob Smith',
|
75
|
+
email: 'bob.smith@techcorp.com',
|
76
|
+
age: 34,
|
77
|
+
department: 'sales'
|
78
|
+
},
|
79
|
+
{
|
80
|
+
name: 'Carol Wilson',
|
81
|
+
email: 'carol.wilson@techcorp.com',
|
82
|
+
age: 29,
|
83
|
+
department: 'marketing'
|
84
|
+
},
|
85
|
+
{
|
86
|
+
name: 'David Brown',
|
87
|
+
email: 'david.brown@techcorp.com',
|
88
|
+
age: 31,
|
89
|
+
department: 'engineering'
|
90
|
+
},
|
91
|
+
{
|
92
|
+
name: 'Eve Davis',
|
93
|
+
email: 'eve.davis@techcorp.com',
|
94
|
+
age: 27,
|
95
|
+
department: 'support'
|
96
|
+
},
|
97
|
+
{
|
98
|
+
name: 'Frank Miller',
|
99
|
+
email: 'frank.miller@techcorp.com',
|
100
|
+
age: 35,
|
101
|
+
department: 'sales'
|
102
|
+
},
|
103
|
+
{
|
104
|
+
name: 'Grace Lee',
|
105
|
+
email: 'grace.lee@techcorp.com',
|
106
|
+
age: 26,
|
107
|
+
department: 'engineering'
|
108
|
+
},
|
109
|
+
{
|
110
|
+
name: 'Henry Clark',
|
111
|
+
email: 'henry.clark@techcorp.com',
|
112
|
+
age: 33,
|
113
|
+
department: 'marketing'
|
114
|
+
}
|
115
|
+
]
|
116
|
+
|
117
|
+
sample_users.each_with_index do |user_data, index|
|
118
|
+
puts " Creating user #{index + 1}/#{sample_users.length}: #{user_data[:name]}"
|
119
|
+
response = make_request('POST', '/users', user_data)
|
120
|
+
|
121
|
+
if response && response.code == '201'
|
122
|
+
user = JSON.parse(response.body)
|
123
|
+
@users << user
|
124
|
+
puts " โ Created user with ID: #{user['id']}"
|
125
|
+
else
|
126
|
+
puts " โ Failed to create user: #{user_data[:name]}"
|
127
|
+
end
|
128
|
+
|
129
|
+
# Small delay to spread out the requests
|
130
|
+
sleep(0.1)
|
131
|
+
end
|
132
|
+
|
133
|
+
puts " โ Created #{@users.length} users"
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_user_queries
|
137
|
+
puts "๐ Testing user query patterns..."
|
138
|
+
|
139
|
+
# Basic user listing
|
140
|
+
puts " Testing pagination..."
|
141
|
+
make_request('GET', '/users')
|
142
|
+
make_request('GET', '/users?page=1&limit=3')
|
143
|
+
make_request('GET', '/users?page=2&limit=3')
|
144
|
+
|
145
|
+
# Department filtering
|
146
|
+
puts " Testing department filtering..."
|
147
|
+
%w[engineering sales marketing support].each do |dept|
|
148
|
+
make_request('GET', "/users?department=#{dept}")
|
149
|
+
end
|
150
|
+
|
151
|
+
# Combined filtering and pagination
|
152
|
+
puts " Testing combined filtering..."
|
153
|
+
make_request('GET', '/users?department=engineering&page=1&limit=2')
|
154
|
+
|
155
|
+
# Individual user lookups
|
156
|
+
puts " Testing individual user lookups..."
|
157
|
+
@users.first(3).each do |user|
|
158
|
+
make_request('GET', "/users/#{user['id']}")
|
159
|
+
end
|
160
|
+
|
161
|
+
puts " โ User query tests completed"
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_analytics
|
165
|
+
puts "๐ Testing analytics endpoints..."
|
166
|
+
|
167
|
+
# Department statistics
|
168
|
+
3.times do |i|
|
169
|
+
puts " Running analytics query #{i + 1}/3..."
|
170
|
+
make_request('GET', '/analytics/department-stats')
|
171
|
+
sleep(0.2)
|
172
|
+
end
|
173
|
+
|
174
|
+
puts " โ Analytics tests completed"
|
175
|
+
end
|
176
|
+
|
177
|
+
def test_error_scenarios
|
178
|
+
puts "โ Testing error scenarios..."
|
179
|
+
|
180
|
+
# Invalid JSON
|
181
|
+
puts " Testing invalid JSON..."
|
182
|
+
make_request('POST', '/users', '{"invalid": json}', content_type: 'application/json', raw: true)
|
183
|
+
|
184
|
+
# Validation errors
|
185
|
+
puts " Testing validation errors..."
|
186
|
+
|
187
|
+
invalid_users = [
|
188
|
+
{ name: '', email: 'invalid', age: 15, department: 'invalid' }, # Multiple validation errors
|
189
|
+
{ name: 'John', email: 'not-an-email', age: 25, department: 'engineering' }, # Bad email
|
190
|
+
{ name: 'Jane', email: 'jane@example.com', age: 16, department: 'engineering' }, # Too young
|
191
|
+
{ name: 'Bob', email: 'bob@example.com', age: 30, department: 'nonexistent' } # Invalid department
|
192
|
+
]
|
193
|
+
|
194
|
+
invalid_users.each_with_index do |user_data, index|
|
195
|
+
puts " Testing validation error #{index + 1}/#{invalid_users.length}..."
|
196
|
+
make_request('POST', '/users', user_data)
|
197
|
+
sleep(0.1)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Not found errors
|
201
|
+
puts " Testing not found errors..."
|
202
|
+
fake_uuid = '12345678-1234-1234-1234-123456789999'
|
203
|
+
make_request('GET', "/users/#{fake_uuid}")
|
204
|
+
make_request('PUT', "/users/#{fake_uuid}", { name: 'Updated Name' })
|
205
|
+
make_request('DELETE', "/users/#{fake_uuid}")
|
206
|
+
|
207
|
+
puts " โ Error scenario tests completed"
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_performance_scenarios
|
211
|
+
puts "โก Testing performance scenarios..."
|
212
|
+
|
213
|
+
# Concurrent requests simulation
|
214
|
+
puts " Simulating concurrent user listing requests..."
|
215
|
+
threads = []
|
216
|
+
|
217
|
+
5.times do |i|
|
218
|
+
threads << Thread.new do
|
219
|
+
make_request('GET', '/users', nil, thread_id: i)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
threads.each(&:join)
|
224
|
+
|
225
|
+
# Update operations
|
226
|
+
puts " Testing update operations..."
|
227
|
+
if @users.any?
|
228
|
+
user = @users.first
|
229
|
+
update_data = {
|
230
|
+
name: "#{user['name']} (Updated)",
|
231
|
+
age: user['age'] + 1
|
232
|
+
}
|
233
|
+
make_request('PUT', "/users/#{user['id']}", update_data)
|
234
|
+
end
|
235
|
+
|
236
|
+
# Delete operations
|
237
|
+
puts " Testing delete operations..."
|
238
|
+
if @users.length > 1
|
239
|
+
user_to_delete = @users.last
|
240
|
+
make_request('DELETE', "/users/#{user_to_delete['id']}")
|
241
|
+
end
|
242
|
+
|
243
|
+
puts " โ Performance scenario tests completed"
|
244
|
+
end
|
245
|
+
|
246
|
+
def make_request(method, path, body = nil, content_type: 'application/json', raw: false, thread_id: nil)
|
247
|
+
uri = URI("#{@base_url}#{path}")
|
248
|
+
|
249
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
250
|
+
|
251
|
+
request = case method.upcase
|
252
|
+
when 'GET'
|
253
|
+
Net::HTTP::Get.new(uri)
|
254
|
+
when 'POST'
|
255
|
+
Net::HTTP::Post.new(uri)
|
256
|
+
when 'PUT'
|
257
|
+
Net::HTTP::Put.new(uri)
|
258
|
+
when 'DELETE'
|
259
|
+
Net::HTTP::Delete.new(uri)
|
260
|
+
else
|
261
|
+
raise "Unsupported method: #{method}"
|
262
|
+
end
|
263
|
+
|
264
|
+
if body
|
265
|
+
if raw
|
266
|
+
request.body = body
|
267
|
+
else
|
268
|
+
request.body = body.to_json
|
269
|
+
end
|
270
|
+
request['Content-Type'] = content_type
|
271
|
+
end
|
272
|
+
|
273
|
+
# Add custom headers for tracing
|
274
|
+
request['X-Test-Scenario'] = 'honeycomb-demo'
|
275
|
+
request['X-Thread-Id'] = thread_id.to_s if thread_id
|
276
|
+
|
277
|
+
begin
|
278
|
+
response = http.request(request)
|
279
|
+
|
280
|
+
status_symbol = case response.code.to_i
|
281
|
+
when 200..299
|
282
|
+
'โ'
|
283
|
+
when 400..499
|
284
|
+
'โ '
|
285
|
+
else
|
286
|
+
'โ'
|
287
|
+
end
|
288
|
+
|
289
|
+
thread_info = thread_id ? " [T#{thread_id}]" : ""
|
290
|
+
puts " #{status_symbol} #{method.upcase} #{path} โ #{response.code}#{thread_info}"
|
291
|
+
|
292
|
+
response
|
293
|
+
rescue StandardError => e
|
294
|
+
puts " โ #{method.upcase} #{path} โ Error: #{e.message}"
|
295
|
+
nil
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Run the test if this file is executed directly
|
301
|
+
if __FILE__ == $PROGRAM_NAME
|
302
|
+
if ARGV.include?('--help') || ARGV.include?('-h')
|
303
|
+
puts "Honeycomb.io Observability Demo Test Script"
|
304
|
+
puts ""
|
305
|
+
puts "Usage: ruby test_honeycomb_demo.rb [URL]"
|
306
|
+
puts ""
|
307
|
+
puts "Arguments:"
|
308
|
+
puts " URL Base URL of the API server (default: http://localhost:4567)"
|
309
|
+
puts ""
|
310
|
+
puts "Examples:"
|
311
|
+
puts " ruby test_honeycomb_demo.rb"
|
312
|
+
puts " ruby test_honeycomb_demo.rb http://localhost:4567"
|
313
|
+
puts ""
|
314
|
+
puts "This script will:"
|
315
|
+
puts " 1. Test health check endpoints"
|
316
|
+
puts " 2. Create sample users with various departments"
|
317
|
+
puts " 3. Test different query patterns (pagination, filtering)"
|
318
|
+
puts " 4. Test analytics endpoints"
|
319
|
+
puts " 5. Generate error scenarios for testing"
|
320
|
+
puts " 6. Simulate performance scenarios"
|
321
|
+
puts ""
|
322
|
+
puts "All requests will generate traces in Honeycomb.io for analysis."
|
323
|
+
puts ""
|
324
|
+
puts "โ ๏ธ Make sure to start the server first:"
|
325
|
+
puts " ruby honeycomb_working_example.rb"
|
326
|
+
exit 0
|
327
|
+
end
|
328
|
+
|
329
|
+
base_url = ARGV[0] || 'http://localhost:4567'
|
330
|
+
|
331
|
+
puts "๐ฏ Target URL: #{base_url}"
|
332
|
+
puts ""
|
333
|
+
|
334
|
+
# Check if server is running
|
335
|
+
begin
|
336
|
+
uri = URI("#{base_url}/health")
|
337
|
+
response = Net::HTTP.get_response(uri)
|
338
|
+
if response.code != '200'
|
339
|
+
puts "โ Server not responding correctly at #{base_url}"
|
340
|
+
puts " Make sure the Honeycomb demo server is running:"
|
341
|
+
puts " ruby examples/observability/honeycomb_working_example.rb"
|
342
|
+
exit 1
|
343
|
+
end
|
344
|
+
rescue StandardError => e
|
345
|
+
puts "โ Cannot connect to server at #{base_url}"
|
346
|
+
puts " Error: #{e.message}"
|
347
|
+
puts " Make sure the Honeycomb demo server is running:"
|
348
|
+
puts " ruby examples/observability/honeycomb_working_example.rb"
|
349
|
+
exit 1
|
350
|
+
end
|
351
|
+
|
352
|
+
tester = HoneycombDemoTester.new(base_url)
|
353
|
+
tester.run_comprehensive_test
|
354
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Quick test to verify Honeycomb integration is working
|
5
|
+
require 'net/http'
|
6
|
+
require 'json'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
puts "๐ฏ Testing Honeycomb.io Integration"
|
10
|
+
puts "=================================="
|
11
|
+
|
12
|
+
# Start server in background
|
13
|
+
puts "๐ก Starting server..."
|
14
|
+
server_pid = spawn("bundle exec ruby honeycomb_working_example.rb",
|
15
|
+
out: "/dev/null", err: "/dev/null")
|
16
|
+
|
17
|
+
# Wait for server to start
|
18
|
+
sleep(3)
|
19
|
+
puts "โ
Server started (PID: #{server_pid})"
|
20
|
+
|
21
|
+
begin
|
22
|
+
base_url = 'http://localhost:4567'
|
23
|
+
|
24
|
+
# Test health endpoint
|
25
|
+
puts "\n๐ฅ Testing health endpoint..."
|
26
|
+
uri = URI("#{base_url}/health")
|
27
|
+
response = Net::HTTP.get_response(uri)
|
28
|
+
|
29
|
+
if response.code == '200'
|
30
|
+
puts "โ
Health check successful (#{response.code})"
|
31
|
+
health_data = JSON.parse(response.body)
|
32
|
+
puts " Status: #{health_data['status']}"
|
33
|
+
puts " Service: #{health_data['service']}"
|
34
|
+
else
|
35
|
+
puts "โ Health check failed (#{response.code})"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Test user creation (will generate traces)
|
39
|
+
puts "\n๐ค Testing user creation..."
|
40
|
+
uri = URI("#{base_url}/users")
|
41
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
42
|
+
|
43
|
+
request = Net::HTTP::Post.new(uri)
|
44
|
+
request['Content-Type'] = 'application/json'
|
45
|
+
request.body = {
|
46
|
+
name: 'Test User for Honeycomb',
|
47
|
+
email: 'test@honeycomb-demo.com',
|
48
|
+
age: 30,
|
49
|
+
department: 'engineering'
|
50
|
+
}.to_json
|
51
|
+
|
52
|
+
response = http.request(request)
|
53
|
+
|
54
|
+
if response.code == '201'
|
55
|
+
puts "โ
User creation successful (#{response.code})"
|
56
|
+
user_data = JSON.parse(response.body)
|
57
|
+
puts " Created user: #{user_data['name']} (ID: #{user_data['id']})"
|
58
|
+
|
59
|
+
# Test getting the user back
|
60
|
+
puts "\n๐ Testing user retrieval..."
|
61
|
+
get_uri = URI("#{base_url}/users/#{user_data['id']}")
|
62
|
+
get_response = Net::HTTP.get_response(get_uri)
|
63
|
+
|
64
|
+
if get_response.code == '200'
|
65
|
+
puts "โ
User retrieval successful (#{get_response.code})"
|
66
|
+
else
|
67
|
+
puts "โ User retrieval failed (#{get_response.code})"
|
68
|
+
end
|
69
|
+
else
|
70
|
+
puts "โ User creation failed (#{response.code})"
|
71
|
+
puts " Response: #{response.body}"
|
72
|
+
end
|
73
|
+
|
74
|
+
# Test analytics endpoint (complex operation)
|
75
|
+
puts "\n๐ Testing analytics endpoint..."
|
76
|
+
analytics_uri = URI("#{base_url}/analytics/department-stats")
|
77
|
+
analytics_response = Net::HTTP.get_response(analytics_uri)
|
78
|
+
|
79
|
+
if analytics_response.code == '200'
|
80
|
+
puts "โ
Analytics successful (#{analytics_response.code})"
|
81
|
+
analytics_data = JSON.parse(analytics_response.body)
|
82
|
+
puts " Total users: #{analytics_data['total_users']}"
|
83
|
+
else
|
84
|
+
puts "โ Analytics failed (#{analytics_response.code})"
|
85
|
+
end
|
86
|
+
|
87
|
+
puts "\n๐ Test completed successfully!"
|
88
|
+
puts ""
|
89
|
+
puts "๐ Traces should now be visible in your Honeycomb dashboard:"
|
90
|
+
puts " 1. Go to https://ui.honeycomb.io/"
|
91
|
+
puts " 2. Look for dataset: 'rapitapir-demo'"
|
92
|
+
puts " 3. You should see traces for:"
|
93
|
+
puts " - GET /health"
|
94
|
+
puts " - POST /users"
|
95
|
+
puts " - GET /users/:id"
|
96
|
+
puts " - GET /analytics/department-stats"
|
97
|
+
puts ""
|
98
|
+
puts "๐ Try these queries in Honeycomb:"
|
99
|
+
puts " - WHERE business.operation EXISTS"
|
100
|
+
puts " - WHERE http.method = 'POST'"
|
101
|
+
puts " - WHERE db.operation EXISTS"
|
102
|
+
puts " - GROUP BY business.operation"
|
103
|
+
|
104
|
+
rescue StandardError => e
|
105
|
+
puts "โ Error during testing: #{e.message}"
|
106
|
+
ensure
|
107
|
+
puts "\n๐ Stopping server..."
|
108
|
+
Process.kill('TERM', server_pid) if server_pid
|
109
|
+
sleep(1)
|
110
|
+
puts "โ
Server stopped"
|
111
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Test script to validate Honeycomb.io observability example
|
5
|
+
require 'bundler/setup'
|
6
|
+
|
7
|
+
# Add local lib to load path for RapiTapir
|
8
|
+
$LOAD_PATH.unshift(File.expand_path('../../lib', __dir__))
|
9
|
+
|
10
|
+
# Set mock environment variables
|
11
|
+
ENV['OTEL_EXPORTER_OTLP_HEADERS'] = 'x-honeycomb-team=test-key'
|
12
|
+
ENV['OTEL_SERVICE_NAME'] = 'rapitapir-demo'
|
13
|
+
ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] = 'https://api.honeycomb.io'
|
14
|
+
|
15
|
+
# Override $PROGRAM_NAME to avoid server startup
|
16
|
+
original_program_name = $PROGRAM_NAME
|
17
|
+
$PROGRAM_NAME = 'test_validation'
|
18
|
+
|
19
|
+
begin
|
20
|
+
puts "๐งช Testing Honeycomb.io observability example..."
|
21
|
+
|
22
|
+
# Test individual gem loading
|
23
|
+
puts " Loading OpenTelemetry SDK..."
|
24
|
+
require 'opentelemetry/sdk'
|
25
|
+
|
26
|
+
puts " Loading OpenTelemetry OTLP exporter..."
|
27
|
+
require 'opentelemetry/exporter/otlp'
|
28
|
+
|
29
|
+
puts " Loading OpenTelemetry instrumentation..."
|
30
|
+
require 'opentelemetry/instrumentation/all'
|
31
|
+
|
32
|
+
puts " Loading OpenTelemetry baggage processor..."
|
33
|
+
require 'opentelemetry/processor/baggage/baggage_span_processor'
|
34
|
+
|
35
|
+
puts " Loading Sinatra..."
|
36
|
+
require 'sinatra/base'
|
37
|
+
|
38
|
+
puts " Loading JSON..."
|
39
|
+
require 'json'
|
40
|
+
|
41
|
+
# Now load the main example file
|
42
|
+
puts " Loading honeycomb_example.rb..."
|
43
|
+
load File.join(__dir__, 'honeycomb_example.rb')
|
44
|
+
|
45
|
+
# Test that the class was defined
|
46
|
+
unless defined?(HoneycombDemoAPI)
|
47
|
+
raise "HoneycombDemoAPI class not defined"
|
48
|
+
end
|
49
|
+
|
50
|
+
puts ""
|
51
|
+
puts "โ
Success! All components loaded correctly:"
|
52
|
+
puts " โ OpenTelemetry SDK initialized"
|
53
|
+
puts " โ OTLP exporter configured"
|
54
|
+
puts " โ Automatic instrumentation enabled"
|
55
|
+
puts " โ Baggage processor configured"
|
56
|
+
puts " โ RapiTapir configuration loaded"
|
57
|
+
puts " โ Sinatra app class defined: #{HoneycombDemoAPI.name}"
|
58
|
+
puts ""
|
59
|
+
puts "๐ Ready to run the Honeycomb.io observability demo!"
|
60
|
+
puts " Usage: ruby honeycomb_example.rb"
|
61
|
+
puts ""
|
62
|
+
puts "๐ Next steps:"
|
63
|
+
puts " 1. Get a Honeycomb.io API key from https://ui.honeycomb.io/account"
|
64
|
+
puts " 2. Copy .env.example to .env and add your API key"
|
65
|
+
puts " 3. Run: ruby honeycomb_example.rb"
|
66
|
+
puts " 4. Make requests to generate traces"
|
67
|
+
puts " 5. View traces in Honeycomb.io dashboard"
|
68
|
+
|
69
|
+
rescue LoadError => e
|
70
|
+
puts "โ LoadError: #{e.message}"
|
71
|
+
puts " Make sure all gems are installed: bundle install"
|
72
|
+
rescue StandardError => e
|
73
|
+
puts "โ Error: #{e.message}"
|
74
|
+
puts " Backtrace:"
|
75
|
+
puts e.backtrace.first(5).map { |line| " #{line}" }
|
76
|
+
ensure
|
77
|
+
$PROGRAM_NAME = original_program_name
|
78
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Test script for the working Honeycomb example
|
5
|
+
require 'bundler/setup'
|
6
|
+
|
7
|
+
# Set mock environment variables
|
8
|
+
ENV['OTEL_EXPORTER_OTLP_HEADERS'] = 'x-honeycomb-team=test-key'
|
9
|
+
ENV['OTEL_SERVICE_NAME'] = 'rapitapir-demo'
|
10
|
+
ENV['OTEL_EXPORTER_OTLP_ENDPOINT'] = 'https://api.honeycomb.io'
|
11
|
+
|
12
|
+
# Override $PROGRAM_NAME to avoid server startup
|
13
|
+
original_program_name = $PROGRAM_NAME
|
14
|
+
$PROGRAM_NAME = 'test_validation'
|
15
|
+
|
16
|
+
begin
|
17
|
+
puts "๐งช Testing working Honeycomb.io observability example..."
|
18
|
+
|
19
|
+
# Load the working example
|
20
|
+
puts " Loading honeycomb_working_example.rb..."
|
21
|
+
load File.join(__dir__, 'honeycomb_working_example.rb')
|
22
|
+
|
23
|
+
# Test that the class was defined
|
24
|
+
unless defined?(HoneycombDemoAPI)
|
25
|
+
raise "HoneycombDemoAPI class not defined"
|
26
|
+
end
|
27
|
+
|
28
|
+
puts ""
|
29
|
+
puts "โ
Success! Working Honeycomb example loaded correctly:"
|
30
|
+
puts " โ OpenTelemetry SDK initialized"
|
31
|
+
puts " โ OTLP exporter configured for Honeycomb.io"
|
32
|
+
puts " โ Automatic instrumentation enabled (Sinatra, Rack, HTTP)"
|
33
|
+
puts " โ Baggage processor configured for context propagation"
|
34
|
+
puts " โ Custom RapiTapir observability extension loaded"
|
35
|
+
puts " โ Sinatra app class defined: #{HoneycombDemoAPI.name}"
|
36
|
+
puts ""
|
37
|
+
puts "๐ Ready to run the Honeycomb.io observability demo!"
|
38
|
+
puts " Usage: ruby honeycomb_working_example.rb"
|
39
|
+
puts ""
|
40
|
+
puts "๐ Next steps:"
|
41
|
+
puts " 1. Get a Honeycomb.io API key from https://ui.honeycomb.io/account"
|
42
|
+
puts " 2. Copy .env.example to .env and add your API key"
|
43
|
+
puts " 3. Load environment: source .env"
|
44
|
+
puts " 4. Run: ruby honeycomb_working_example.rb"
|
45
|
+
puts " 5. Make requests to generate traces"
|
46
|
+
puts " 6. View traces in Honeycomb.io dashboard"
|
47
|
+
puts ""
|
48
|
+
puts "๐ง Available endpoints:"
|
49
|
+
puts " GET /health - Health check with tracing"
|
50
|
+
puts " GET /users - List users with pagination"
|
51
|
+
puts " POST /users - Create user with validation"
|
52
|
+
puts " GET /users/:id - Get user by ID"
|
53
|
+
puts " PUT /users/:id - Update user"
|
54
|
+
puts " DELETE /users/:id - Delete user"
|
55
|
+
puts " GET /analytics/department-stats - Complex analytics operation"
|
56
|
+
|
57
|
+
rescue LoadError => e
|
58
|
+
puts "โ LoadError: #{e.message}"
|
59
|
+
puts " Make sure all gems are installed: bundle install"
|
60
|
+
rescue StandardError => e
|
61
|
+
puts "โ Error: #{e.message}"
|
62
|
+
puts " Backtrace:"
|
63
|
+
puts e.backtrace.first(5).map { |line| " #{line}" }
|
64
|
+
ensure
|
65
|
+
$PROGRAM_NAME = original_program_name
|
66
|
+
end
|