fluent-plugin-mixpanel 0.0.8 → 0.0.9
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/.gitignore +1 -0
- data/.travis.yml +3 -3
- data/README.md +12 -0
- data/fluent-plugin-mixpanel.gemspec +2 -2
- data/lib/fluent/plugin/mixpanel_ruby_error_handler.rb +15 -0
- data/lib/fluent/plugin/out_mixpanel.rb +31 -14
- data/test/helper.rb +1 -0
- data/test/plugin/test_in_http_mixpanel.rb +31 -16
- data/test/plugin/test_mixpanel_ruby_error_handler.rb +16 -0
- data/test/plugin/test_out_mixpanel.rb +112 -28
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96a9b1fba6cc39288c0391efc0816839dcc081e7
|
4
|
+
data.tar.gz: ffeddf702547a2d981517dcc364af2c31cf89f70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77255b4cb64f0dda7774fa891f2a52a5bffb465a4f95cb3c79b18c0449d19e49026871fde9ba41d2a8ca4434e39be362bb48628932483782ed501828237cd5df
|
7
|
+
data.tar.gz: e618c0d33e8de6e44dae7503c339f344bc516883941045fe89e0af92e9a975493876578235b30ea4a29b3f02ff367af2aa0662f7dcd6b1f48d7765dfcfc15fe7
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
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.
|
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.
|
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
|
-
|
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(
|
72
|
-
|
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
|
-
|
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(
|
83
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
@@ -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,
|
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
|
47
|
-
assert_equal 'X-Requested-With', res
|
48
|
-
assert_equal 'GET, POST, OPTIONS', res
|
49
|
-
assert_equal 'http://foo.example', res
|
50
|
-
assert_equal '1728000', res
|
51
|
-
assert_equal 'no-cache, no-store', res
|
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,
|
66
|
-
res = track("#{tag}", {"json"=>record, "time"=>
|
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,
|
85
|
-
res = track("#{tag}", {"json"=>record, "time"=>
|
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 =
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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.
|
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:
|
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.
|
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.
|
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.
|
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
|