mixpanel-ruby 2.3.0 → 3.0.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,35 @@
1
+ module Mixpanel
2
+ module Flags
3
+ # Selected variant returned from flag evaluation
4
+ class SelectedVariant
5
+ attr_accessor :variant_key, :variant_value, :experiment_id,
6
+ :is_experiment_active, :is_qa_tester
7
+
8
+ # @param variant_key [String, nil] The variant key
9
+ # @param variant_value [Object] The variant value (any type)
10
+ # @param experiment_id [String, nil] Associated experiment ID
11
+ # @param is_experiment_active [Boolean, nil] Whether experiment is active
12
+ # @param is_qa_tester [Boolean, nil] Whether user is a QA tester
13
+ def initialize(variant_key: nil, variant_value: nil, experiment_id: nil,
14
+ is_experiment_active: nil, is_qa_tester: nil)
15
+ @variant_key = variant_key
16
+ @variant_value = variant_value
17
+ @experiment_id = experiment_id
18
+ @is_experiment_active = is_experiment_active
19
+ @is_qa_tester = is_qa_tester
20
+ end
21
+
22
+ # Convert to hash representation
23
+ # @return [Hash]
24
+ def to_h
25
+ {
26
+ variant_key: @variant_key,
27
+ variant_value: @variant_value,
28
+ experiment_id: @experiment_id,
29
+ is_experiment_active: @is_experiment_active,
30
+ is_qa_tester: @is_qa_tester
31
+ }.compact
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,65 @@
1
+ require 'securerandom'
2
+
3
+ module Mixpanel
4
+ module Flags
5
+ module Utils
6
+ EXPOSURE_EVENT = '$experiment_started'.freeze
7
+
8
+ # FNV-1a 64-bit hash implementation
9
+ # Used for consistent variant assignment
10
+ #
11
+ # @param data [String] Data to hash
12
+ # @return [Integer] 64-bit hash value
13
+ def self.fnv1a_64(data)
14
+ fnv_prime = 0x100000001b3
15
+ hash_value = 0xcbf29ce484222325
16
+
17
+ data.bytes.each do |byte|
18
+ hash_value ^= byte
19
+ hash_value *= fnv_prime
20
+ hash_value &= 0xffffffffffffffff # Keep 64-bit
21
+ end
22
+
23
+ hash_value
24
+ end
25
+
26
+ # Normalized hash for variant assignment
27
+ # Returns a float in the range [0.0, 1.0) for rollout percentage matching
28
+ #
29
+ # @param key [String] Key to hash (typically distinct_id)
30
+ # @param salt [String] Salt value (flag-specific)
31
+ # @return [Float] Value between 0.0 and 1.0 (non-inclusive upper bound)
32
+ def self.normalized_hash(key, salt)
33
+ combined = key.to_s + salt.to_s
34
+ hash_value = fnv1a_64(combined)
35
+ (hash_value % 100) / 100.0
36
+ end
37
+
38
+ # Prepare common query parameters for flags API
39
+ #
40
+ # @param token [String] Mixpanel project token
41
+ # @param $lib_version [String] SDK version
42
+ # @return [Hash] Query parameters
43
+ def self.prepare_common_query_params(token, lib_version)
44
+ {
45
+ 'mp_lib' => 'ruby',
46
+ '$lib_version' => lib_version,
47
+ 'token' => token
48
+ }
49
+ end
50
+
51
+ # Generate W3C traceparent header for distributed tracing
52
+ # Format: 00-{trace-id}-{parent-id}-{trace-flags}
53
+ #
54
+ # @return [String] traceparent header value
55
+ def self.generate_traceparent
56
+ version = '00'
57
+ trace_id = SecureRandom.hex(16)
58
+ parent_id = SecureRandom.hex(8)
59
+ trace_flags = '01' # sampled
60
+
61
+ "#{version}-#{trace_id}-#{parent_id}-#{trace_flags}"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -170,7 +170,7 @@ module Mixpanel
170
170
  def update(message)
171
171
  data = {
172
172
  '$token' => @token,
173
- '$time' => Time.now.to_f,
173
+ '$time' => (Time.now.to_f * 1000).to_i,
174
174
  }.merge(message)
175
175
 
176
176
  message = {'data' => data}
@@ -223,7 +223,7 @@ module Mixpanel
223
223
  def update(message)
224
224
  data = {
225
225
  '$token' => @token,
226
- '$time' => Time.now.to_f,
226
+ '$time' => (Time.now.to_f * 1000).to_i,
227
227
  }.merge(message)
228
228
 
229
229
  message = {'data' => data}
@@ -1,6 +1,8 @@
1
1
  require 'mixpanel-ruby/events.rb'
2
2
  require 'mixpanel-ruby/people.rb'
3
3
  require 'mixpanel-ruby/groups.rb'
4
+ require 'mixpanel-ruby/flags/local_flags_provider.rb'
5
+ require 'mixpanel-ruby/flags/remote_flags_provider.rb'
4
6
 
5
7
  module Mixpanel
6
8
  # Use Mixpanel::Tracker to track events and profile updates in your application.
@@ -33,6 +35,14 @@ module Mixpanel
33
35
  # An instance of Mixpanel::Groups. Use this to send groups updates
34
36
  attr_reader :groups
35
37
 
38
+ # An instance of Mixpanel::Flags::LocalFlagsProvider. Use this for
39
+ # client-side feature flag evaluation
40
+ attr_reader :local_flags
41
+
42
+ # An instance of Mixpanel::Flags::RemoteFlagsProvider. Use this for
43
+ # server-side feature flag evaluation
44
+ attr_reader :remote_flags
45
+
36
46
  # Takes your Mixpanel project token, as a string.
37
47
  #
38
48
  # tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
@@ -52,11 +62,31 @@ module Mixpanel
52
62
  # If a block is provided, it is passed a type (one of :event or :profile_update)
53
63
  # and a string message. This same format is accepted by Mixpanel::Consumer#send!
54
64
  # and Mixpanel::BufferedConsumer#send!
55
- def initialize(token, error_handler=nil, &block)
65
+ def initialize(token, error_handler=nil, local_flags_config: nil, remote_flags_config: nil, &block)
56
66
  super(token, error_handler, &block)
57
67
  @token = token
58
68
  @people = People.new(token, error_handler, &block)
59
69
  @groups = Groups.new(token, error_handler, &block)
70
+
71
+ # Initialize local flags if config provided
72
+ if local_flags_config
73
+ @local_flags = Flags::LocalFlagsProvider.new(
74
+ token,
75
+ local_flags_config,
76
+ method(:track), # Pass bound method as callback
77
+ error_handler || ErrorHandler.new
78
+ )
79
+ end
80
+
81
+ # Initialize remote flags if config provided
82
+ if remote_flags_config
83
+ @remote_flags = Flags::RemoteFlagsProvider.new(
84
+ token,
85
+ remote_flags_config,
86
+ method(:track), # Pass bound method as callback
87
+ error_handler || ErrorHandler.new
88
+ )
89
+ end
60
90
  end
61
91
 
62
92
  # A call to #track is a report that an event has occurred. #track
@@ -165,7 +195,7 @@ module Mixpanel
165
195
  properties = {
166
196
  'distinct_id' => distinct_id,
167
197
  'token' => @token,
168
- 'time' => Time.now.to_f,
198
+ 'time' => (Time.now.to_f * 1000).to_i,
169
199
  'mp_lib' => 'ruby',
170
200
  '$lib_version' => Mixpanel::VERSION,
171
201
  }.merge(properties)
@@ -1,3 +1,3 @@
1
1
  module Mixpanel
2
- VERSION = '2.3.0'
2
+ VERSION = '3.0.0'
3
3
  end
data/lib/mixpanel-ruby.rb CHANGED
@@ -1,3 +1,8 @@
1
1
  require 'mixpanel-ruby/consumer.rb'
2
2
  require 'mixpanel-ruby/tracker.rb'
3
3
  require 'mixpanel-ruby/version.rb'
4
+ require 'mixpanel-ruby/flags/utils.rb'
5
+ require 'mixpanel-ruby/flags/types.rb'
6
+ require 'mixpanel-ruby/flags/flags_provider.rb'
7
+ require 'mixpanel-ruby/flags/local_flags_provider.rb'
8
+ require 'mixpanel-ruby/flags/remote_flags_provider.rb'
@@ -12,10 +12,17 @@ spec = Gem::Specification.new do |spec|
12
12
  spec.homepage = 'https://mixpanel.com/help/reference/ruby'
13
13
  spec.license = 'Apache License 2.0'
14
14
 
15
- spec.required_ruby_version = '>= 2.0.0'
15
+ spec.required_ruby_version = '>= 3.0.0'
16
+ spec.add_runtime_dependency 'mutex_m'
17
+ spec.add_runtime_dependency "base64"
18
+ spec.add_runtime_dependency 'json-logic-rb', '~> 0.1.5'
16
19
 
17
20
  spec.add_development_dependency 'activesupport', '~> 4.0'
18
- spec.add_development_dependency 'rake', '~> 0'
21
+ spec.add_development_dependency 'rake', '~> 13'
19
22
  spec.add_development_dependency 'rspec', '~> 3.0'
20
- spec.add_development_dependency 'webmock', '~> 1.18'
23
+ spec.add_development_dependency 'webmock', '~> 3.16.2'
24
+ spec.add_development_dependency 'debug'
25
+ spec.add_development_dependency 'ruby-lsp-rspec'
26
+ spec.add_development_dependency 'simplecov'
27
+ spec.add_development_dependency 'simplecov-cobertura'
21
28
  end
@@ -27,7 +27,7 @@ describe Mixpanel::Events do
27
27
  'mp_lib' => 'ruby',
28
28
  '$lib_version' => Mixpanel::VERSION,
29
29
  'token' => 'TEST TOKEN',
30
- 'time' => @time_now.to_i
30
+ 'time' => @time_now.to_i * 1000
31
31
  }
32
32
  }]])
33
33
  end
@@ -46,7 +46,7 @@ describe Mixpanel::Events do
46
46
  'mp_lib' => 'ruby',
47
47
  '$lib_version' => Mixpanel::VERSION,
48
48
  'token' => 'TEST TOKEN',
49
- 'time' => @time_now.to_i
49
+ 'time' => @time_now.to_i * 1000
50
50
  }
51
51
  }
52
52
  } ]])