fluent-plugin-mixpanel 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d8d9a539d77b2b4338ad6de2f4389095fd034816
4
+ data.tar.gz: 62760bebcef57a117db6191fd5610d99a079ca7e
5
+ SHA512:
6
+ metadata.gz: 9383f6371b857b50d34892e334193b308124378497f70f9baaf4c21af058acc89a34e6ecf3222fa3f4800e6435ea8360caaa8fe2aa2fd69f9d0a45b2d264324c
7
+ data.tar.gz: f4c3f7cc40d6879ef48dd827a655a50d8caa583ba2a69578632f5db62ce9638ac17349941354423e82566feec5a8d1144fa4f23801aaed009790bc49b02eedd5
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-mixpanel.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2014- Kazuyuki Honda
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # fluent-plugin-mixpanel
2
+
3
+ [![Build Status](https://travis-ci.org/hakobera/fluent-plugin-mixpanel.png?branch=master)](https://travis-ci.org/hakobera/fluent-plugin-mixpanel)
4
+
5
+ ## Component
6
+
7
+ ### MixpanelOutput
8
+
9
+ [Fluentd](http://fluentd.org) plugin to send event track data to [mixpanel](https://mixpanel.com).
10
+
11
+ ## Installation
12
+
13
+ Install with gem or fluent-gem command as:
14
+
15
+ ```
16
+ # for fluentd
17
+ $ gem install fluent-plugin-mixpanel
18
+
19
+ # for td-agent
20
+ $ sudo /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-mixpanel
21
+ ```
22
+
23
+ ## Configuration
24
+
25
+ ### MixpanelOutput
26
+
27
+ MixpanelOutput needs mixpanel's `project_token`, that can get from your mixpanel project settings.
28
+ You should also specify property key name by `distinct_id_key` and `event_key`.
29
+
30
+ ```xml
31
+ <match output.mixpanel.*>
32
+ type mixpanel
33
+ project_token YOUR_PROJECT_TOKEN
34
+ distinct_id_key user_id
35
+ event_key event_name
36
+ </match>
37
+ ```
38
+
39
+ If record like this:
40
+
41
+ ```rb
42
+ { user_id: "123", event_name: "event1", key1: "value1", key2: "value2" }
43
+ ```
44
+
45
+ above settings send to the following data to mixpanel, using [mixpanel-ruby](https://github.com/mixpanel/mixpanel-ruby) gem.
46
+
47
+ ```rb
48
+ tracker = Mixpanel::Tracker.new(YOUR_PROJECT_TOKEN)
49
+ tracker.track("123", "event1", { key1: "value1", key2: "value2" })
50
+ ```
51
+
52
+ ## Contributing
53
+
54
+ 1. Fork it ( http://github.com/hakobera/fluent-plugin-mixpanel/fork )
55
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
56
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
57
+ 4. Push to the branch (`git push origin my-new-feature`)
58
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-mixpanel"
7
+ spec.version = "0.0.1"
8
+ spec.authors = ["Kazuyuki Honda"]
9
+ spec.email = ["hakobera@gmail.com"]
10
+ spec.summary = %q{Fluentd plugin to send event track data to mixpanel}
11
+ spec.description = %q{Fluentd plugin to send event track data to mixpanel}
12
+ spec.homepage = "https://github.com/hakobera/fluent-plugin-mixpanel"
13
+ spec.license = "Apache License, Version 2.0"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_runtime_dependency "fluentd"
21
+ spec.add_runtime_dependency "mixpanel-ruby"
22
+
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "webmock"
25
+ end
@@ -0,0 +1,76 @@
1
+ class Fluent::MixpanelOutput < Fluent::BufferedOutput
2
+ Fluent::Plugin.register_output('mixpanel', self)
3
+
4
+ config_param :project_token, :string
5
+ config_param :distinct_id_key, :string
6
+ config_param :event_key, :string
7
+
8
+ def initialize
9
+ super
10
+ require 'mixpanel-ruby'
11
+ end
12
+
13
+ def configure(conf)
14
+ super
15
+ @project_tokey = conf['project_token']
16
+ @distinct_id_key = conf['distinct_id_key']
17
+ @event_key = conf['event_key']
18
+
19
+ if @project_token.empty?
20
+ raise Fluent::ConfigError, "'project_token' must be specifed."
21
+ end
22
+
23
+ if @distinct_id_key.empty?
24
+ raise Fluent::ConfigError, "'distinct_id_key' must be specifed."
25
+ end
26
+
27
+ if @event_key.empty?
28
+ raise Fluent::ConfigError, "'event_key' must be specifed."
29
+ end
30
+ end
31
+
32
+ def start
33
+ super
34
+ @tracker = Mixpanel::Tracker.new(@project_token)
35
+ end
36
+
37
+ def shutdown
38
+ super
39
+ end
40
+
41
+ def format(tag, time, record)
42
+ [tag, time, record].to_msgpack
43
+ end
44
+
45
+ def write(chunk)
46
+ records = []
47
+ chunk.msgpack_each do |tag, time, record|
48
+ data = {}
49
+
50
+ if record[@distinct_id_key]
51
+ data['distinct_id'] = record[@distinct_id_key]
52
+ record.delete(@distinct_id_key)
53
+ else
54
+ log.warn('no distinct_id')
55
+ return
56
+ end
57
+
58
+ if record[@event_key]
59
+ data['event'] = record[@event_key]
60
+ record.delete(@event_key)
61
+ else
62
+ log.warn('no event')
63
+ return
64
+ end
65
+
66
+ record.merge!(time: time.to_i)
67
+ data['properties'] = record
68
+
69
+ records << data
70
+ end
71
+
72
+ records.each do |record|
73
+ @tracker.track(record['distinct_id'], record['event'], record['properties'])
74
+ end
75
+ end
76
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ require 'fluent/test'
15
+ unless ENV.has_key?('VERBOSE')
16
+ nulllogger = Object.new
17
+ nulllogger.instance_eval {|obj|
18
+ def method_missing(method, *args)
19
+ # pass
20
+ end
21
+ }
22
+ $log = nulllogger
23
+ end
24
+
25
+ require 'fluent/plugin/out_mixpanel'
26
+
27
+ class Test::Unit::TestCase
28
+ end
@@ -0,0 +1,93 @@
1
+ require 'helper'
2
+ require 'uri'
3
+ require 'webmock/test_unit'
4
+
5
+ WebMock.disable_net_connect!
6
+
7
+ class MixpanelOutputTest < Test::Unit::TestCase
8
+
9
+ def setup
10
+ Fluent::Test.setup
11
+ @out = []
12
+ end
13
+
14
+ CONFIG = %[
15
+ project_token test_token
16
+ distinct_id_key user_id
17
+ event_key event
18
+ ]
19
+
20
+ def create_driver(conf = CONFIG)
21
+ Fluent::Test::BufferedOutputTestDriver.new(Fluent::MixpanelOutput).configure(conf)
22
+ end
23
+
24
+ def stub_mixpanel(url="https://api.mixpanel.com/track")
25
+ stub_request(:post, url).with do |req|
26
+ body = URI.decode_www_form(req.body)
27
+ @out << JSON.load(Base64.decode64(body.assoc('data').last))
28
+ end.to_return(status: 200, body: JSON.generate({ status: 1 }))
29
+ end
30
+
31
+ def stub_mixpanel_unavailable(url="https://api.mixpanel.com/track")
32
+ stub_request(:post, url).to_return(status: 503, body: "Service Unavailable")
33
+ end
34
+
35
+ def sample_record
36
+ { user_id: "123", event: "event1", key1: "value1", key2: "value2" }
37
+ end
38
+
39
+ def test_configure
40
+ d = create_driver
41
+
42
+ assert_equal 'test_token', d.instance.project_token
43
+ assert_equal 'user_id', d.instance.distinct_id_key
44
+ assert_equal 'event', d.instance.event_key
45
+ end
46
+
47
+ def test_write
48
+ stub_mixpanel
49
+ d = create_driver
50
+ time = Time.new('2014-01-01T01:23:45+00:00')
51
+ d.emit(sample_record, time)
52
+ d.run
53
+
54
+ assert_equal "123", @out[0]['properties']['distinct_id']
55
+ assert_equal "event1", @out[0]['event']
56
+ assert_equal time.to_i, @out[0]['properties']['time']
57
+ assert_equal "value1", @out[0]['properties']['key1']
58
+ assert_equal "value2", @out[0]['properties']['key2']
59
+ end
60
+
61
+ def test_write_multi_request
62
+ stub_mixpanel
63
+ d = create_driver
64
+ time1 = Time.new('2014-01-01T01:23:45+00:00')
65
+ time2 = Time.new('2014-01-02T01:23:45+00:00')
66
+
67
+ d.emit(sample_record, time1)
68
+ d.emit(sample_record.merge(key3: "value3"), time2)
69
+ d.run
70
+
71
+ assert_equal "123", @out[0]['properties']['distinct_id']
72
+ assert_equal "event1", @out[0]['event']
73
+ assert_equal time1.to_i, @out[0]['properties']['time']
74
+ assert_equal "value1", @out[0]['properties']['key1']
75
+ assert_equal "value2", @out[0]['properties']['key2']
76
+
77
+ assert_equal "123", @out[1]['properties']['distinct_id']
78
+ assert_equal "event1", @out[1]['event']
79
+ assert_equal time2.to_i, @out[1]['properties']['time']
80
+ assert_equal "value1", @out[1]['properties']['key1']
81
+ assert_equal "value2", @out[1]['properties']['key2']
82
+ assert_equal "value2", @out[1]['properties']['key2']
83
+ end
84
+
85
+ def test_request_error
86
+ stub_mixpanel_unavailable
87
+ d = create_driver
88
+ d.emit(sample_record)
89
+ assert_raise(Mixpanel::ConnectionError) {
90
+ d.run
91
+ }
92
+ end
93
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-mixpanel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Kazuyuki Honda
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluentd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mixpanel-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Fluentd plugin to send event track data to mixpanel
70
+ email:
71
+ - hakobera@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - fluent-plugin-mixpanel.gemspec
83
+ - lib/fluent/plugin/out_mixpanel.rb
84
+ - test/helper.rb
85
+ - test/plugin/test_out_mixpanel.rb
86
+ homepage: https://github.com/hakobera/fluent-plugin-mixpanel
87
+ licenses:
88
+ - Apache License, Version 2.0
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.0
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Fluentd plugin to send event track data to mixpanel
110
+ test_files:
111
+ - test/helper.rb
112
+ - test/plugin/test_out_mixpanel.rb