langfuse-rb 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.
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "logger"
4
+
5
+ module Langfuse
6
+ # Configuration object for Langfuse client
7
+ #
8
+ # @example Global configuration
9
+ # Langfuse.configure do |config|
10
+ # config.public_key = ENV['LANGFUSE_PUBLIC_KEY']
11
+ # config.secret_key = ENV['LANGFUSE_SECRET_KEY']
12
+ # config.cache_ttl = 120
13
+ # end
14
+ #
15
+ # @example Per-client configuration
16
+ # config = Langfuse::Config.new do |c|
17
+ # c.public_key = "pk_..."
18
+ # c.secret_key = "sk_..."
19
+ # end
20
+ #
21
+ class Config
22
+ # @return [String, nil] Langfuse public API key
23
+ attr_accessor :public_key
24
+
25
+ # @return [String, nil] Langfuse secret API key
26
+ attr_accessor :secret_key
27
+
28
+ # @return [String] Base URL for Langfuse API
29
+ attr_accessor :base_url
30
+
31
+ # @return [Integer] HTTP request timeout in seconds
32
+ attr_accessor :timeout
33
+
34
+ # @return [Logger] Logger instance for debugging
35
+ attr_accessor :logger
36
+
37
+ # @return [Integer] Cache TTL in seconds
38
+ attr_accessor :cache_ttl
39
+
40
+ # @return [Integer] Maximum number of cached items
41
+ attr_accessor :cache_max_size
42
+
43
+ # @return [Symbol] Cache backend (:memory or :rails)
44
+ attr_accessor :cache_backend
45
+
46
+ # @return [Integer] Lock timeout in seconds for distributed cache stampede protection
47
+ attr_accessor :cache_lock_timeout
48
+
49
+ # @return [Boolean] Use async processing for traces (requires ActiveJob)
50
+ attr_accessor :tracing_async
51
+
52
+ # @return [Integer] Number of events to batch before sending
53
+ attr_accessor :batch_size
54
+
55
+ # @return [Integer] Interval in seconds to flush buffered events
56
+ attr_accessor :flush_interval
57
+
58
+ # @return [Symbol] ActiveJob queue name for async processing
59
+ attr_accessor :job_queue
60
+
61
+ # Default values
62
+ DEFAULT_BASE_URL = "https://cloud.langfuse.com"
63
+ DEFAULT_TIMEOUT = 5
64
+ DEFAULT_CACHE_TTL = 60
65
+ DEFAULT_CACHE_MAX_SIZE = 1000
66
+ DEFAULT_CACHE_BACKEND = :memory
67
+ DEFAULT_CACHE_LOCK_TIMEOUT = 10
68
+ DEFAULT_TRACING_ASYNC = true
69
+ DEFAULT_BATCH_SIZE = 50
70
+ DEFAULT_FLUSH_INTERVAL = 10
71
+ DEFAULT_JOB_QUEUE = :default
72
+
73
+ # Initialize a new Config object
74
+ #
75
+ # @yield [config] Optional block for configuration
76
+ # @yieldparam config [Config] The config instance
77
+ def initialize
78
+ @public_key = ENV.fetch("LANGFUSE_PUBLIC_KEY", nil)
79
+ @secret_key = ENV.fetch("LANGFUSE_SECRET_KEY", nil)
80
+ @base_url = ENV.fetch("LANGFUSE_BASE_URL", DEFAULT_BASE_URL)
81
+ @timeout = DEFAULT_TIMEOUT
82
+ @cache_ttl = DEFAULT_CACHE_TTL
83
+ @cache_max_size = DEFAULT_CACHE_MAX_SIZE
84
+ @cache_backend = DEFAULT_CACHE_BACKEND
85
+ @cache_lock_timeout = DEFAULT_CACHE_LOCK_TIMEOUT
86
+ @tracing_async = DEFAULT_TRACING_ASYNC
87
+ @batch_size = DEFAULT_BATCH_SIZE
88
+ @flush_interval = DEFAULT_FLUSH_INTERVAL
89
+ @job_queue = DEFAULT_JOB_QUEUE
90
+ @logger = default_logger
91
+
92
+ yield(self) if block_given?
93
+ end
94
+
95
+ # Validate the configuration
96
+ #
97
+ # @raise [ConfigurationError] if configuration is invalid
98
+ # @return [void]
99
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
100
+ def validate!
101
+ raise ConfigurationError, "public_key is required" if public_key.nil? || public_key.empty?
102
+ raise ConfigurationError, "secret_key is required" if secret_key.nil? || secret_key.empty?
103
+ raise ConfigurationError, "base_url cannot be empty" if base_url.nil? || base_url.empty?
104
+ raise ConfigurationError, "timeout must be positive" if timeout.nil? || timeout <= 0
105
+ raise ConfigurationError, "cache_ttl must be non-negative" if cache_ttl.nil? || cache_ttl.negative?
106
+ raise ConfigurationError, "cache_max_size must be positive" if cache_max_size.nil? || cache_max_size <= 0
107
+
108
+ if cache_lock_timeout.nil? || cache_lock_timeout <= 0
109
+ raise ConfigurationError,
110
+ "cache_lock_timeout must be positive"
111
+ end
112
+
113
+ validate_cache_backend!
114
+ end
115
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
116
+
117
+ private
118
+
119
+ def default_logger
120
+ if defined?(Rails) && Rails.respond_to?(:logger)
121
+ Rails.logger
122
+ else
123
+ Logger.new($stdout, level: Logger::WARN)
124
+ end
125
+ end
126
+
127
+ def validate_cache_backend!
128
+ valid_backends = %i[memory rails]
129
+ return if valid_backends.include?(cache_backend)
130
+
131
+ raise ConfigurationError,
132
+ "cache_backend must be one of #{valid_backends.inspect}, got #{cache_backend.inspect}"
133
+ end
134
+ end
135
+ end