logstash-filter-mixpanel 0.1.3 → 0.1.4

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YzNhMGYxMmM5OTBkZjFlMjQxZDc0NjE4ZjRmMzk1NWI0ZjQ4N2U2ZA==
4
+ ZDU0ODI4YTRjYjk1YzRiNDk5YTdkZTNhMWRmM2U4MjMyNzNmMmMxNA==
5
5
  data.tar.gz: !binary |-
6
- YTRlMzhmOTc3MzhlZjYwZWZkZWJiMTdlY2Q1Mzk3YWJiOWNhMWMyMg==
6
+ Y2E2ZDE0OGNjOGQ0MGQwNDBjNDhlZGRkYjEzMDc5ODcyNmQ1MTA5ZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MzIyMDhkODU3YWJkMjdlNGY5Yzc4ZGUyMDI4NzRjMWVjZDVmYjhkY2Q5M2Fi
10
- NTIxY2RmMTkyYTMzYmNiMzdiYzRjZTNjNTFkYTI2ZWJlN2E4YjNkNzIyZDU0
11
- ZTljYTNkZGMzMTE1NTE5ZWY2MzkyYjExOWI4ZmRlZTRiOTI5MDA=
9
+ NmFjMmI3MTdkMjAxOWVkY2RlNzBmOWJiMTc0MDU0OWQzZGFmODZiZWRhYjE1
10
+ ZThlMTI1NGNlMjU0NTIxMmQ3NDE4Njk4OWFjODNlZmNjNmNlZGFiMTdlNGNh
11
+ YTg0ZTIxNjU5NGNkNmExNmJhODVlZmMzYjFmYzY1YzUzZWYzMmE=
12
12
  data.tar.gz: !binary |-
13
- MWU1NDBjYmUyOGRjNTk3MGFiZjY2MWM2YTc0MDAxNzI2YmQzM2U5YjViMTQz
14
- ZGUwYTQ4ZmMzNTJhZjRlOTI1ODBhMTkzMWFhNDQxOWE4MGJiM2Q0MjU1MmJl
15
- ZWU4YWVjYmJhYWE4MzIxOGNhYWMzMjY3M2M2YWJhNDczZTIyYzY=
13
+ ODViNGM2ZDU0NjhlYmQ0NGYwYjkyZjVkM2UxODkyMmEyYzUwNGQ2ZmI1MDQ4
14
+ MTgwOTMzYjY5NDRmNzdkOGVhZjk3NWNiYTE1ZWUxMTJkNjJlOTFkODI4N2Mw
15
+ YTY2OTE4NDQ5ZmI0ZjJkZmMwZDg2YjUxODNiN2JiZGJiZGYwZjY=
@@ -24,9 +24,11 @@ class LogStash::Filters::Mixpanel < LogStash::Filters::Base
24
24
  config :api_key, :validate => :string, :required => true
25
25
  config :api_secret, :validate => :string, :required => true
26
26
  config :where, :validate => :array, :required => true
27
+ config :use_or, :validate => :boolean, :default => false
27
28
  config :source, :validate => :string, :default => 'message'
28
29
  config :target, :validate => :string, :default => 'mixpanel'
29
30
  config :tag_on_failure, :validate => :array, :default => ['_mixpanelfilterfailure']
31
+ config :tag_on_multiresults, :validate => :array, :default => ['_mixpanelfiltermultiresults']
30
32
 
31
33
 
32
34
  public
@@ -40,7 +42,7 @@ class LogStash::Filters::Mixpanel < LogStash::Filters::Base
40
42
  public
41
43
  def filter(event)
42
44
 
43
- result = fetch_data
45
+ result = fetch_data event
44
46
  if !result.nil?
45
47
  event[@target] = result
46
48
 
@@ -55,12 +57,18 @@ class LogStash::Filters::Mixpanel < LogStash::Filters::Base
55
57
  end # def filter
56
58
 
57
59
  private
58
- def fetch_data
60
+ def fetch_data(event)
59
61
  options = {}
60
62
  options['where'] = prepare_where @where if @where
61
63
 
62
64
  response = @mp.request('engage', options)
63
- if response['results'].size >= 1
65
+ if response['results'].size == 1
66
+ single_res = response['results'][0]
67
+ elsif response['results'].size > 1
68
+ @tag_on_multiresults.each do |tag|
69
+ event['tags'] ||= []
70
+ event['tags'] << tag unless event['tags'].include?(tag)
71
+ end
64
72
  single_res = response['results'][0]
65
73
  else
66
74
  return nil
@@ -72,18 +80,22 @@ class LogStash::Filters::Mixpanel < LogStash::Filters::Base
72
80
  end
73
81
 
74
82
  private
75
- def prepare_where wheredata
83
+ def prepare_where(wheredata)
76
84
  special_properties = %w(email first_name last_name last_seen created)
77
85
  res_array = []
78
86
  wheredata.each { |constraint|
79
87
  constraint.each { |key, value|
80
88
  # prepend key with dollar sigh if key is in special_properties
81
- # TODO: add test for special properties without dollar sign
82
89
  key = "$#{key}" if special_properties.include? key
83
90
 
84
91
  res_array.push "properties[\"#{key}\"] == \"#{value}\""
85
92
  }
86
93
  }
87
- res_array.join ' and '
94
+ if @use_or
95
+ result = res_array.join ' or '
96
+ else
97
+ result = res_array.join ' and '
98
+ end
99
+ result
88
100
  end
89
- end # class LogStash::Filters::Example
101
+ end # class LogStash::Filters::Mixpanel
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-filter-mixpanel'
3
- s.version = '0.1.3'
3
+ s.version = '0.1.4'
4
4
  s.version = "#{s.version}.pre.#{ENV['TRAVIS_BUILD_NUMBER']}" if ENV['TRAVIS'] and ENV['TRAVIS_BRANCH'] != 'master'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "This filter checks mixpanel for additional people data and adds it to the event data"
@@ -1,5 +1,6 @@
1
1
  require File.absolute_path(File.join(File.dirname(__FILE__), '../../spec/spec_helper'))
2
2
  require File.absolute_path(File.join(File.dirname(__FILE__), '../../lib/logstash/filters/mixpanel'))
3
+ require 'rspec'
3
4
  require 'mixpanel_client'
4
5
  require 'mixpanel-ruby'
5
6
  require 'ffaker'
@@ -7,39 +8,6 @@ require 'base64'
7
8
 
8
9
 
9
10
  describe LogStash::Filters::Mixpanel do
10
- before(:all) do
11
- @mp = Mixpanel::Tracker.new(ENV['MP_PROJECT_TOKEN'])
12
-
13
- @user_1_id = FFaker::Guid.guid
14
- @user_1_ip = FFaker::Internet.ip_v4_address
15
- @user_1_email = FFaker::Internet.safe_email
16
- @user_1_first_name = FFaker::NameDE.first_name
17
- @user_1_last_name = FFaker::NameDE.last_name
18
- @user_1_data = {
19
- :$first_name => @user_1_first_name,
20
- :$last_name => @user_1_last_name,
21
- :$email => @user_1_email,
22
- 'Device ID' => @user_1_id
23
- }
24
- @mp.people.set(@user_1_id, @user_1_data, ip=@user_1_ip)
25
- @mp.track(@user_1_id, 'user 1 created')
26
-
27
- @user_2_id = FFaker::Guid.guid
28
- @user_2_ip = FFaker::Internet.ip_v4_address
29
- @user_2_email = FFaker::Internet.safe_email
30
- @user_2_first_name = @user_1_first_name
31
- @user_2_last_name = @user_1_last_name
32
- @user_2_data = {
33
- :$first_name => @user_2_first_name,
34
- :$last_name => @user_2_last_name,
35
- :$email => @user_2_email,
36
- 'Device ID' => @user_2_id
37
- }
38
- @mp.people.set(@user_2_id, @user_2_data, ip=@user_2_ip)
39
- @mp.track(@user_2_id, 'user 2 created')
40
-
41
-
42
- end
43
11
 
44
12
  context 'raise error' do
45
13
  context 'on wrong api key config' do
@@ -106,95 +74,244 @@ describe LogStash::Filters::Mixpanel do
106
74
 
107
75
  context 'fetch created user' do
108
76
  context 'by device id' do
77
+ before {
78
+ @id = FFaker::Guid.guid
79
+ @expected_result = {
80
+ 'page' => 0,
81
+ 'page_size' => 1000,
82
+ 'results' => [{ '$distinc_id' => 123124,
83
+ '$properties' => { '$created' => '2008-12-12T11:20:47',
84
+ '$email' => 'example@mixpanel.com',
85
+ '$first_name' => 'Example',
86
+ '$last_name' => 'Name',
87
+ 'Device ID' => @id,
88
+ '$last_seen' => '2008-06-09T23:08:40' }
89
+ }]
90
+ }
91
+ Mixpanel::Client.any_instance.stub(:request).and_return(@expected_result)
92
+ }
93
+
109
94
  let(:config) do <<-CONFIG
110
95
  filter {
111
96
  mixpanel {
112
97
  api_key => '#{ENV['MP_PROJECT_KEY']}'
113
98
  api_secret => '#{ENV['MP_PROJECT_SECRET']}'
114
- where => [{'Device ID' => '#{@user_1_id}'}]
99
+ where => [{'Device ID' => '#{@id}'}]
115
100
  }
116
101
  }
117
102
  CONFIG
118
103
  end
119
104
 
120
- sample("message" => "123") do
105
+ sample('message' => '123') do
121
106
  expect(subject).to include('mixpanel')
122
107
  expect(subject['mixpanel']).to include('Device ID')
123
108
  expect(subject['mixpanel']).to include('$distinct_id')
124
109
  expect(subject['mixpanel']).to include('$email')
125
110
  expect(subject['mixpanel']).to include('$last_name')
126
111
  expect(subject['mixpanel']).to include('Device ID')
112
+ expect(subject['mixpanel']['Device ID']).to eq(@id)
113
+ expect(subject['mixpanel']).to eq(@expected_result['results'][0]['$properties'])
127
114
  insist { subject['tags'] }.nil?
128
115
  end
129
116
  end
130
117
 
131
- context 'by email' do
132
- let(:config) do <<-CONFIG
133
- filter {
134
- mixpanel {
135
- api_key => '#{ENV['MP_PROJECT_KEY']}'
136
- api_secret => '#{ENV['MP_PROJECT_SECRET']}'
137
- where => [{'email' => '#{@user_1_email}'}]
118
+ # TODO: Create Unit test for "by email if it has no dollar char"
119
+ # context 'by email if it has no dollar char' do
120
+ # before {
121
+ # @id = FFaker::Guid.guid
122
+ # @expected_result = {
123
+ # 'page' => 0,
124
+ # 'page_size' => 1000,
125
+ # 'results' => [{ '$distinc_id' => 123124,
126
+ # '$properties' => { '$created' => '2008-12-12T11:20:47',
127
+ # '$email' => 'example@mixpanel.com',
128
+ # '$first_name' => 'Example',
129
+ # '$last_name' => 'Name',
130
+ # 'Device ID' => @id,
131
+ # '$last_seen' => '2008-06-09T23:08:40' }
132
+ # }]
133
+ # }
134
+ # Mixpanel::Client.any_instance.stub(:request).and_return(@expected_result)
135
+ # }
136
+ #
137
+ # let(:config) do <<-CONFIG
138
+ # filter {
139
+ # mixpanel {
140
+ # api_key => '#{ENV['MP_PROJECT_KEY']}'
141
+ # api_secret => '#{ENV['MP_PROJECT_SECRET']}'
142
+ # where => [{'email' => '#{@id}'}]
143
+ # }
144
+ # }
145
+ # CONFIG
146
+ # end
147
+ #
148
+ # sample('message' => '123') do
149
+ # expect(subject).to include("mixpanel")
150
+ # expect(subject['mixpanel']).to include('Device ID')
151
+ # expect(subject['mixpanel']).to include('$distinct_id')
152
+ # expect(subject['mixpanel']).to include('$email')
153
+ # expect(subject['mixpanel']).to include('$last_name')
154
+ # expect(subject['mixpanel']).to include('Device ID')
155
+ # insist { subject['tags'] }.nil?
156
+ # end
157
+ # end
158
+ #
159
+ # TODO: Create Unit test for "by email if it has dollar char"
160
+ # context 'by email if it has dollar char' do
161
+ # let(:config) do <<-CONFIG
162
+ # filter {
163
+ # mixpanel {
164
+ # api_key => '#{ENV['MP_PROJECT_KEY']}'
165
+ # api_secret => '#{ENV['MP_PROJECT_SECRET']}'
166
+ # where => [{'$email' => '#{@user_1_email}'}]
167
+ # }
168
+ # }
169
+ # CONFIG
170
+ # end
171
+ #
172
+ # sample('message' => '123') do
173
+ # expect(subject).to include("mixpanel")
174
+ # expect(subject['mixpanel']).to include('Device ID')
175
+ # expect(subject['mixpanel']).to include('$distinct_id')
176
+ # expect(subject['mixpanel']).to include('$email')
177
+ # expect(subject['mixpanel']).to include('$last_name')
178
+ # expect(subject['mixpanel']).to include('Device ID')
179
+ # insist { subject['tags'] }.nil?
180
+ # end
181
+ # end
182
+ end
183
+
184
+ context 'test on multiple returns' do
185
+ context 'with and constraint' do
186
+ before {
187
+ @first_name = FFaker::NameDE.first_name
188
+ @expected_result = {
189
+ 'page' => 0,
190
+ 'page_size' => 1000,
191
+ 'results' => [{ '$distinc_id' => 123124,
192
+ '$properties' => { '$created' => '2008-12-12T11:20:47',
193
+ '$email' => 'example1@mixpanel.com',
194
+ '$first_name' => @first_name,
195
+ '$last_name' => 'Name1',
196
+ 'Device ID' => '123',
197
+ '$last_seen' => '2008-06-09T23:08:40' }
198
+ }, { '$distinc_id' => 1231244,
199
+ '$properties' => { '$created' => '2008-12-12T11:20:47',
200
+ '$email' => 'example2@mixpanel.com',
201
+ '$first_name' => @first_name,
202
+ '$last_name' => 'Name2',
203
+ 'Device ID' => '1234',
204
+ '$last_seen' => '2008-06-09T23:08:40' }
205
+ }]
138
206
  }
207
+ Mixpanel::Client.any_instance.stub(:request).and_return(@expected_result)
139
208
  }
140
- CONFIG
209
+
210
+ let(:config) do <<-CONFIG
211
+ filter {
212
+ mixpanel {
213
+ api_key => '#{ENV['MP_PROJECT_KEY']}'
214
+ api_secret => '#{ENV['MP_PROJECT_SECRET']}'
215
+ where => [{'first_name' => '#{@first_name}'}]
216
+ }
217
+ }
218
+ CONFIG
141
219
  end
142
220
 
143
- sample("message" => "123") do
144
- expect(subject).to include('mixpanel')
221
+ sample('message' => '123') do
222
+ expect(subject).to include("mixpanel")
145
223
  expect(subject['mixpanel']).to include('Device ID')
146
224
  expect(subject['mixpanel']).to include('$distinct_id')
147
225
  expect(subject['mixpanel']).to include('$email')
226
+ expect(subject['mixpanel']).to include('$first_name')
148
227
  expect(subject['mixpanel']).to include('$last_name')
149
228
  expect(subject['mixpanel']).to include('Device ID')
150
- insist { subject['tags'] }.nil?
229
+ expect(subject).to include('tags')
230
+
231
+ expect(subject['tags']).to include('_mixpanelfiltermultiresults')
232
+ expect(subject['mixpanel']).to eq(@expected_result['results'][0]['$properties'])
233
+ # expect(subject['mixpanel']['$first_name']).to eq(@first_name)
234
+ # expect(subject['mixpanel']['$last_name']).to eq('Name1')
151
235
  end
152
236
  end
153
- end
154
237
 
155
- context 'test on multiple returns' do
156
- let(:config) do <<-CONFIG
157
- filter {
158
- mixpanel {
159
- api_key => '#{ENV['MP_PROJECT_KEY']}'
160
- api_secret => '#{ENV['MP_PROJECT_SECRET']}'
161
- where => [{'first_name' => '#{@user_1_first_name}'}]
238
+ context 'with or constraint' do
239
+ before {
240
+ @email1 = FFaker::Internet.safe_email
241
+ @email2 = FFaker::Internet.safe_email
242
+ @expected_result = {
243
+ 'page' => 0,
244
+ 'page_size' => 1000,
245
+ 'results' => [{ '$distinc_id' => 123124,
246
+ '$properties' => { '$created' => '2008-12-12T11:20:47',
247
+ '$email' => 'example1@mixpanel.com',
248
+ '$first_name' => 'Firstname1',
249
+ '$last_name' => 'Name1',
250
+ 'Device ID' => '123',
251
+ '$last_seen' => '2008-06-09T23:08:40' }
252
+ }, { '$distinc_id' => 1231244,
253
+ '$properties' => { '$created' => '2008-12-12T11:20:47',
254
+ '$email' => 'example1@mixpanel.com',
255
+ '$first_name' => 'Firstname2',
256
+ '$last_name' => 'Name2',
257
+ 'Device ID' => '1234',
258
+ '$last_seen' => '2008-06-09T23:08:40' }
259
+ }]
162
260
  }
261
+ Mixpanel::Client.any_instance.stub(:request).and_return(@expected_result)
163
262
  }
164
- CONFIG
165
- end
166
263
 
167
- sample("message" => "123") do
168
- expect(subject).to include('mixpanel')
169
- expect(subject['mixpanel']).to include('Device ID')
170
- expect(subject['mixpanel']).to include('$distinct_id')
171
- expect(subject['mixpanel']).to include('$email')
172
- expect(subject['mixpanel']).to include('$last_name')
173
- expect(subject['mixpanel']).to include('Device ID')
174
- insist { subject['tags'] }.nil?
264
+ let(:config) do <<-CONFIG
265
+ filter {
266
+ mixpanel {
267
+ api_key => '#{ENV['MP_PROJECT_KEY']}'
268
+ api_secret => '#{ENV['MP_PROJECT_SECRET']}'
269
+ where => [{'email' => '#{@email1}'}, {'email' => '#{@email2}'}]
270
+ use_or => true
271
+ }
272
+ }
273
+ CONFIG
274
+ end
275
+
276
+ sample('message' => '123') do
277
+ expect(subject).to include('mixpanel')
278
+ expect(subject['mixpanel']).to include('Device ID')
279
+ expect(subject['mixpanel']).to include('$distinct_id')
280
+ expect(subject['mixpanel']).to include('$email')
281
+ expect(subject['mixpanel']).to include('$last_name')
282
+ expect(subject['mixpanel']).to include('Device ID')
283
+
284
+ expect(subject).to include('tags')
285
+ expect(subject['tags']).to include('_mixpanelfiltermultiresults')
286
+ expect(subject['mixpanel']).to eq(@expected_result['results'][0]['$properties'])
287
+ end
175
288
  end
176
289
  end
177
290
 
178
291
  context 'test on no returns' do
292
+ before {
293
+ @expected_result = {
294
+ 'page' => 0,
295
+ 'page_size' => 1000,
296
+ 'results' => []
297
+ }
298
+ Mixpanel::Client.any_instance.stub(:request).and_return(@expected_result)
299
+ }
300
+
179
301
  let(:config) do <<-CONFIG
180
302
  filter {
181
303
  mixpanel {
182
304
  api_key => '#{ENV['MP_PROJECT_KEY']}'
183
305
  api_secret => '#{ENV['MP_PROJECT_SECRET']}'
184
- where => [{'first_name' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}]
306
+ where => [{'$first_name' => 'thisfirstnameshouldneverbeseen123'}]
185
307
  }
186
308
  }
187
309
  CONFIG
188
310
  end
189
311
 
190
- sample("message" => "123") do
191
- insist { subject["tags"] }.include?('_mixpanelfilterfailure')
312
+ sample('message' => '123') do
313
+ insist { subject['tags'] }.include?('_mixpanelfilterfailure')
192
314
  reject { subject }.include?('mixpanel')
193
315
  end
194
316
  end
195
-
196
- after(:all) do
197
- @mp.people.delete_user(@user_1_id)
198
- @mp.people.delete_user(@user_2_id)
199
- end
200
317
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-mixpanel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Torsten Feld