Skip to content

Commit 79dc8dd

Browse files
feat: ruby observability plugin (#360)
1 parent 65a5e6a commit 79dc8dd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+6108
-883
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ docker/enterprise-private.pem
3838
# Editor Artifacts
3939
**/.idea
4040
.vscode/*.log
41+
.cursor/rules/
4142

4243
dump.rdb
4344

e2e/ruby/rails/api-only/Gemfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ group :development do
4646
# gem "spring"
4747
end
4848

49-
gem 'highlight_io', path: '../../../../sdk/highlight-ruby/highlight'
49+
# LaunchDarkly SDK and Observability Plugin
50+
gem 'launchdarkly-server-sdk', '~> 8.0'
51+
gem 'launchdarkly-observability', path: '../../../../sdk/@launchdarkly/observability-ruby'

e2e/ruby/rails/api-only/Gemfile.lock

Lines changed: 212 additions & 215 deletions
Large diffs are not rendered by default.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
class ApplicationController < ActionController::API
22
include ActionController::Cookies
3+
4+
private
5+
6+
def ld_client
7+
Rails.configuration.ld_client
8+
end
39
end
Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,64 @@
11
class HealthController < ApplicationController
22
def index
3-
render(json: { status: 'ok', timestamp: Time.current })
3+
context = LaunchDarkly::LDContext.create({ key: 'health-check', kind: 'service' })
4+
state = ld_client.all_flags_state(context)
5+
6+
render(json: {
7+
status: 'ok',
8+
timestamp: Time.current,
9+
launchdarkly: {
10+
connected: state.valid?,
11+
flag_count: state.values_map.size
12+
}
13+
})
414
end
515

616
def error
717
raise(StandardError, 'Test API error')
818
end
19+
20+
# GET /health/flags
21+
# Returns all flag evaluations for testing
22+
def flags
23+
user_key = params[:user_key] || 'anonymous'
24+
context = LaunchDarkly::LDContext.create({ key: user_key, kind: 'user' })
25+
26+
state = ld_client.all_flags_state(context)
27+
28+
# Get detailed evaluations for all flags
29+
evaluations = {}
30+
state.values_map.each_key do |flag_key|
31+
detail = ld_client.variation_detail(flag_key, context, nil)
32+
evaluations[flag_key] = {
33+
value: detail.value,
34+
variation_index: detail.variation_index,
35+
reason: detail.reason&.kind
36+
}
37+
end
38+
39+
render(json: {
40+
valid: state.valid?,
41+
context_key: user_key,
42+
flag_count: evaluations.size,
43+
evaluations: evaluations
44+
})
45+
end
46+
47+
# GET /health/flags/:key
48+
# Evaluate a specific flag
49+
def flag
50+
flag_key = params[:key]
51+
user_key = params[:user_key] || 'anonymous'
52+
context = LaunchDarkly::LDContext.create({ key: user_key, kind: 'user' })
53+
54+
detail = ld_client.variation_detail(flag_key, context, nil)
55+
56+
render(json: {
57+
flag_key: flag_key,
58+
context_key: user_key,
59+
value: detail.value,
60+
variation_index: detail.variation_index,
61+
reason: detail.reason ? JSON.parse(detail.reason.to_json) : nil
62+
})
63+
end
964
end

e2e/ruby/rails/api-only/config/initializers/highlight.rb

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# frozen_string_literal: true
2+
3+
require 'launchdarkly-server-sdk'
4+
require 'launchdarkly_observability'
5+
6+
# Create observability plugin (SDK key and environment automatically inferred)
7+
observability_plugin = LaunchDarklyObservability::Plugin.new(
8+
otlp_endpoint: ENV.fetch('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318'),
9+
service_name: 'launchdarkly-ruby-api-only',
10+
service_version: '1.0.0'
11+
)
12+
13+
# Initialize LaunchDarkly client with real SDK key
14+
sdk_key = ENV.fetch('LAUNCHDARKLY_SDK_KEY') do
15+
Rails.logger.warn '[LaunchDarkly] LAUNCHDARKLY_SDK_KEY not set, client will not connect'
16+
nil
17+
end
18+
19+
config = LaunchDarkly::Config.new(
20+
plugins: [observability_plugin]
21+
)
22+
23+
Rails.configuration.ld_client = LaunchDarkly::LDClient.new(sdk_key, config)
24+
25+
at_exit { Rails.configuration.ld_client.close }
26+
27+
Rails.logger.info '[LaunchDarkly] Client initialized with observability plugin'

e2e/ruby/rails/api-only/config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
root to: 'health#index'
55

66
get 'health', to: 'health#index'
7+
get 'health/flags', to: 'health#flags'
8+
get 'health/flags/:key', to: 'health#flag'
79
get 'error', to: 'health#error'
810
end

e2e/ruby/rails/api-only/test/controllers/health_controller_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ class HealthControllerTest < ActionDispatch::IntegrationTest
1717
end
1818
end
1919

20-
test 'should include highlight headers' do
21-
get health_path, headers: { 'X-Highlight-Request' => 'test-session/test-request' }
20+
test 'should handle custom headers' do
21+
get health_path, headers: { 'X-Request-ID' => 'test-request-123' }
2222
assert_response :success
2323
end
2424
end

e2e/ruby/rails/demo/Gemfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,6 @@ group :test do
7272
gem 'selenium-webdriver'
7373
end
7474

75-
gem 'highlight_io', path: '../../../../sdk/highlight-ruby/highlight'
76-
77-
gem 'rubocop', '~> 1.65'
75+
# LaunchDarkly SDK and Observability Plugin
76+
gem 'launchdarkly-server-sdk', '~> 8.0'
77+
gem 'launchdarkly-observability', path: '../../../../sdk/@launchdarkly/observability-ruby'

0 commit comments

Comments
 (0)