logstash-output-charrington 0.3.24 → 0.3.25
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 +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 +64 -64
- data/lib/logstash/outputs/charrington/process.rb +23 -19
- 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 +32 -37
- data/lib/logstash-output-charrington_jars.rb +2 -1
- data/logstash-output-charrington.gemspec +9 -9
- 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
- metadata +35 -57
@@ -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,7 +223,7 @@ 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)
|
@@ -231,27 +231,27 @@ module Charrington
|
|
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,7 +65,9 @@ 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)
|
@@ -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)
|