fluent-plugin-mixpanel 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -1
- data/example/http_server.sh +2 -0
- data/example/in_http_mixpanel.conf +13 -0
- data/example/index.html +32 -0
- data/fluent-plugin-mixpanel.gemspec +1 -1
- data/lib/fluent/plugin/in_http_mixpanel.rb +31 -0
- data/test/helper.rb +10 -0
- data/test/plugin/test_in_http_mixpanel.rb +116 -0
- data/test/plugin/test_out_mixpanel.rb +0 -3
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 491a99b98d20fddb7832d1057d7ff25c2dc89dba
|
4
|
+
data.tar.gz: 9a8b0b46a1f990178fd3352ac480cd884c779de4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94563b6483f2e5f6b4bff5953ed2a5d258c37839409de91ff8c552499bcbec900c055308b2712201c0a929a1d89a292178a12c0212ecb8411c6ff3e408fdce38
|
7
|
+
data.tar.gz: f8551e6232f9ea49f87585e3de4b9cd1f956b7c6f3b45f7350aac4e6d164977128485fff69e29a089fa6ae6f8d5e7f43a5a519f4c4f8202c23e36146e8adaab5
|
data/README.md
CHANGED
@@ -8,6 +8,10 @@
|
|
8
8
|
|
9
9
|
[Fluentd](http://fluentd.org) plugin to send event track data to [mixpanel](https://mixpanel.com).
|
10
10
|
|
11
|
+
### HttpMixpanelInput
|
12
|
+
|
13
|
+
[Fluentd](http://fluentd.org) plugin to integrate [mixpanel javascript libraries](https://mixpanel.com/docs/integration-libraries/javascript).
|
14
|
+
|
11
15
|
## Installation
|
12
16
|
|
13
17
|
Install with gem or fluent-gem command as:
|
@@ -27,7 +31,7 @@ $ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-mixpanel
|
|
27
31
|
MixpanelOutput needs mixpanel's `project_token`, that can get from your mixpanel project settings.
|
28
32
|
You should also specify property key name by `distinct_id_key` and `event_key`.
|
29
33
|
|
30
|
-
```
|
34
|
+
```
|
31
35
|
<match output.mixpanel.*>
|
32
36
|
type mixpanel
|
33
37
|
project_token YOUR_PROJECT_TOKEN
|
@@ -49,6 +53,24 @@ tracker = Mixpanel::Tracker.new(YOUR_PROJECT_TOKEN)
|
|
49
53
|
tracker.track("123", "event1", { key1: "value1", key2: "value2" })
|
50
54
|
```
|
51
55
|
|
56
|
+
### HttpMixpanelInput
|
57
|
+
|
58
|
+
HttpMixpanelInput is very similar to [http Input Plugin](http://docs.fluentd.org/en/articles/in_http). Only difference is that it needs `access_control_allow_origin`, to accept [Cross-site HTTP requests](https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS).
|
59
|
+
|
60
|
+
```
|
61
|
+
<source>
|
62
|
+
type http_mixpanel
|
63
|
+
bind 127.0.0.1
|
64
|
+
port 8888
|
65
|
+
body_size_limit 10m
|
66
|
+
keepalive_timeout 5
|
67
|
+
add_http_headers true
|
68
|
+
access_control_allow_origin http://0.0.0.0:8000
|
69
|
+
</source>
|
70
|
+
```
|
71
|
+
|
72
|
+
In example folder, you can see example configuration and HTML.
|
73
|
+
|
52
74
|
## Contributing
|
53
75
|
|
54
76
|
1. Fork it ( http://github.com/hakobera/fluent-plugin-mixpanel/fork )
|
data/example/index.html
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>in_http_mixpanel example</title>
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
<ul>
|
9
|
+
<li><button data-event='event1' data-value="1">Event1</button></li>
|
10
|
+
<li><button data-event='event2' data-value="2">Event2</button></li>
|
11
|
+
<li><button data-event='event3' data-value="3">Event3</button></li>
|
12
|
+
</ul>
|
13
|
+
<script type="text/javascript">
|
14
|
+
(function(c,a){window.mixpanel=a;var b,d,h,e;b=c.createElement("script");
|
15
|
+
b.type="text/javascript";b.async=!0;b.src=("https:"===c.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';d=c.getElementsByTagName("script")[0];d.parentNode.insertBefore(b,d);a._i=[];a.init=function(b,c,f){function d(a,b){var c=b.split(".");2==c.length&&(a=a[c[0]],b=c[1]);a[b]=function(){a.push([b].concat(Array.prototype.slice.call(arguments,0)))}}var g=a;"undefined"!==typeof f?g=a[f]=[]:f="mixpanel";g.people=g.people||[];h=['disable','track','track_pageview','track_links','track_forms','register','register_once','unregister','identify','alias','name_tag','set_config','people.set','people.set_once','people.increment','people.track_charge','people.append'];for(e=0;e<h.length;e++)d(g,h[e]);a._i.push([b,c,f])};a.__SV=1.2;})(document,window.mixpanel||[]);
|
16
|
+
mixpanel.init("dummy", {
|
17
|
+
api_host: 'http://0.0.0.0:8888',
|
18
|
+
debug: true
|
19
|
+
});
|
20
|
+
</script>
|
21
|
+
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
|
22
|
+
<script>
|
23
|
+
$(function () {
|
24
|
+
$('button').on('click', function () {
|
25
|
+
var evt = $(this).data('event');
|
26
|
+
var value = $(this).data('value');
|
27
|
+
mixpanel.track(evt, { value: value });
|
28
|
+
});
|
29
|
+
});
|
30
|
+
</script>
|
31
|
+
</body>
|
32
|
+
</html>
|
@@ -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.2"
|
8
8
|
spec.authors = ["Kazuyuki Honda"]
|
9
9
|
spec.email = ["hakobera@gmail.com"]
|
10
10
|
spec.summary = %q{Fluentd plugin to send event track data to mixpanel}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'fluent/plugin/in_http'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
class Fluent::HttpMixpanelInput < Fluent::HttpInput
|
5
|
+
Fluent::Plugin.register_input('http_mixpanel', self)
|
6
|
+
|
7
|
+
config_param :access_control_allow_origin
|
8
|
+
config_param :tag_prefix, :default => 'mixpanel'
|
9
|
+
|
10
|
+
def on_request(path_info, params)
|
11
|
+
data = Base64.decode64(params['data']).force_encoding('utf-8')
|
12
|
+
json = JSON.parse(data)
|
13
|
+
path = "/#{tag_prefix}.#{json['event']}"
|
14
|
+
params['json'] = json['properties'].to_json
|
15
|
+
params['time'] = (params['_'].to_i / 1000).to_s if params['_']
|
16
|
+
|
17
|
+
ret = super(path, params)
|
18
|
+
|
19
|
+
headers = {
|
20
|
+
'Access-Control-Allow-Credentials' => true,
|
21
|
+
'Access-Control-Allow-Headers' => 'X-Requested-With',
|
22
|
+
'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS',
|
23
|
+
'Access-Control-Allow-Origin' => access_control_allow_origin,
|
24
|
+
'Access-Control-Max-Age' => 1728000,
|
25
|
+
'Cache-Control' => 'no-cache, no-store',
|
26
|
+
'Content-type' => 'text/plain'
|
27
|
+
}
|
28
|
+
|
29
|
+
[ret[0], headers, (ret[0] == 200 ? 1 : 0)]
|
30
|
+
end
|
31
|
+
end
|
data/test/helper.rb
CHANGED
@@ -8,6 +8,8 @@ rescue Bundler::BundlerError => e
|
|
8
8
|
exit e.status_code
|
9
9
|
end
|
10
10
|
require 'test/unit'
|
11
|
+
require 'webmock/test_unit'
|
12
|
+
WebMock.disable_net_connect!(:allow_localhost => true)
|
11
13
|
|
12
14
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
15
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
@@ -22,7 +24,15 @@ unless ENV.has_key?('VERBOSE')
|
|
22
24
|
$log = nulllogger
|
23
25
|
end
|
24
26
|
|
27
|
+
def unused_port
|
28
|
+
s = TCPServer.open(0)
|
29
|
+
port = s.addr[1]
|
30
|
+
s.close
|
31
|
+
port
|
32
|
+
end
|
33
|
+
|
25
34
|
require 'fluent/plugin/out_mixpanel'
|
35
|
+
require 'fluent/plugin/in_http_mixpanel'
|
26
36
|
|
27
37
|
class Test::Unit::TestCase
|
28
38
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'net/http'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
class HttpMixpanelInputTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Fluent::Test.setup
|
9
|
+
end
|
10
|
+
|
11
|
+
PORT = unused_port
|
12
|
+
CONFIG = %[
|
13
|
+
port #{PORT}
|
14
|
+
bind 127.0.0.1
|
15
|
+
body_size_limit 10m
|
16
|
+
keepalive_timeout 5
|
17
|
+
access_control_allow_origin http://foo.example
|
18
|
+
]
|
19
|
+
|
20
|
+
def create_driver(conf=CONFIG)
|
21
|
+
Fluent::Test::InputTestDriver.new(Fluent::HttpMixpanelInput).configure(conf)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_configure
|
25
|
+
d = create_driver
|
26
|
+
assert_equal PORT, d.instance.port
|
27
|
+
assert_equal '127.0.0.1', d.instance.bind
|
28
|
+
assert_equal 10*1024*1024, d.instance.body_size_limit
|
29
|
+
assert_equal 5, d.instance.keepalive_timeout
|
30
|
+
assert_equal false, d.instance.add_http_headers
|
31
|
+
assert_equal 'http://foo.example', d.instance.access_control_allow_origin
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_time
|
35
|
+
d = create_driver
|
36
|
+
|
37
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
38
|
+
Fluent::Engine.now = time
|
39
|
+
|
40
|
+
d.expect_emit "mixpanel.tag1", time, {"a"=>1}
|
41
|
+
d.expect_emit "mixpanel.tag2", time, {"a"=>2}
|
42
|
+
|
43
|
+
d.run do
|
44
|
+
d.expected_emits.each {|tag,time,record|
|
45
|
+
res = track("#{tag}", {"json"=>record})
|
46
|
+
assert_equal "200", res.code
|
47
|
+
assert_equal 'true', res.header['access-control-allow-credentials']
|
48
|
+
assert_equal 'X-Requested-With', res.header['access-control-allow-headers']
|
49
|
+
assert_equal 'GET, POST, OPTIONS', res.header['access-control-allow-methods']
|
50
|
+
assert_equal d.instance.access_control_allow_origin, res.header['access-control-allow-origin']
|
51
|
+
assert_equal '1728000', res.header['access-control-max-age']
|
52
|
+
assert_equal 'no-cache, no-store', res.header['cache-control']
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_json
|
58
|
+
d = create_driver
|
59
|
+
|
60
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
61
|
+
|
62
|
+
d.expect_emit "mixpanel.tag1", time, {"a"=>1}
|
63
|
+
d.expect_emit "mixpanel.tag2", time, {"a"=>2}
|
64
|
+
|
65
|
+
d.run do
|
66
|
+
d.expected_emits.each {|tag,time,record|
|
67
|
+
res = track("#{tag}", {"json"=>record, "time"=>time.to_s})
|
68
|
+
assert_equal "200", res.code
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
d.emit_streams.each { |tag, es|
|
73
|
+
assert !include_http_header?(es.first[1])
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_json_with_add_http_headers
|
78
|
+
d = create_driver(CONFIG + "add_http_headers true")
|
79
|
+
|
80
|
+
time = Time.parse("2011-01-02 13:14:15 UTC").to_i
|
81
|
+
|
82
|
+
records = [["mixpanel.tag1", time, {"a"=>1}], ["mixpanel.tag2", time, {"a"=>2}]]
|
83
|
+
|
84
|
+
d.run do
|
85
|
+
records.each {|tag,time,record|
|
86
|
+
res = track("#{tag}", {"json"=>record, "time"=>time.to_s})
|
87
|
+
assert_equal "200", res.code
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
d.emit_streams.each { |tag, es|
|
92
|
+
assert include_http_header?(es.first[1])
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
def track(tag, params)
|
97
|
+
event = tag.sub(/^mixpanel\.(.+)$/, '\1')
|
98
|
+
data = {
|
99
|
+
event: event,
|
100
|
+
properties: params['json']
|
101
|
+
}
|
102
|
+
data = URI.escape(Base64.encode64(data.to_json))
|
103
|
+
query = "data=#{data}"
|
104
|
+
query += "&ip=1"
|
105
|
+
query += "&_=#{params['time']}000" if params['time']
|
106
|
+
path = "/track/?#{query}"
|
107
|
+
|
108
|
+
http = Net::HTTP.new("127.0.0.1", PORT)
|
109
|
+
req = Net::HTTP::Get.new(path)
|
110
|
+
http.request(req)
|
111
|
+
end
|
112
|
+
|
113
|
+
def include_http_header?(record)
|
114
|
+
record.keys.find { |header| header.start_with?('HTTP_') }
|
115
|
+
end
|
116
|
+
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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuyuki Honda
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -79,9 +79,14 @@ files:
|
|
79
79
|
- LICENSE.txt
|
80
80
|
- README.md
|
81
81
|
- Rakefile
|
82
|
+
- example/http_server.sh
|
83
|
+
- example/in_http_mixpanel.conf
|
84
|
+
- example/index.html
|
82
85
|
- fluent-plugin-mixpanel.gemspec
|
86
|
+
- lib/fluent/plugin/in_http_mixpanel.rb
|
83
87
|
- lib/fluent/plugin/out_mixpanel.rb
|
84
88
|
- test/helper.rb
|
89
|
+
- test/plugin/test_in_http_mixpanel.rb
|
85
90
|
- test/plugin/test_out_mixpanel.rb
|
86
91
|
homepage: https://github.com/hakobera/fluent-plugin-mixpanel
|
87
92
|
licenses:
|
@@ -109,4 +114,5 @@ specification_version: 4
|
|
109
114
|
summary: Fluentd plugin to send event track data to mixpanel
|
110
115
|
test_files:
|
111
116
|
- test/helper.rb
|
117
|
+
- test/plugin/test_in_http_mixpanel.rb
|
112
118
|
- test/plugin/test_out_mixpanel.rb
|