fluent-plugin-mixpanel 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1f52ca8a3eeb5cf55c6edafa375a7ef3baa85129
4
- data.tar.gz: f1ec985b547288ee38f281513e5c6b8945a7da60
3
+ metadata.gz: 96a9b1fba6cc39288c0391efc0816839dcc081e7
4
+ data.tar.gz: ffeddf702547a2d981517dcc364af2c31cf89f70
5
5
  SHA512:
6
- metadata.gz: f5bc26f5e50925291e9b46163d2b5c8e838221982441c65eea3f366820a3e199817679e2569c7dfb8f51e961d7543c0859269181f0d924ccd05dbc27511f48a4
7
- data.tar.gz: 52e60e00116aa0668fc56c6a3dfe3971cd964e358800c5881acf1cc817cfe972158f60bf668350324f3375a299377410422c2b75674fc50f4ff8391db1b5f060
6
+ metadata.gz: 77255b4cb64f0dda7774fa891f2a52a5bffb465a4f95cb3c79b18c0449d19e49026871fde9ba41d2a8ca4434e39be362bb48628932483782ed501828237cd5df
7
+ data.tar.gz: e618c0d33e8de6e44dae7503c339f344bc516883941045fe89e0af92e9a975493876578235b30ea4a29b3f02ff367af2aa0662f7dcd6b1f48d7765dfcfc15fe7
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea/
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.0.0
4
- - 2.1.0
5
- - 2.2.0
3
+ - 2.1.9
4
+ - 2.2.5
5
+ - 2.3.1
data/README.md CHANGED
@@ -62,6 +62,18 @@ tracker.track("123", "event1", { key1: "value1", key2: "value2" })
62
62
 
63
63
  You can use tag name as event name like this. (see additional tag manipulations options below)
64
64
 
65
+ #### Discarding mixpanel errors
66
+
67
+ When delivering events to Mixpanel, Fluent creates a chunk of messages to send. By default, if one event fails to send to Mixpanel, all messages in that chunk are requeued for delivery. Enabling `discard_event_on_send_error` allows you to ignore single delivery failures. The event is logged via `info`, including the record being dropped.
68
+
69
+ ```
70
+ <match output.mixpanel.*>
71
+ ...
72
+ discard_event_on_send_error true
73
+ ...
74
+ </match>
75
+ ```
76
+
65
77
  ##PLEASE NOTE (breaking api change in a future release)
66
78
 
67
79
  The api for remove_tag_prefix will be changing in a future release. There is currently a boolean option,
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fluent-plugin-mixpanel"
7
- spec.version = "0.0.8"
7
+ spec.version = "0.0.9"
8
8
  spec.authors = ["Kazuyuki Honda"]
9
9
  spec.email = ["hakobera@gmail.com"]
10
10
  spec.summary = %q{Fluentd plugin to input/output event track data to mixpanel}
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_runtime_dependency "fluentd", ">= 0.10.55"
21
- spec.add_runtime_dependency "mixpanel-ruby", "~> 2.1.0"
21
+ spec.add_runtime_dependency "mixpanel-ruby", "~> 2.2.0"
22
22
 
23
23
  spec.add_development_dependency "rake"
24
24
  spec.add_development_dependency "webmock"
@@ -0,0 +1,15 @@
1
+ require 'mixpanel-ruby'
2
+
3
+ class Fluent::MixpanelOutputErrorHandler < Mixpanel::ErrorHandler
4
+ def initialize(logger)
5
+ @logger = logger
6
+ end
7
+
8
+ def handle(error)
9
+ # Default behavior is to not return an error. Mixpanel-ruby gem returns
10
+ # true/false. If there is an error, an optional error handler is called.
11
+ # In this case, here, we only want to log the error for future development
12
+ # of error handling.
13
+ @logger.error "MixpanelOutputErrorHandler:\n\tClass: #{error.class.to_s}\n\tMessage: #{error.message}\n\tBacktrace: #{error.backtrace}"
14
+ end
15
+ end
@@ -1,11 +1,12 @@
1
+ require_relative "mixpanel_ruby_error_handler.rb"
1
2
 
2
3
  class Fluent::MixpanelOutput < Fluent::BufferedOutput
3
4
  Fluent::Plugin.register_output('mixpanel', self)
4
5
 
5
6
  include Fluent::HandleTagNameMixin
6
7
 
7
- config_param :project_token, :string
8
- config_param :api_key, :string, :default => ''
8
+ config_param :project_token, :string, :secret => true
9
+ config_param :api_key, :string, :default => '', :secret => true
9
10
  config_param :use_import, :bool, :default => nil
10
11
  config_param :distinct_id_key, :string
11
12
  config_param :event_key, :string, :default => nil
@@ -13,6 +14,7 @@ class Fluent::MixpanelOutput < Fluent::BufferedOutput
13
14
  config_param :event_map_tag, :bool, :default => false
14
15
  #NOTE: This will be removed in a future release. Please specify the '.' on any prefix
15
16
  config_param :use_legacy_prefix_behavior, :default => true
17
+ config_param :discard_event_on_send_error, :default => false
16
18
 
17
19
  class MixpanelError < StandardError
18
20
  end
@@ -32,6 +34,7 @@ class Fluent::MixpanelOutput < Fluent::BufferedOutput
32
34
  @api_key = conf['api_key']
33
35
  @use_import = conf['use_import']
34
36
  @use_legacy_prefix_behavior = conf['use_legacy_prefix_behavior']
37
+ @discard_event_on_send_error = conf['discard_event_on_send_error']
35
38
 
36
39
  if @event_key.nil? and !@event_map_tag
37
40
  raise Fluent::ConfigError, "'event_key' must be specifed when event_map_tag == false."
@@ -40,7 +43,8 @@ class Fluent::MixpanelOutput < Fluent::BufferedOutput
40
43
 
41
44
  def start
42
45
  super
43
- @tracker = Mixpanel::Tracker.new(@project_token)
46
+ error_handler = Fluent::MixpanelOutputErrorHandler.new(log)
47
+ @tracker = Mixpanel::Tracker.new(@project_token, error_handler)
44
48
  end
45
49
 
46
50
  def shutdown
@@ -68,19 +72,19 @@ class Fluent::MixpanelOutput < Fluent::BufferedOutput
68
72
  data['event'] = record[@event_key]
69
73
  prop.delete(@event_key)
70
74
  else
71
- log.warn('no event')
72
- return
75
+ log.warn("no event, tag: #{tag}, time: #{time.to_s}, record: #{record.to_json}")
76
+ next
73
77
  end
74
78
 
75
79
  # Ignore browswer only special event
76
- return if data['event'].start_with?('mp_')
80
+ next if data['event'].start_with?('mp_')
77
81
 
78
82
  if record[@distinct_id_key]
79
83
  data['distinct_id'] = record[@distinct_id_key]
80
84
  prop.delete(@distinct_id_key)
81
85
  else
82
- log.warn('no distinct_id')
83
- return
86
+ log.warn("no distinct_id, tag: #{tag}, time: #{time.to_s}, record: #{record.to_json}")
87
+ next
84
88
  end
85
89
 
86
90
  if !@ip_key.nil? and record[@ip_key]
@@ -98,13 +102,26 @@ class Fluent::MixpanelOutput < Fluent::BufferedOutput
98
102
  end
99
103
 
100
104
  def send_to_mixpanel(records)
105
+ log.debug("sending #{records.length} to mixpanel")
106
+
101
107
  records.each do |record|
102
- success = if @use_import
103
- @tracker.import(@api_key, record['distinct_id'], record['event'], record['properties'])
104
- else
105
- @tracker.track(record['distinct_id'], record['event'], record['properties'])
106
- end
107
- raise MixpanelError.new("Failed to track event to mixpanel") unless success
108
+ success = true
109
+
110
+ if @use_import
111
+ success = @tracker.import(@api_key, record['distinct_id'], record['event'], record['properties'])
112
+ else
113
+ success = @tracker.track(record['distinct_id'], record['event'], record['properties'])
114
+ end
115
+
116
+ unless success
117
+ if @discard_event_on_send_error
118
+ msg = "Failed to track event to mixpanel:\n"
119
+ msg += "\tRecord: #{record.to_json}"
120
+ log.info(msg)
121
+ else
122
+ raise MixpanelError.new("Failed to track event to mixpanel")
123
+ end
124
+ end
108
125
  end
109
126
  end
110
127
  end
data/test/helper.rb CHANGED
@@ -31,6 +31,7 @@ def unused_port
31
31
  port
32
32
  end
33
33
 
34
+ require 'fluent/plugin/mixpanel_ruby_error_handler'
34
35
  require 'fluent/plugin/out_mixpanel'
35
36
  require 'fluent/plugin/in_http_mixpanel'
36
37
 
@@ -1,9 +1,23 @@
1
1
  require 'helper'
2
2
  require 'net/http'
3
3
  require 'base64'
4
+ require 'fluent/test'
5
+ require 'net/http'
4
6
 
5
7
  class HttpMixpanelInputTest < Test::Unit::TestCase
6
-
8
+
9
+ class << self
10
+ def startup
11
+ socket_manager_path = ServerEngine::SocketManager::Server.generate_path
12
+ @server = ServerEngine::SocketManager::Server.open(socket_manager_path)
13
+ ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
14
+ end
15
+
16
+ def shutdown
17
+ @server.close
18
+ end
19
+ end
20
+
7
21
  def setup
8
22
  Fluent::Test.setup
9
23
  end
@@ -11,13 +25,14 @@ class HttpMixpanelInputTest < Test::Unit::TestCase
11
25
  PORT = unused_port
12
26
  CONFIG = %[
13
27
  port #{PORT}
14
- bind 127.0.0.1
28
+ bind "127.0.0.1"
15
29
  body_size_limit 10m
16
30
  keepalive_timeout 5
31
+ respond_with_empty_img true
17
32
  ]
18
33
 
19
34
  def create_driver(conf=CONFIG)
20
- Fluent::Test::InputTestDriver.new(Fluent::HttpMixpanelInput).configure(conf)
35
+ Fluent::Test::InputTestDriver.new(Fluent::HttpMixpanelInput).configure(conf, true)
21
36
  end
22
37
 
23
38
  def test_configure
@@ -26,7 +41,7 @@ class HttpMixpanelInputTest < Test::Unit::TestCase
26
41
  assert_equal '127.0.0.1', d.instance.bind
27
42
  assert_equal 10*1024*1024, d.instance.body_size_limit
28
43
  assert_equal 5, d.instance.keepalive_timeout
29
- assert_equal false, d.instance.add_http_headers
44
+ assert_equal false, d.instance.add_http_headers
30
45
  end
31
46
 
32
47
  def test_time
@@ -39,16 +54,16 @@ class HttpMixpanelInputTest < Test::Unit::TestCase
39
54
  d.expect_emit "mixpanel.tag2", time, {"a"=>2}
40
55
 
41
56
  d.run do
42
- d.expected_emits.each {|tag,time,record|
57
+ d.expected_emits.each {|tag, record_time, record|
43
58
  res = track("#{tag}", {"json"=>record})
44
59
  assert_equal "200", res.code
45
60
  assert_equal '1', res.body
46
- assert_equal 'true', res.header['access-control-allow-credentials']
47
- assert_equal 'X-Requested-With', res.header['access-control-allow-headers']
48
- assert_equal 'GET, POST, OPTIONS', res.header['access-control-allow-methods']
49
- assert_equal 'http://foo.example', res.header['access-control-allow-origin']
50
- assert_equal '1728000', res.header['access-control-max-age']
51
- assert_equal 'no-cache, no-store', res.header['cache-control']
61
+ assert_equal 'true', res['access-control-allow-credentials']
62
+ assert_equal 'X-Requested-With', res['access-control-allow-headers']
63
+ assert_equal 'GET, POST, OPTIONS', res['access-control-allow-methods']
64
+ assert_equal 'http://foo.example', res['access-control-allow-origin']
65
+ assert_equal '1728000', res['access-control-max-age']
66
+ assert_equal 'no-cache, no-store', res['cache-control']
52
67
  }
53
68
  end
54
69
  end
@@ -62,8 +77,8 @@ class HttpMixpanelInputTest < Test::Unit::TestCase
62
77
  d.expect_emit "mixpanel.tag2", time, {"a"=>2}
63
78
 
64
79
  d.run do
65
- d.expected_emits.each {|tag,time,record|
66
- res = track("#{tag}", {"json"=>record, "time"=>time.to_s})
80
+ d.expected_emits.each {|tag, record_time, record|
81
+ res = track("#{tag}", {"json"=>record, "time"=>record_time.to_s})
67
82
  assert_equal "200", res.code
68
83
  }
69
84
  end
@@ -81,8 +96,8 @@ class HttpMixpanelInputTest < Test::Unit::TestCase
81
96
  records = [["mixpanel.tag1", time, {"a"=>1}], ["mixpanel.tag2", time, {"a"=>2}]]
82
97
 
83
98
  d.run do
84
- records.each {|tag,time,record|
85
- res = track("#{tag}", {"json"=>record, "time"=>time.to_s})
99
+ records.each {|tag, record_time, record|
100
+ res = track("#{tag}", {"json"=>record, "time"=>record_time.to_s})
86
101
  assert_equal "200", res.code
87
102
  }
88
103
  end
@@ -99,7 +114,7 @@ class HttpMixpanelInputTest < Test::Unit::TestCase
99
114
  event: event,
100
115
  properties: params['json']
101
116
  }
102
- data = URI.escape(Base64.encode64(data.to_json))
117
+ data = CGI.escape(Base64.encode64(data.to_json))
103
118
  query = "data=#{data}"
104
119
  path = "/track/?#{query}"
105
120
 
@@ -0,0 +1,16 @@
1
+ require 'helper'
2
+
3
+ class MixpanelRubyErrorHandlerTest < Test::Unit::TestCase
4
+
5
+ def test_handle
6
+ mixpanel_error = Fluent::MixpanelOutput::MixpanelError.new("Foobar failed")
7
+ @io = StringIO.new
8
+ logger = Logger.new(@io)
9
+ error = Fluent::MixpanelOutputErrorHandler.new(logger)
10
+ error.handle(mixpanel_error)
11
+
12
+ output = @io.string
13
+ expected_output = "MixpanelOutputErrorHandler:\n\tClass: Fluent::MixpanelOutput::MixpanelError\n\tMessage: Foobar failed\n\tBacktrace: \n"
14
+ assert_match expected_output, output
15
+ end
16
+ end
@@ -1,5 +1,6 @@
1
1
  require 'helper'
2
2
  require 'uri'
3
+ require 'msgpack'
3
4
 
4
5
  class MixpanelOutputTest < Test::Unit::TestCase
5
6
 
@@ -70,14 +71,14 @@ class MixpanelOutputTest < Test::Unit::TestCase
70
71
  def test_write
71
72
  stub_mixpanel
72
73
  d = create_driver(CONFIG + "event_key event")
73
- time = Time.new('2014-01-01T01:23:45+00:00')
74
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
74
75
  d.emit(sample_record, time)
75
76
  d.run
76
77
 
77
78
  assert_equal "test_token", @out[0]['properties']['token']
78
79
  assert_equal "123", @out[0]['properties']['distinct_id']
79
80
  assert_equal "event1", @out[0]['event']
80
- assert_equal time.to_i, @out[0]['properties']['time']
81
+ assert_equal time, @out[0]['properties']['time']
81
82
  assert_equal "value1", @out[0]['properties']['key1']
82
83
  assert_equal "value2", @out[0]['properties']['key2']
83
84
  end
@@ -85,7 +86,7 @@ class MixpanelOutputTest < Test::Unit::TestCase
85
86
  def test_write_setting_time_via_export
86
87
  stub_mixpanel_import
87
88
  d = create_driver(CONFIG + "use_import true\nevent_key event")
88
- time = Time.new('2014-01-01T01:23:45+00:00')
89
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
89
90
  d.emit(sample_record.merge!('time' => 1435707767), time)
90
91
  d.run
91
92
 
@@ -100,8 +101,8 @@ class MixpanelOutputTest < Test::Unit::TestCase
100
101
  def test_write_multi_request
101
102
  stub_mixpanel_import
102
103
  d = create_driver(IMPORT_CONFIG + "event_key event")
103
- time1 = Time.new('2014-01-01T01:23:45+00:00')
104
- time2 = Time.new('2014-01-02T01:23:45+00:00')
104
+ time1 = Time.new('2014-01-01T01:23:45+00:00').to_i
105
+ time2 = Time.new('2014-01-02T01:23:45+00:00').to_i
105
106
 
106
107
  d.emit(sample_record, time1)
107
108
  d.emit(sample_record.merge(key3: "value3"), time2)
@@ -109,13 +110,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
109
110
 
110
111
  assert_equal "123", @out[0]['properties']['distinct_id']
111
112
  assert_equal "event1", @out[0]['event']
112
- assert_equal time1.to_i, @out[0]['properties']['time']
113
+ assert_equal time1, @out[0]['properties']['time']
113
114
  assert_equal "value1", @out[0]['properties']['key1']
114
115
  assert_equal "value2", @out[0]['properties']['key2']
115
116
 
116
117
  assert_equal "123", @out[1]['properties']['distinct_id']
117
118
  assert_equal "event1", @out[1]['event']
118
- assert_equal time2.to_i, @out[1]['properties']['time']
119
+ assert_equal time2, @out[1]['properties']['time']
119
120
  assert_equal "value1", @out[1]['properties']['key1']
120
121
  assert_equal "value2", @out[1]['properties']['key2']
121
122
  assert_equal "value2", @out[1]['properties']['key2']
@@ -124,13 +125,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
124
125
  def test_write_with_ip_key
125
126
  stub_mixpanel
126
127
  d = create_driver(CONFIG + "event_key event\n ip_key ip_address")
127
- time = Time.new('2014-01-01T01:23:45+00:00')
128
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
128
129
  d.emit(sample_record.merge('ip_address' => '192.168.0.2'), time)
129
130
  d.run
130
131
 
131
132
  assert_equal "123", @out[0]['properties']['distinct_id']
132
133
  assert_equal "event1", @out[0]['event']
133
- assert_equal time.to_i, @out[0]['properties']['time']
134
+ assert_equal time, @out[0]['properties']['time']
134
135
  assert_equal "192.168.0.2", @out[0]['properties']['ip']
135
136
  assert_equal "value1", @out[0]['properties']['key1']
136
137
  assert_equal "value2", @out[0]['properties']['key2']
@@ -139,13 +140,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
139
140
  def test_write_with_no_tag_manipulation
140
141
  stub_mixpanel
141
142
  d = create_driver(CONFIG + "event_map_tag true")
142
- time = Time.new('2014-01-01T01:23:45+00:00')
143
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
143
144
  d.emit(sample_record, time)
144
145
  d.run
145
146
 
146
147
  assert_equal "123", @out[0]['properties']['distinct_id']
147
148
  assert_equal "mixpanel.test", @out[0]['event']
148
- assert_equal time.to_i, @out[0]['properties']['time']
149
+ assert_equal time, @out[0]['properties']['time']
149
150
  assert_equal "value1", @out[0]['properties']['key1']
150
151
  assert_equal "value2", @out[0]['properties']['key2']
151
152
  end
@@ -153,13 +154,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
153
154
  def test_write_with_event_map_tag_removing_prefix
154
155
  stub_mixpanel
155
156
  d = create_driver(CONFIG + "remove_tag_prefix mixpanel.\n event_map_tag true")
156
- time = Time.new('2014-01-01T01:23:45+00:00')
157
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
157
158
  d.emit(sample_record, time)
158
159
  d.run
159
160
 
160
161
  assert_equal "123", @out[0]['properties']['distinct_id']
161
162
  assert_equal "test", @out[0]['event']
162
- assert_equal time.to_i, @out[0]['properties']['time']
163
+ assert_equal time, @out[0]['properties']['time']
163
164
  assert_equal "value1", @out[0]['properties']['key1']
164
165
  assert_equal "value2", @out[0]['properties']['key2']
165
166
  end
@@ -167,13 +168,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
167
168
  def test_write_with_event_map_tag_removing_prefix_LEGACY
168
169
  stub_mixpanel
169
170
  d = create_driver(CONFIG + "remove_tag_prefix mixpanel\n event_map_tag true\n use_legacy_prefix_behavior true")
170
- time = Time.new('2014-01-01T01:23:45+00:00')
171
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
171
172
  d.emit(sample_record, time)
172
173
  d.run
173
174
 
174
175
  assert_equal "123", @out[0]['properties']['distinct_id']
175
176
  assert_equal "test", @out[0]['event']
176
- assert_equal time.to_i, @out[0]['properties']['time']
177
+ assert_equal time, @out[0]['properties']['time']
177
178
  assert_equal "value1", @out[0]['properties']['key1']
178
179
  assert_equal "value2", @out[0]['properties']['key2']
179
180
  end
@@ -181,13 +182,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
181
182
  def test_write_with_event_map_tag_removing_prefix_LEGACY_with_dot
182
183
  stub_mixpanel
183
184
  d = create_driver(CONFIG + "remove_tag_prefix mixpanel.\n event_map_tag true\n use_legacy_prefix_behavior true")
184
- time = Time.new('2014-01-01T01:23:45+00:00')
185
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
185
186
  d.emit(sample_record, time)
186
187
  d.run
187
188
 
188
189
  assert_equal "123", @out[0]['properties']['distinct_id']
189
190
  assert_equal "test", @out[0]['event']
190
- assert_equal time.to_i, @out[0]['properties']['time']
191
+ assert_equal time, @out[0]['properties']['time']
191
192
  assert_equal "value1", @out[0]['properties']['key1']
192
193
  assert_equal "value2", @out[0]['properties']['key2']
193
194
  end
@@ -195,13 +196,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
195
196
  def test_write_with_event_map_tag_removing_suffix
196
197
  stub_mixpanel
197
198
  d = create_driver(CONFIG + "remove_tag_suffix .test\n event_map_tag true")
198
- time = Time.new('2014-01-01T01:23:45+00:00')
199
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
199
200
  d.emit(sample_record, time)
200
201
  d.run
201
202
 
202
203
  assert_equal "123", @out[0]['properties']['distinct_id']
203
204
  assert_equal "mixpanel", @out[0]['event']
204
- assert_equal time.to_i, @out[0]['properties']['time']
205
+ assert_equal time, @out[0]['properties']['time']
205
206
  assert_equal "value1", @out[0]['properties']['key1']
206
207
  assert_equal "value2", @out[0]['properties']['key2']
207
208
  end
@@ -209,13 +210,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
209
210
  def test_write_with_event_map_tag_adding_prefix
210
211
  stub_mixpanel
211
212
  d = create_driver(CONFIG + "add_tag_prefix foo.\n event_map_tag true")
212
- time = Time.new('2014-01-01T01:23:45+00:00')
213
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
213
214
  d.emit(sample_record, time)
214
215
  d.run
215
216
 
216
217
  assert_equal "123", @out[0]['properties']['distinct_id']
217
218
  assert_equal "foo.mixpanel.test", @out[0]['event']
218
- assert_equal time.to_i, @out[0]['properties']['time']
219
+ assert_equal time, @out[0]['properties']['time']
219
220
  assert_equal "value1", @out[0]['properties']['key1']
220
221
  assert_equal "value2", @out[0]['properties']['key2']
221
222
  end
@@ -223,13 +224,13 @@ class MixpanelOutputTest < Test::Unit::TestCase
223
224
  def test_write_with_event_map_tag_adding_suffix
224
225
  stub_mixpanel
225
226
  d = create_driver(CONFIG + "add_tag_suffix .foo\n event_map_tag true")
226
- time = Time.new('2014-01-01T01:23:45+00:00')
227
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
227
228
  d.emit(sample_record, time)
228
229
  d.run
229
230
 
230
231
  assert_equal "123", @out[0]['properties']['distinct_id']
231
232
  assert_equal "mixpanel.test.foo", @out[0]['event']
232
- assert_equal time.to_i, @out[0]['properties']['time']
233
+ assert_equal time, @out[0]['properties']['time']
233
234
  assert_equal "value1", @out[0]['properties']['key1']
234
235
  assert_equal "value2", @out[0]['properties']['key2']
235
236
  end
@@ -237,7 +238,7 @@ class MixpanelOutputTest < Test::Unit::TestCase
237
238
  def test_write_ignore_special_event
238
239
  stub_mixpanel
239
240
  d = create_driver(CONFIG + "event_key event")
240
- time = Time.new('2014-01-01T01:23:45+00:00')
241
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
241
242
  d.emit({ user_id: '123', event: 'mp_page_view' }, time)
242
243
  d.run
243
244
 
@@ -247,14 +248,14 @@ class MixpanelOutputTest < Test::Unit::TestCase
247
248
  def test_write_ignore_special_property
248
249
  stub_mixpanel
249
250
  d = create_driver(CONFIG + "event_key event")
250
- time = Time.new('2014-01-01T01:23:45+00:00')
251
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
251
252
  d.emit(sample_record.merge('mp_event' => '3'), time)
252
253
  d.run
253
254
 
254
255
  assert_equal "test_token", @out[0]['properties']['token']
255
256
  assert_equal "123", @out[0]['properties']['distinct_id']
256
257
  assert_equal "event1", @out[0]['event']
257
- assert_equal time.to_i, @out[0]['properties']['time']
258
+ assert_equal time, @out[0]['properties']['time']
258
259
  assert_equal "value1", @out[0]['properties']['key1']
259
260
  assert_equal "value2", @out[0]['properties']['key2']
260
261
  assert_equal false, @out[0]['properties'].key?('mp_event')
@@ -263,14 +264,14 @@ class MixpanelOutputTest < Test::Unit::TestCase
263
264
  def test_write_delete_supried_token
264
265
  stub_mixpanel
265
266
  d = create_driver(CONFIG + "event_key event")
266
- time = Time.new('2014-01-01T01:23:45+00:00')
267
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
267
268
  d.emit(sample_record.merge('token' => '123'), time)
268
269
  d.run
269
270
 
270
271
  assert_equal "test_token", @out[0]['properties']['token']
271
272
  assert_equal "123", @out[0]['properties']['distinct_id']
272
273
  assert_equal "event1", @out[0]['event']
273
- assert_equal time.to_i, @out[0]['properties']['time']
274
+ assert_equal time, @out[0]['properties']['time']
274
275
  assert_equal "value1", @out[0]['properties']['key1']
275
276
  assert_equal "value2", @out[0]['properties']['key2']
276
277
  assert_equal false, @out[0]['properties'].key?('mp_event')
@@ -284,4 +285,87 @@ class MixpanelOutputTest < Test::Unit::TestCase
284
285
  d.run
285
286
  }
286
287
  end
288
+
289
+ def test_multiple_records_1_missing_event
290
+ stub_mixpanel
291
+ d = create_driver(CONFIG + "event_key event")
292
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
293
+ d.emit(sample_record, time)
294
+
295
+ broken_record = sample_record.dup.delete(:event)
296
+ d.emit(broken_record, time)
297
+
298
+ d.run
299
+
300
+ assert_equal 1, @out.length
301
+
302
+ assert_equal "test_token", @out[0]['properties']['token']
303
+ assert_equal "123", @out[0]['properties']['distinct_id']
304
+ assert_equal "event1", @out[0]['event']
305
+ assert_equal time, @out[0]['properties']['time']
306
+ assert_equal "value1", @out[0]['properties']['key1']
307
+ assert_equal "value2", @out[0]['properties']['key2']
308
+
309
+ end
310
+
311
+ def test_multiple_records_1_missing_distinct_id
312
+ stub_mixpanel
313
+ d = create_driver(CONFIG + "event_key event")
314
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
315
+ d.emit(sample_record, time)
316
+
317
+ broken_record = sample_record.dup.delete(:user_id)
318
+ d.emit(broken_record, time)
319
+
320
+ d.run
321
+
322
+ assert_equal 1, @out.length
323
+
324
+ assert_equal "test_token", @out[0]['properties']['token']
325
+ assert_equal "123", @out[0]['properties']['distinct_id']
326
+ assert_equal "event1", @out[0]['event']
327
+ assert_equal time, @out[0]['properties']['time']
328
+ assert_equal "value1", @out[0]['properties']['key1']
329
+ assert_equal "value2", @out[0]['properties']['key2']
330
+
331
+ end
332
+
333
+ def test_multiple_records_1_having_mp
334
+ stub_mixpanel
335
+ d = create_driver(CONFIG + "event_key event")
336
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
337
+ d.emit(sample_record, time)
338
+
339
+ broken_record = sample_record.dup.merge({ event: 'mp_foo'})
340
+ d.emit(broken_record, time)
341
+
342
+ d.run
343
+
344
+ assert_equal 1, @out.length
345
+
346
+ assert_equal "test_token", @out[0]['properties']['token']
347
+ assert_equal "123", @out[0]['properties']['distinct_id']
348
+ assert_equal "event1", @out[0]['event']
349
+ assert_equal time, @out[0]['properties']['time']
350
+ assert_equal "value1", @out[0]['properties']['key1']
351
+ assert_equal "value2", @out[0]['properties']['key2']
352
+
353
+ end
354
+
355
+ def test_request_error_discard
356
+ stub_mixpanel_unavailable
357
+ d = create_driver(CONFIG + "event_key event\ndiscard_event_on_send_error true")
358
+ time = Time.new('2014-01-01T01:23:45+00:00').to_i
359
+ d.emit(sample_record, time)
360
+ d.run
361
+
362
+ logs = d.instance.log.logs
363
+
364
+ assert_match "MixpanelOutputErrorHandler:", logs[0]
365
+ assert_match "Class: Mixpanel::ServerError", logs[0]
366
+ assert_match "Message: Could not write to Mixpanel, server responded with 503 returning: 'Service Unavailable", logs[0]
367
+ assert_match "Backtrace", logs[0]
368
+ assert_match "Failed to track event to mixpanel", logs[1]
369
+ assert_match 'Record: {"properties":{"key1":"value1","key2":"value2","time":' + time.to_s + '},"event":"event1","distinct_id":"123"}', logs[1]
370
+ end
287
371
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-mixpanel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuyuki Honda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-22 00:00:00.000000000 Z
11
+ date: 2016-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.1.0
33
+ version: 2.2.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.1.0
40
+ version: 2.2.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -98,9 +98,11 @@ files:
98
98
  - example/index.html
99
99
  - fluent-plugin-mixpanel.gemspec
100
100
  - lib/fluent/plugin/in_http_mixpanel.rb
101
+ - lib/fluent/plugin/mixpanel_ruby_error_handler.rb
101
102
  - lib/fluent/plugin/out_mixpanel.rb
102
103
  - test/helper.rb
103
104
  - test/plugin/test_in_http_mixpanel.rb
105
+ - test/plugin/test_mixpanel_ruby_error_handler.rb
104
106
  - test/plugin/test_out_mixpanel.rb
105
107
  homepage: https://github.com/hakobera/fluent-plugin-mixpanel
106
108
  licenses:
@@ -122,11 +124,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
124
  version: '0'
123
125
  requirements: []
124
126
  rubyforge_project:
125
- rubygems_version: 2.4.5
127
+ rubygems_version: 2.5.1
126
128
  signing_key:
127
129
  specification_version: 4
128
130
  summary: Fluentd plugin to input/output event track data to mixpanel
129
131
  test_files:
130
132
  - test/helper.rb
131
133
  - test/plugin/test_in_http_mixpanel.rb
134
+ - test/plugin/test_mixpanel_ruby_error_handler.rb
132
135
  - test/plugin/test_out_mixpanel.rb