ablaevent-ruby 2.3.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/bin/posthog +109 -0
- data/lib/posthog/backoff_policy.rb +44 -0
- data/lib/posthog/client.rb +291 -0
- data/lib/posthog/defaults.rb +39 -0
- data/lib/posthog/feature_flags.rb +466 -0
- data/lib/posthog/field_parser.rb +169 -0
- data/lib/posthog/logging.rb +68 -0
- data/lib/posthog/message_batch.rb +71 -0
- data/lib/posthog/noop_worker.rb +16 -0
- data/lib/posthog/response.rb +13 -0
- data/lib/posthog/send_worker.rb +67 -0
- data/lib/posthog/transport.rb +144 -0
- data/lib/posthog/utils.rb +132 -0
- data/lib/posthog/version.rb +3 -0
- data/lib/posthog-ruby.rb +1 -0
- data/lib/posthog.rb +9 -0
- metadata +185 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
require 'posthog/logging'
|
|
3
|
+
|
|
4
|
+
class PostHog
|
|
5
|
+
# A batch of `Message`s to be sent to the API
|
|
6
|
+
class MessageBatch
|
|
7
|
+
class JSONGenerationError < StandardError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
extend Forwardable
|
|
11
|
+
include PostHog::Logging
|
|
12
|
+
include PostHog::Defaults::MessageBatch
|
|
13
|
+
|
|
14
|
+
def initialize(max_message_count)
|
|
15
|
+
@messages = []
|
|
16
|
+
@max_message_count = max_message_count
|
|
17
|
+
@json_size = 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def <<(message)
|
|
21
|
+
begin
|
|
22
|
+
message_json = message.to_json
|
|
23
|
+
rescue StandardError => e
|
|
24
|
+
raise JSONGenerationError, "Serialization error: #{e}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
message_json_size = message_json.bytesize
|
|
28
|
+
if message_too_big?(message_json_size)
|
|
29
|
+
logger.error('a message exceeded the maximum allowed size')
|
|
30
|
+
else
|
|
31
|
+
@messages << message
|
|
32
|
+
@json_size += message_json_size + 1 # One byte for the comma
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def full?
|
|
37
|
+
item_count_exhausted? || size_exhausted?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def clear
|
|
41
|
+
@messages.clear
|
|
42
|
+
@json_size = 0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def_delegators :@messages, :to_json
|
|
46
|
+
def_delegators :@messages, :empty?
|
|
47
|
+
def_delegators :@messages, :length
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def item_count_exhausted?
|
|
52
|
+
@messages.length >= @max_message_count
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def message_too_big?(message_json_size)
|
|
56
|
+
message_json_size > Defaults::Message::MAX_BYTES
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# We consider the max size here as just enough to leave room for one more
|
|
60
|
+
# message of the largest size possible. This is a shortcut that allows us
|
|
61
|
+
# to use a native Ruby `Queue` that doesn't allow peeking. The tradeoff
|
|
62
|
+
# here is that we might fit in less messages than possible into a batch.
|
|
63
|
+
#
|
|
64
|
+
# The alternative is to use our own `Queue` implementation that allows
|
|
65
|
+
# peeking, and to consider the next message size when calculating whether
|
|
66
|
+
# the message can be accomodated in this batch.
|
|
67
|
+
def size_exhausted?
|
|
68
|
+
@json_size >= (MAX_BYTES - Defaults::Message::MAX_BYTES)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'posthog/defaults'
|
|
2
|
+
require 'posthog/message_batch'
|
|
3
|
+
require 'posthog/transport'
|
|
4
|
+
require 'posthog/utils'
|
|
5
|
+
|
|
6
|
+
class PostHog
|
|
7
|
+
class SendWorker
|
|
8
|
+
include PostHog::Utils
|
|
9
|
+
include PostHog::Defaults
|
|
10
|
+
include PostHog::Logging
|
|
11
|
+
|
|
12
|
+
# public: Creates a new worker
|
|
13
|
+
#
|
|
14
|
+
# The worker continuously takes messages off the queue
|
|
15
|
+
# and makes requests to the posthog.com api
|
|
16
|
+
#
|
|
17
|
+
# queue - Queue synchronized between client and worker
|
|
18
|
+
# api_key - String of the project's API key
|
|
19
|
+
# options - Hash of worker options
|
|
20
|
+
# batch_size - Fixnum of how many items to send in a batch
|
|
21
|
+
# on_error - Proc of what to do on an error
|
|
22
|
+
#
|
|
23
|
+
def initialize(queue, api_key, options = {})
|
|
24
|
+
symbolize_keys! options
|
|
25
|
+
@queue = queue
|
|
26
|
+
@api_key = api_key
|
|
27
|
+
@on_error = options[:on_error] || proc { |status, error| }
|
|
28
|
+
batch_size = options[:batch_size] || Defaults::MessageBatch::MAX_SIZE
|
|
29
|
+
@batch = MessageBatch.new(batch_size)
|
|
30
|
+
@lock = Mutex.new
|
|
31
|
+
@transport = Transport.new api_host: options[:host], skip_ssl_verification: options[:skip_ssl_verification]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# public: Continuously runs the loop to check for new events
|
|
35
|
+
#
|
|
36
|
+
def run
|
|
37
|
+
until Thread.current[:should_exit]
|
|
38
|
+
return if @queue.empty?
|
|
39
|
+
|
|
40
|
+
@lock.synchronize do
|
|
41
|
+
consume_message_from_queue! until @batch.full? || @queue.empty?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
res = @transport.send @api_key, @batch
|
|
45
|
+
@on_error.call(res.status, res.error) unless res.status == 200
|
|
46
|
+
|
|
47
|
+
@lock.synchronize { @batch.clear }
|
|
48
|
+
end
|
|
49
|
+
ensure
|
|
50
|
+
@transport.shutdown
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# public: Check whether we have outstanding requests.
|
|
54
|
+
#
|
|
55
|
+
def is_requesting?
|
|
56
|
+
@lock.synchronize { !@batch.empty? }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def consume_message_from_queue!
|
|
62
|
+
@batch << @queue.pop
|
|
63
|
+
rescue MessageBatch::JSONGenerationError => e
|
|
64
|
+
@on_error.call(-1, e.to_s)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'posthog/defaults'
|
|
2
|
+
require 'posthog/utils'
|
|
3
|
+
require 'posthog/response'
|
|
4
|
+
require 'posthog/logging'
|
|
5
|
+
require 'posthog/backoff_policy'
|
|
6
|
+
require 'net/http'
|
|
7
|
+
require 'net/https'
|
|
8
|
+
require 'json'
|
|
9
|
+
|
|
10
|
+
class PostHog
|
|
11
|
+
class Transport
|
|
12
|
+
include PostHog::Defaults::Request
|
|
13
|
+
include PostHog::Utils
|
|
14
|
+
include PostHog::Logging
|
|
15
|
+
|
|
16
|
+
def initialize(options = {})
|
|
17
|
+
if options[:api_host]
|
|
18
|
+
uri = URI.parse(options[:api_host])
|
|
19
|
+
options[:host] = uri.host
|
|
20
|
+
options[:ssl] = uri.scheme == 'https'
|
|
21
|
+
options[:port] = uri.port
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
options[:host] = !options[:host].nil? ? options[:host] : HOST
|
|
25
|
+
options[:port] = !options[:port].nil? ? options[:port] : PORT
|
|
26
|
+
options[:ssl] = !options[:ssl].nil? ? options[:ssl] : SSL
|
|
27
|
+
|
|
28
|
+
@headers = options[:headers] || HEADERS
|
|
29
|
+
@path = options[:path] || PATH
|
|
30
|
+
@retries = options[:retries] || RETRIES
|
|
31
|
+
@backoff_policy = options[:backoff_policy] || PostHog::BackoffPolicy.new
|
|
32
|
+
|
|
33
|
+
http = Net::HTTP.new(options[:host], options[:port])
|
|
34
|
+
http.use_ssl = options[:ssl]
|
|
35
|
+
http.read_timeout = 8
|
|
36
|
+
http.open_timeout = 4
|
|
37
|
+
if options[:skip_ssl_verification]
|
|
38
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
@http = http
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Sends a batch of messages to the API
|
|
45
|
+
#
|
|
46
|
+
# @return [Response] API response
|
|
47
|
+
def send(api_key, batch)
|
|
48
|
+
logger.debug("Sending request for #{batch.length} items")
|
|
49
|
+
|
|
50
|
+
last_response, exception =
|
|
51
|
+
retry_with_backoff(@retries) do
|
|
52
|
+
status_code, body = send_request(api_key, batch)
|
|
53
|
+
error = JSON.parse(body)['error']
|
|
54
|
+
should_retry = should_retry_request?(status_code, body)
|
|
55
|
+
logger.debug("Response status code: #{status_code}")
|
|
56
|
+
logger.debug("Response error: #{error}") if error
|
|
57
|
+
|
|
58
|
+
[Response.new(status_code, error), should_retry]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if exception
|
|
62
|
+
logger.error(exception.message)
|
|
63
|
+
exception.backtrace.each { |line| logger.error(line) }
|
|
64
|
+
Response.new(-1, exception.to_s)
|
|
65
|
+
else
|
|
66
|
+
last_response
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Closes a persistent connection if it exists
|
|
71
|
+
def shutdown
|
|
72
|
+
@http.finish if @http.started?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def should_retry_request?(status_code, body)
|
|
78
|
+
if status_code >= 500
|
|
79
|
+
true # Server error
|
|
80
|
+
elsif status_code == 429
|
|
81
|
+
true # Rate limited
|
|
82
|
+
elsif status_code >= 400
|
|
83
|
+
logger.error(body)
|
|
84
|
+
false # Client error. Do not retry, but log
|
|
85
|
+
else
|
|
86
|
+
false
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Takes a block that returns [result, should_retry].
|
|
91
|
+
#
|
|
92
|
+
# Retries upto `retries_remaining` times, if `should_retry` is false or
|
|
93
|
+
# an exception is raised. `@backoff_policy` is used to determine the
|
|
94
|
+
# duration to sleep between attempts
|
|
95
|
+
#
|
|
96
|
+
# Returns [last_result, raised_exception]
|
|
97
|
+
def retry_with_backoff(retries_remaining, &block)
|
|
98
|
+
result, caught_exception = nil
|
|
99
|
+
should_retry = false
|
|
100
|
+
|
|
101
|
+
begin
|
|
102
|
+
result, should_retry = yield
|
|
103
|
+
return result, nil unless should_retry
|
|
104
|
+
rescue StandardError => e
|
|
105
|
+
should_retry = true
|
|
106
|
+
caught_exception = e
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
if should_retry && (retries_remaining > 1)
|
|
110
|
+
logger.debug("Retrying request, #{retries_remaining} retries left")
|
|
111
|
+
sleep(@backoff_policy.next_interval.to_f / 1000)
|
|
112
|
+
retry_with_backoff(retries_remaining - 1, &block)
|
|
113
|
+
else
|
|
114
|
+
[result, caught_exception]
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Sends a request for the batch, returns [status_code, body]
|
|
119
|
+
def send_request(api_key, batch)
|
|
120
|
+
payload = JSON.generate(api_key: api_key, batch: batch)
|
|
121
|
+
|
|
122
|
+
request = Net::HTTP::Post.new(@path, @headers)
|
|
123
|
+
|
|
124
|
+
if self.class.stub
|
|
125
|
+
logger.debug "stubbed request to #{@path}: " \
|
|
126
|
+
"api key = #{api_key}, batch = #{JSON.generate(batch)}"
|
|
127
|
+
|
|
128
|
+
[200, '{}']
|
|
129
|
+
else
|
|
130
|
+
@http.start unless @http.started? # Maintain a persistent connection
|
|
131
|
+
response = @http.request(request, payload)
|
|
132
|
+
[response.code.to_i, response.body]
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
class << self
|
|
137
|
+
attr_writer :stub
|
|
138
|
+
|
|
139
|
+
def stub
|
|
140
|
+
@stub || ENV['STUB']
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
3
|
+
class PostHog
|
|
4
|
+
|
|
5
|
+
class InconclusiveMatchError < StandardError
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Utils
|
|
9
|
+
extend self
|
|
10
|
+
|
|
11
|
+
# public: Return a new hash with keys converted from strings to symbols
|
|
12
|
+
#
|
|
13
|
+
def symbolize_keys(hash)
|
|
14
|
+
hash.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# public: Convert hash keys from strings to symbols in place
|
|
18
|
+
#
|
|
19
|
+
def symbolize_keys!(hash)
|
|
20
|
+
hash.replace symbolize_keys hash
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# public: Return a new hash with keys as strings
|
|
24
|
+
#
|
|
25
|
+
def stringify_keys(hash)
|
|
26
|
+
hash.each_with_object({}) { |(k, v), memo| memo[k.to_s] = v }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# public: Returns a new hash with all the date values in the into iso8601
|
|
30
|
+
# strings
|
|
31
|
+
#
|
|
32
|
+
def isoify_dates(hash)
|
|
33
|
+
hash.each_with_object({}) do |(k, v), memo|
|
|
34
|
+
memo[k] = datetime_in_iso8601(v)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# public: Converts all the date values in the into iso8601 strings in place
|
|
39
|
+
#
|
|
40
|
+
def isoify_dates!(hash)
|
|
41
|
+
hash.replace isoify_dates hash
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# public: Returns a uid string
|
|
45
|
+
#
|
|
46
|
+
def uid
|
|
47
|
+
arr = SecureRandom.random_bytes(16).unpack('NnnnnN')
|
|
48
|
+
arr[2] = (arr[2] & 0x0fff) | 0x4000
|
|
49
|
+
arr[3] = (arr[3] & 0x3fff) | 0x8000
|
|
50
|
+
'%08x-%04x-%04x-%04x-%04x%08x' % arr
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def datetime_in_iso8601(datetime)
|
|
54
|
+
case datetime
|
|
55
|
+
when Time
|
|
56
|
+
time_in_iso8601 datetime
|
|
57
|
+
when DateTime
|
|
58
|
+
time_in_iso8601 datetime.to_time
|
|
59
|
+
when Date
|
|
60
|
+
date_in_iso8601 datetime
|
|
61
|
+
else
|
|
62
|
+
datetime
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def time_in_iso8601(time, fraction_digits = 3)
|
|
67
|
+
fraction =
|
|
68
|
+
(('.%06i' % time.usec)[0, fraction_digits + 1] if fraction_digits > 0)
|
|
69
|
+
|
|
70
|
+
"#{time.strftime('%Y-%m-%dT%H:%M:%S')}#{fraction}#{formatted_offset(time, true, 'Z')}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def date_in_iso8601(date)
|
|
74
|
+
date.strftime('%F')
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def formatted_offset(time, colon = true, alternate_utc_string = nil)
|
|
78
|
+
time.utc? && alternate_utc_string ||
|
|
79
|
+
seconds_to_utc_offset(time.utc_offset, colon)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def seconds_to_utc_offset(seconds, colon = true)
|
|
83
|
+
(colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON) % [
|
|
84
|
+
(seconds < 0 ? '-' : '+'),
|
|
85
|
+
(seconds.abs / 3600),
|
|
86
|
+
((seconds.abs % 3600) / 60)
|
|
87
|
+
]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def convert_to_datetime(value)
|
|
91
|
+
if value.respond_to?(:strftime)
|
|
92
|
+
parsed_date = value
|
|
93
|
+
return parsed_date
|
|
94
|
+
elsif value.respond_to?(:to_str)
|
|
95
|
+
begin
|
|
96
|
+
parsed_date = DateTime.parse(value)
|
|
97
|
+
return parsed_date
|
|
98
|
+
rescue ArgumentError => e
|
|
99
|
+
raise InconclusiveMatchError.new("#{value} is not in a valid date format")
|
|
100
|
+
end
|
|
101
|
+
else
|
|
102
|
+
raise InconclusiveMatchError.new("The date provided must be a string or date object")
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
UTC_OFFSET_WITH_COLON = '%s%02d:%02d'
|
|
107
|
+
UTC_OFFSET_WITHOUT_COLON = UTC_OFFSET_WITH_COLON.sub(':', '')
|
|
108
|
+
|
|
109
|
+
def is_valid_regex(regex)
|
|
110
|
+
begin
|
|
111
|
+
Regexp.new(regex)
|
|
112
|
+
return true
|
|
113
|
+
rescue RegexpError
|
|
114
|
+
return false
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class SizeLimitedHash < Hash
|
|
119
|
+
def initialize(max_length, *args, &block)
|
|
120
|
+
super(*args, &block)
|
|
121
|
+
@max_length = max_length
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def []=(key, value)
|
|
125
|
+
if length >= @max_length
|
|
126
|
+
clear
|
|
127
|
+
end
|
|
128
|
+
super
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
data/lib/posthog-ruby.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'posthog'
|
data/lib/posthog.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ablaevent-ruby
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 2.3.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- ''
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2023-07-07 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: concurrent-ruby
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: commander
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '4.4'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '4.4'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '10.3'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '10.3'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rspec
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '3.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '3.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: tzinfo
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - '='
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: 1.2.1
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - '='
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 1.2.1
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: activesupport
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: 4.1.11
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: 4.1.11
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: oj
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: 3.6.2
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: 3.6.2
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: rubocop
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: 0.51.0
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: 0.51.0
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: codecov
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: 0.1.4
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: 0.1.4
|
|
139
|
+
description: The PostHog ruby library
|
|
140
|
+
email: hey@posthog.com
|
|
141
|
+
executables:
|
|
142
|
+
- posthog
|
|
143
|
+
extensions: []
|
|
144
|
+
extra_rdoc_files: []
|
|
145
|
+
files:
|
|
146
|
+
- bin/posthog
|
|
147
|
+
- lib/posthog-ruby.rb
|
|
148
|
+
- lib/posthog.rb
|
|
149
|
+
- lib/posthog/backoff_policy.rb
|
|
150
|
+
- lib/posthog/client.rb
|
|
151
|
+
- lib/posthog/defaults.rb
|
|
152
|
+
- lib/posthog/feature_flags.rb
|
|
153
|
+
- lib/posthog/field_parser.rb
|
|
154
|
+
- lib/posthog/logging.rb
|
|
155
|
+
- lib/posthog/message_batch.rb
|
|
156
|
+
- lib/posthog/noop_worker.rb
|
|
157
|
+
- lib/posthog/response.rb
|
|
158
|
+
- lib/posthog/send_worker.rb
|
|
159
|
+
- lib/posthog/transport.rb
|
|
160
|
+
- lib/posthog/utils.rb
|
|
161
|
+
- lib/posthog/version.rb
|
|
162
|
+
homepage: https://github.com/AblaAnalytics/ablaevent-ruby
|
|
163
|
+
licenses:
|
|
164
|
+
- MIT
|
|
165
|
+
metadata: {}
|
|
166
|
+
post_install_message:
|
|
167
|
+
rdoc_options: []
|
|
168
|
+
require_paths:
|
|
169
|
+
- lib
|
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
171
|
+
requirements:
|
|
172
|
+
- - ">="
|
|
173
|
+
- !ruby/object:Gem::Version
|
|
174
|
+
version: '2.0'
|
|
175
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - ">="
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '0'
|
|
180
|
+
requirements: []
|
|
181
|
+
rubygems_version: 3.1.2
|
|
182
|
+
signing_key:
|
|
183
|
+
specification_version: 4
|
|
184
|
+
summary: PostHog library
|
|
185
|
+
test_files: []
|