logstash-output-charrington 0.3.22 → 0.3.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -4
- data/lib/logstash/outputs/charrington/alter_postgres_table.rb +41 -41
- data/lib/logstash/outputs/charrington/alter_redshift_table.rb +50 -49
- data/lib/logstash/outputs/charrington/create_postgres_table.rb +33 -32
- data/lib/logstash/outputs/charrington/create_redshift_table.rb +34 -32
- data/lib/logstash/outputs/charrington/insert.rb +65 -65
- data/lib/logstash/outputs/charrington/process.rb +24 -20
- data/lib/logstash/outputs/charrington/service.rb +4 -0
- data/lib/logstash/outputs/charrington/transform_postgres.rb +10 -6
- data/lib/logstash/outputs/charrington/transform_redshift.rb +40 -36
- data/lib/logstash/outputs/charrington.rb +33 -38
- data/lib/logstash-output-charrington_jars.rb +17 -4
- data/lib/logstash_output_charrington_jars.rb +6 -0
- data/lib/org/apache/logging/log4j/log4j-api/2.17.0/log4j-api-2.17.0.jar +0 -0
- data/lib/org/apache/logging/log4j/log4j-core/2.17.0/log4j-core-2.17.0.jar +0 -0
- data/lib/org/apache/logging/log4j/log4j-slf4j-impl/2.17.0/log4j-slf4j-impl-2.17.0.jar +0 -0
- data/logstash-output-charrington.gemspec +10 -10
- data/spec/charrington_spec_helper.rb +30 -35
- data/spec/{logstash-output-charrington_test_jars.rb → logstash_output_charrington_test_jars.rb} +2 -1
- data/spec/outputs/charrington_mysql_spec.rb +1 -0
- data/spec/outputs/charrington_postgres_spec.rb +1 -1
- data/spec/outputs/charrington_spec.rb +33 -29
- data/vendor/jar-dependencies/runtime-jars/log4j-api-2.17.0.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/log4j-core-2.17.0.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/log4j-slf4j-impl-2.17.0.jar +0 -0
- metadata +46 -71
- data/lib/org/apache/logging/log4j/log4j-api/2.6.2/log4j-api-2.6.2.jar +0 -0
- data/lib/org/apache/logging/log4j/log4j-slf4j-impl/2.6.2/log4j-slf4j-impl-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/log4j-api-2.6.2.jar +0 -0
- data/vendor/jar-dependencies/runtime-jars/log4j-slf4j-impl-2.6.2.jar +0 -0
@@ -1,24 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require File.join(File.dirname(__FILE__),
|
4
|
-
require File.join(File.dirname(__FILE__),
|
5
|
-
require File.join(File.dirname(__FILE__),
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'create_postgres_table')
|
4
|
+
require File.join(File.dirname(__FILE__), 'create_redshift_table')
|
5
|
+
require File.join(File.dirname(__FILE__), 'alter_postgres_table')
|
6
|
+
require File.join(File.dirname(__FILE__), 'alter_redshift_table')
|
7
|
+
require File.join(File.dirname(__FILE__), 'service')
|
6
8
|
require 'time'
|
7
9
|
|
8
10
|
module Charrington
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
# This service assumes that the data is already clean and in a flattened hash format.
|
12
|
+
# The Transform service should be called before calling this.
|
13
|
+
class Insert # rubocop:disable Metrics/ClassLength
|
13
14
|
include Service
|
14
15
|
include LogStash::Util::Loggable
|
15
16
|
attr_accessor :event, :should_retry
|
16
|
-
attr_reader :connection, :schema, :table_name, :columns, :driver, :opts, :transformer, :tracks
|
17
|
-
|
18
|
-
# TODO create a current_table_columns (alter_postgres_table.rb) query on the tracks table to get the current columns
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
attr_reader :connection, :schema, :table_name, :columns, :driver, :opts, :transformer, :tracks, :event_as_json_keyword, :enable_event_as_json_keyword
|
18
|
+
|
19
|
+
# TODO: create a current_table_columns (alter_postgres_table.rb) query on the tracks table to get the current columns
|
20
|
+
REDSHIFT_TRACKS_COLUMNS = %w[id action app_name received_at uuid uuid_ts anonymous_id context_ip context_library_name context_library_version context_page_path context_page_referrer context_page_title context_page_url context_user_agent event event_text original_timestamp sent_at timestamp user_id user_uid context_campaign_medium context_campaign_name context_page_search context_campaign_source segment_dedupe_id context_campaign_content].freeze
|
21
|
+
POSTGRES_TRACKS_COLUMNS = %w[anonymous_user app_name event published_at session_ip session_library_name session_library_version session_page_path session_page_referrer session_page_search session_page_title session_page_url session_user_agent user_id user_uid].freeze
|
22
|
+
TIMESTAMP_COLUMNS = %w[published_at sent_at original_timestamp received_at timestamp].freeze
|
22
23
|
|
23
24
|
Error = Class.new(StandardError)
|
24
25
|
EventNil = Class.new(Error)
|
@@ -26,19 +27,20 @@ module Charrington
|
|
26
27
|
InsertFailed = Class.new(Error)
|
27
28
|
|
28
29
|
def initialize(connection, event, opts = {})
|
29
|
-
raise EventNil,
|
30
|
+
raise EventNil, 'Table name is nil' if event.nil?
|
31
|
+
|
30
32
|
@transformer = opts[:transformer]
|
31
33
|
@event = event.to_hash
|
32
34
|
@tracks = create_tracks(@event)
|
33
|
-
event_name = event[
|
34
|
-
raise TableNameNil,
|
35
|
+
event_name = event['event'].to_s.strip
|
36
|
+
raise TableNameNil, 'Table name is nil' if event_name.empty?
|
35
37
|
|
36
38
|
@connection = connection
|
37
39
|
@schema = opts[:schema].empty? ? '' : "#{opts[:schema]}."
|
38
40
|
|
39
41
|
@table_name = underscore(event_name)
|
40
42
|
|
41
|
-
@columns = event.keys.map{|x| underscore(x)}
|
43
|
+
@columns = event.keys.map { |x| underscore(x) }
|
42
44
|
@should_retry = false
|
43
45
|
@enable_event_as_json_keyword = opts[:enable_event_as_json_keyword]
|
44
46
|
@event_as_json_keyword = opts[:event_as_json_keyword]
|
@@ -47,35 +49,34 @@ module Charrington
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def call
|
50
|
-
|
52
|
+
logger.info "Attempting insert into table name: #{table_name}"
|
51
53
|
insert_sql = insert_event_statement
|
52
54
|
insert_stmt = connection.prepareStatement(insert_sql)
|
53
|
-
|
55
|
+
logger.info "Insert statement passed into prepareStatement is: #{insert_stmt}"
|
54
56
|
insert_stmt = add_statement_event_params(insert_stmt, event)
|
55
|
-
|
57
|
+
logger.info "Insert statement to be run is: #{insert_stmt.toString}"
|
56
58
|
insert_stmt.execute
|
57
59
|
|
58
|
-
|
60
|
+
logger.info 'Attempting insert into tracks table'
|
59
61
|
do_tracks_insert
|
60
62
|
|
61
63
|
should_retry
|
62
64
|
rescue Java::JavaSql::SQLException => e
|
63
|
-
case e.getSQLState
|
64
|
-
when
|
65
|
-
|
65
|
+
case e.getSQLState
|
66
|
+
when '42P01'
|
67
|
+
logger.info 'Received Java::JavaSql::SQLException with error sql state of 42P01, moving to create table'
|
66
68
|
should_retry = create_table
|
67
|
-
when
|
68
|
-
|
69
|
+
when '42703'
|
70
|
+
logger.info 'Received Java::JavaSql::SQLException with error sql state of 42703, moving to alter table'
|
69
71
|
should_retry = alter_table
|
70
72
|
else
|
71
73
|
raise InsertFailed, "SQLException (Charrington:Insert) #{e.message} #{insert_sql}"
|
72
74
|
end
|
73
75
|
should_retry
|
74
|
-
|
75
|
-
rescue => e
|
76
|
+
rescue StandardError => e
|
76
77
|
raise InsertFailed, "SQLException (Charrington:Insert) #{e.message} #{insert_sql}"
|
77
78
|
ensure
|
78
|
-
insert_stmt
|
79
|
+
insert_stmt&.close
|
79
80
|
cleanup
|
80
81
|
end
|
81
82
|
|
@@ -83,48 +84,48 @@ module Charrington
|
|
83
84
|
tracks_sql = insert_tracks_statement
|
84
85
|
tracks_stmt = connection.prepareStatement(tracks_sql)
|
85
86
|
tracks_stmt = add_statement_event_params(tracks_stmt, tracks)
|
86
|
-
|
87
|
+
logger.info "Insert tracks statment to be run: #{tracks_stmt.toString}"
|
87
88
|
tracks_stmt.execute
|
88
89
|
rescue Java::JavaSql::SQLException => e
|
89
|
-
|
90
|
+
logger.error("SQLException (Charrington:Insert) Insert tracks entry failed. #{e.message} #{tracks_sql}")
|
90
91
|
ensure
|
91
|
-
tracks_stmt
|
92
|
+
tracks_stmt&.close
|
92
93
|
end
|
93
94
|
|
94
95
|
private
|
95
96
|
|
96
97
|
def tracks_columns
|
97
|
-
|
98
|
+
redshift_transform? ? REDSHIFT_TRACKS_COLUMNS : POSTGRES_TRACKS_COLUMNS
|
98
99
|
end
|
99
100
|
|
100
|
-
def
|
101
|
+
def redshift?
|
101
102
|
driver == 'redshift'
|
102
103
|
end
|
103
104
|
|
104
|
-
def
|
105
|
+
def postgres?
|
105
106
|
driver == 'postgres'
|
106
107
|
end
|
107
108
|
|
108
|
-
def
|
109
|
+
def postgres_transform?
|
109
110
|
transformer == 'postgres'
|
110
111
|
end
|
111
112
|
|
112
|
-
def
|
113
|
+
def redshift_transform?
|
113
114
|
transformer == 'redshift'
|
114
115
|
end
|
115
116
|
|
116
117
|
def create_table
|
117
|
-
if
|
118
|
+
if postgres?
|
118
119
|
Charrington::CreatePostgresTable.call(connection, event, schema, table_name, columns, opts)
|
119
|
-
elsif
|
120
|
+
elsif redshift?
|
120
121
|
Charrington::CreateRedshiftTable.call(connection, event, schema, table_name, columns, opts)
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
124
125
|
def alter_table
|
125
|
-
if
|
126
|
+
if postgres?
|
126
127
|
Charrington::AlterPostgresTable.call(connection, event, schema, table_name, columns)
|
127
|
-
elsif
|
128
|
+
elsif redshift?
|
128
129
|
Charrington::AlterRedshiftTable.call(connection, event, schema, table_name, columns)
|
129
130
|
end
|
130
131
|
end
|
@@ -137,7 +138,7 @@ module Charrington
|
|
137
138
|
### Set Variables
|
138
139
|
def create_tracks(event)
|
139
140
|
tracks = event.clone
|
140
|
-
tracks.
|
141
|
+
tracks.each_key do |key|
|
141
142
|
tracks.delete(key) unless tracks_columns.include?(key)
|
142
143
|
end
|
143
144
|
tracks
|
@@ -151,7 +152,6 @@ module Charrington
|
|
151
152
|
@tracks_columns_text ||= arr_to_csv(tracks.keys)
|
152
153
|
end
|
153
154
|
|
154
|
-
|
155
155
|
def value_placeholders(columns)
|
156
156
|
('?' * columns.length).split('')
|
157
157
|
end
|
@@ -168,19 +168,19 @@ module Charrington
|
|
168
168
|
"INSERT INTO #{schema}tracks #{tracks_columns_text} VALUES #{placeholder_text(tracks.keys)}"
|
169
169
|
end
|
170
170
|
|
171
|
-
def add_statement_event_params(stmt, map)
|
171
|
+
def add_statement_event_params(stmt, map) # rubocop:disable Metrics/CyclomaticComplexity
|
172
172
|
values = []
|
173
|
-
map.keys.each_with_index do |key, idx|
|
173
|
+
map.keys.each_with_index do |key, idx| # rubocop:disable Metrics/BlockLength
|
174
174
|
pos = idx + 1
|
175
175
|
value = map[key]
|
176
176
|
values << value
|
177
177
|
|
178
|
-
if
|
178
|
+
if TIMESTAMP_COLUMNS.include?(key)
|
179
179
|
begin
|
180
180
|
time = parse_date(value)
|
181
181
|
stmt.setTimestamp(pos, time)
|
182
182
|
next
|
183
|
-
rescue java.text.ParseException
|
183
|
+
rescue java.text.ParseException
|
184
184
|
time = parse_date(value, "yyyy-MM-dd'T'HH:mm:ss'Z'")
|
185
185
|
stmt.setTimestamp(pos, time)
|
186
186
|
next
|
@@ -203,7 +203,7 @@ module Charrington
|
|
203
203
|
when Float
|
204
204
|
stmt.setFloat(pos, value)
|
205
205
|
when String
|
206
|
-
stmt.setString(pos, value[0,254]) # truncate at 254 string characters
|
206
|
+
stmt.setString(pos, value[0, 254]) # truncate at 254 string characters
|
207
207
|
when Array, Hash
|
208
208
|
stmt.setString(pos, value.to_json)
|
209
209
|
when true, false
|
@@ -223,35 +223,35 @@ module Charrington
|
|
223
223
|
end
|
224
224
|
|
225
225
|
def arr_to_csv(arr)
|
226
|
-
|
226
|
+
"(#{arr.join(', ')})"
|
227
227
|
end
|
228
228
|
|
229
229
|
def clearable(obj)
|
230
|
-
obj.is_a?
|
230
|
+
obj.is_a?(Hash) || obj.is_a?(Array)
|
231
231
|
end
|
232
232
|
|
233
233
|
def underscore(str)
|
234
|
-
str
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
234
|
+
str
|
235
|
+
.gsub(/::/, '/')
|
236
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
237
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
238
|
+
.downcase
|
239
|
+
.gsub(/[^a-z0-9]+/, '_')
|
240
|
+
.gsub(/\A_+/, '')
|
241
|
+
.gsub(/_+\z/, '')[0, 64]
|
242
242
|
end
|
243
243
|
|
244
244
|
### SQL
|
245
245
|
|
246
246
|
def execute(connection, sql)
|
247
|
-
statement = connection.prepareStatement(
|
248
|
-
statement.execute
|
247
|
+
statement = connection.prepareStatement(sql.gsub(/\s+/, ' ').strip)
|
248
|
+
statement.execute
|
249
249
|
rescue Java::OrgPostgresqlUtil::PSQLException => e
|
250
|
-
|
250
|
+
logger.error "PSQLException: #{e.message}, with SQL: #{sql}"
|
251
251
|
rescue Java::JavaSql::SQLException => e
|
252
|
-
|
252
|
+
logger.error "Redshift SQLException: #{e.message}, with SQL: #{sql}"
|
253
253
|
ensure
|
254
|
-
statement
|
254
|
+
statement&.close
|
255
255
|
end
|
256
256
|
end
|
257
257
|
end
|
@@ -1,10 +1,11 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'service')
|
2
4
|
|
3
5
|
module Charrington
|
6
|
+
# This service starts the process of attempting to insert a row.
|
7
|
+
# It handles retries where applicable.
|
4
8
|
class Process
|
5
|
-
# This service starts the process of attempting to insert a row.
|
6
|
-
# It handles retries where applicable.
|
7
|
-
|
8
9
|
include Service
|
9
10
|
include LogStash::Util::Loggable
|
10
11
|
attr_reader :event, :connection, :opts, :max_retries, :schema, :retry_max_interval, :driver, :transformer
|
@@ -14,8 +15,9 @@ module Charrington
|
|
14
15
|
ProcessFailed = Class.new(Error)
|
15
16
|
EventNil = Class.new(Error)
|
16
17
|
|
17
|
-
def initialize(connection, event, opts={})
|
18
|
-
raise EventNil,
|
18
|
+
def initialize(connection, event, opts = {})
|
19
|
+
raise EventNil, 'Event is nil' if event.nil?
|
20
|
+
|
19
21
|
@connection = connection
|
20
22
|
@event = event.to_hash
|
21
23
|
@opts = opts
|
@@ -31,18 +33,18 @@ module Charrington
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def call
|
34
|
-
while should_retry
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
36
|
+
while should_retry
|
37
|
+
logger.info "Found transformer of #{transformer} for driver of #{driver} with event of: #{event}"
|
38
|
+
transformed =
|
39
|
+
case transformer
|
40
|
+
when 'redshift'
|
41
|
+
Charrington::TransformRedshift.call(event)
|
42
|
+
else
|
43
|
+
Charrington::TransformPostgres.call(event)
|
44
|
+
end
|
45
|
+
logger.info "Transformed event into: #{transformed}"
|
44
46
|
should_retry = Charrington::Insert.call(connection, transformed, opts)
|
45
|
-
break
|
47
|
+
break unless should_retry
|
46
48
|
|
47
49
|
@attempts += 1
|
48
50
|
break if @attempts > max_retries
|
@@ -51,10 +53,10 @@ module Charrington
|
|
51
53
|
# Double the interval for the next time through to achieve exponential backoff
|
52
54
|
sleep_interval
|
53
55
|
end
|
54
|
-
rescue => e
|
56
|
+
rescue StandardError => e
|
55
57
|
raise ProcessFailed, e.message
|
56
58
|
ensure
|
57
|
-
connection
|
59
|
+
connection&.close
|
58
60
|
@event.clear if clearable(@event)
|
59
61
|
end
|
60
62
|
|
@@ -63,11 +65,13 @@ module Charrington
|
|
63
65
|
def sleep_interval
|
64
66
|
sleep(retry_interval)
|
65
67
|
doubled = retry_interval * 2
|
68
|
+
# rubocop:disable Lint/UselessAssignment
|
66
69
|
retry_interval = doubled > retry_max_interval ? retry_max_interval : doubled
|
70
|
+
# rubocop:enable Lint/UselessAssignment
|
67
71
|
end
|
68
72
|
|
69
73
|
def clearable(obj)
|
70
|
-
obj.is_a?
|
74
|
+
obj.is_a?(Hash) || obj.is_a?(Array)
|
71
75
|
end
|
72
76
|
end
|
73
77
|
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Service mix in that provides a `call` helper method
|
2
4
|
module Service
|
3
5
|
def self.included(base)
|
4
6
|
base.extend ClassMethods
|
5
7
|
end
|
6
8
|
|
9
|
+
# Adds a `call` method that creates a new instance
|
10
|
+
# and delegates to the child's call method
|
7
11
|
module ClassMethods
|
8
12
|
def call(*args)
|
9
13
|
new(*args).call
|
@@ -1,6 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'service')
|
2
4
|
|
3
5
|
module Charrington
|
6
|
+
# Inserts and modifies a Postgres database
|
4
7
|
class TransformPostgres
|
5
8
|
include Service
|
6
9
|
attr_accessor :event
|
@@ -11,11 +14,12 @@ module Charrington
|
|
11
14
|
TableNameNil = Class.new(Error)
|
12
15
|
ColumnBlacklist = Class.new(Error)
|
13
16
|
|
14
|
-
KEY_FILTER_BLACKLIST = [
|
15
|
-
KEY_RAISE_BLACKLIST = [
|
17
|
+
KEY_FILTER_BLACKLIST = %w[host path jwt sequence].freeze
|
18
|
+
KEY_RAISE_BLACKLIST = %w[id inserted_at].freeze
|
16
19
|
|
17
20
|
def initialize(event)
|
18
|
-
raise EventNil,
|
21
|
+
raise EventNil, 'Event is nil' if event.nil?
|
22
|
+
|
19
23
|
event = event.to_hash
|
20
24
|
@event = drop_keys(event)
|
21
25
|
@top_level_keys = @event.keys
|
@@ -34,11 +38,11 @@ module Charrington
|
|
34
38
|
def check_blacklist
|
35
39
|
arr = []
|
36
40
|
KEY_RAISE_BLACKLIST.each { |k| arr << k if event.keys.include?(k) }
|
37
|
-
raise ColumnBlacklist, "Event contains these blacklisted keys: #{arr.join(
|
41
|
+
raise ColumnBlacklist, "Event contains these blacklisted keys: #{arr.join(',')}" unless arr.empty?
|
38
42
|
end
|
39
43
|
|
40
44
|
def drop_keys(event)
|
41
|
-
event.delete_if {|k, _v| k.start_with?(
|
45
|
+
event.delete_if { |k, _v| k.start_with?('@') || KEY_FILTER_BLACKLIST.include?(k) }
|
42
46
|
end
|
43
47
|
|
44
48
|
def flatten_hash(hash)
|
@@ -1,7 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'service')
|
2
4
|
require 'securerandom'
|
3
5
|
|
4
6
|
module Charrington
|
7
|
+
# Inserts and modifies a Postgres/Redshift database
|
5
8
|
class TransformRedshift
|
6
9
|
include Service
|
7
10
|
attr_accessor :event
|
@@ -12,11 +15,12 @@ module Charrington
|
|
12
15
|
TableNameNil = Class.new(Error)
|
13
16
|
ColumnBlacklist = Class.new(Error)
|
14
17
|
|
15
|
-
KEY_FILTER_BLACKLIST = [
|
16
|
-
KEY_RAISE_BLACKLIST = ['inserted_at']
|
18
|
+
KEY_FILTER_BLACKLIST = %w[host path jwt sequence].freeze
|
19
|
+
KEY_RAISE_BLACKLIST = ['inserted_at'].freeze
|
17
20
|
|
18
21
|
def initialize(event)
|
19
|
-
raise EventNil,
|
22
|
+
raise EventNil, 'Event is nil' if event.nil?
|
23
|
+
|
20
24
|
event = event.to_hash
|
21
25
|
@event = drop_keys(event)
|
22
26
|
@top_level_keys = @event.keys
|
@@ -27,17 +31,17 @@ module Charrington
|
|
27
31
|
handle_event_key(event)
|
28
32
|
add_id_to_event(event)
|
29
33
|
|
30
|
-
handle_key_transform(event,
|
31
|
-
handle_key_transform(event,
|
32
|
-
handle_key_transform(event,
|
33
|
-
handle_key_transform(event,
|
34
|
-
handle_key_transform(event,
|
34
|
+
handle_key_transform(event, 'anonymous_id', 'anonymous_user')
|
35
|
+
handle_key_transform(event, 'sent_at', 'published_at')
|
36
|
+
handle_key_transform(event, 'original_timestamp', 'sent_at')
|
37
|
+
handle_key_transform(event, 'received_at', 'sent_at')
|
38
|
+
handle_key_transform(event, 'timestamp', 'sent_at')
|
35
39
|
|
36
40
|
handle_meta_section(event)
|
37
41
|
|
38
42
|
transform_session_stuff(event)
|
39
43
|
|
40
|
-
event.delete_if {|k, _v| [
|
44
|
+
event.delete_if { |k, _v| %w[session meta published_at anonymous_user].include?(k) }
|
41
45
|
|
42
46
|
event
|
43
47
|
end
|
@@ -45,65 +49,65 @@ module Charrington
|
|
45
49
|
private
|
46
50
|
|
47
51
|
def handle_key_transform(hash, key_that_should_be_there, key_to_take_value_from)
|
48
|
-
|
49
|
-
hash[key_that_should_be_there] = hash[key_to_take_value_from] || ""
|
50
|
-
else
|
52
|
+
if hash.key?(key_that_should_be_there)
|
51
53
|
hash
|
54
|
+
else
|
55
|
+
hash[key_that_should_be_there] = hash[key_to_take_value_from] || ''
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
55
59
|
def add_id_to_event(hash)
|
56
|
-
hash[
|
60
|
+
hash['id'] = SecureRandom.hex(10)
|
57
61
|
end
|
58
62
|
|
59
63
|
def handle_event_key(hash)
|
60
|
-
event_name = hash[
|
64
|
+
event_name = hash['event'] || ''
|
61
65
|
|
62
|
-
hash[
|
66
|
+
hash['event_text'] = event_name
|
63
67
|
|
64
|
-
hash[
|
68
|
+
hash['event'] = underscore_event_name(event_name)
|
65
69
|
end
|
66
70
|
|
67
71
|
def underscore_event_name(event_name)
|
68
|
-
event_name
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
72
|
+
event_name
|
73
|
+
.gsub(/::/, '/')
|
74
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
75
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
76
|
+
.downcase
|
77
|
+
.gsub(/[^a-z0-9]+/, '_')
|
78
|
+
.gsub(/\A_+/, '')
|
79
|
+
.gsub(/_+\z/, '')
|
76
80
|
end
|
77
81
|
|
78
82
|
def transform_session_stuff(hash)
|
79
|
-
session_stuff = hash[
|
83
|
+
session_stuff = hash['session'] || {}
|
80
84
|
|
81
|
-
session_stuff.each
|
82
|
-
next unless k.
|
85
|
+
session_stuff.each do |k, v|
|
86
|
+
next unless k.is_a?(String)
|
83
87
|
|
84
88
|
hash["context_#{k}"] = v
|
85
|
-
|
89
|
+
end
|
86
90
|
end
|
87
91
|
|
88
92
|
def handle_meta_section(hash)
|
89
|
-
meta_section = hash[
|
93
|
+
meta_section = hash['meta'] || {}
|
90
94
|
|
91
|
-
meta_section.each
|
92
|
-
next unless k.
|
93
|
-
next if [Array, Hash].map { |type| v.
|
95
|
+
meta_section.each do |k, v|
|
96
|
+
next unless k.is_a?(String)
|
97
|
+
next if [Array, Hash].map { |type| v.is_a?(type) }.any?
|
94
98
|
|
95
99
|
hash[k] = v
|
96
|
-
|
100
|
+
end
|
97
101
|
end
|
98
102
|
|
99
103
|
def check_blacklist
|
100
104
|
arr = []
|
101
105
|
KEY_RAISE_BLACKLIST.each { |k| arr << k if event.keys.include?(k) }
|
102
|
-
raise ColumnBlacklist, "Event contains these blacklisted keys: #{arr.join(
|
106
|
+
raise ColumnBlacklist, "Event contains these blacklisted keys: #{arr.join(',')}" unless arr.empty?
|
103
107
|
end
|
104
108
|
|
105
109
|
def drop_keys(event)
|
106
|
-
event.delete_if {|k, _v| k.start_with?(
|
110
|
+
event.delete_if { |k, _v| k.start_with?('@') || KEY_FILTER_BLACKLIST.include?(k) }
|
107
111
|
end
|
108
112
|
|
109
113
|
def flatten_hash(hash)
|