fluent-plugin-extract_query_params 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.
- data/.gitignore +18 -0
- data/Gemfile +2 -0
- data/LICENSE +2 -0
- data/README.md +93 -0
- data/Rakefile +9 -0
- data/fluent-plugin-extract_query_params.gemspec +18 -0
- data/lib/fluent/plugin/out_extract_query_params.rb +67 -0
- data/test/plugin/test_out_extract_query_params.rb +131 -0
- data/test/test_helper.rb +21 -0
- metadata +104 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# fluent-plugin-extract_query_params
|
2
|
+
|
3
|
+
## Component
|
4
|
+
|
5
|
+
### ExtractQueryParamsOutput
|
6
|
+
|
7
|
+
Fluentd plugin to extract key/values from URL query parameters.
|
8
|
+
|
9
|
+
## Synopsis
|
10
|
+
|
11
|
+
Imagin you have a config as below:
|
12
|
+
|
13
|
+
```
|
14
|
+
<match test.**>
|
15
|
+
type extract_query_params
|
16
|
+
|
17
|
+
key url
|
18
|
+
add_tag_prefix extracted.
|
19
|
+
only foo, baz
|
20
|
+
</match>
|
21
|
+
```
|
22
|
+
|
23
|
+
And you feed such a value into fluentd:
|
24
|
+
|
25
|
+
```
|
26
|
+
"test" => {
|
27
|
+
"url" => "http://example.com/?foo=bar&baz=qux&hoge=fuga"
|
28
|
+
}
|
29
|
+
```
|
30
|
+
|
31
|
+
Then you'll get re-emmited tag/record-s below:
|
32
|
+
|
33
|
+
```
|
34
|
+
"extracted.test" => {
|
35
|
+
"url" => "http://example.com/?foo=bar&baz=qux&hoge=fuga"
|
36
|
+
"foo" => "bar",
|
37
|
+
"baz" => "quex"
|
38
|
+
}
|
39
|
+
```
|
40
|
+
|
41
|
+
`hoge` parameter is not extracted.
|
42
|
+
|
43
|
+
## Configuration
|
44
|
+
|
45
|
+
### key
|
46
|
+
|
47
|
+
`key` is used to point a key whose value contains URL string.
|
48
|
+
|
49
|
+
### remove_tag_prefix, remove_tag_suffix, add_tag_prefix, add_tag_suffix
|
50
|
+
|
51
|
+
These params are included from `Fluent::HandleTagNameMixin`. See the code for details.
|
52
|
+
|
53
|
+
You must add at least one of these params.
|
54
|
+
|
55
|
+
### only
|
56
|
+
|
57
|
+
If set, only the key/value whose key is included `only` will be added to the record.
|
58
|
+
|
59
|
+
### except
|
60
|
+
|
61
|
+
If set, the key/value whose key is included `except` will NOT be added to the record.
|
62
|
+
|
63
|
+
## Installation
|
64
|
+
|
65
|
+
Add this line to your application's Gemfile:
|
66
|
+
|
67
|
+
gem 'fluent-plugin-extract_query_params'
|
68
|
+
|
69
|
+
And then execute:
|
70
|
+
|
71
|
+
$ bundle
|
72
|
+
|
73
|
+
Or install it yourself as:
|
74
|
+
|
75
|
+
$ gem install fluent-plugin-extract_query_params
|
76
|
+
|
77
|
+
## Contributing
|
78
|
+
|
79
|
+
1. Fork it
|
80
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
81
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
82
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
83
|
+
5. Create new Pull Request
|
84
|
+
|
85
|
+
## Copyright
|
86
|
+
|
87
|
+
### Copyright
|
88
|
+
|
89
|
+
Copyright (c) 2013- Kentaro Kuribayashi (@kentaro)
|
90
|
+
|
91
|
+
### License
|
92
|
+
|
93
|
+
Apache License, Version 2.0
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'fluent-plugin-extract_query_params'
|
3
|
+
gem.version = '0.0.1'
|
4
|
+
gem.authors = ['Kentaro Kuribayashi']
|
5
|
+
gem.email = ['kentarok@gmail.com']
|
6
|
+
gem.homepage = 'http://github.com/kentaro/fluent-plugin-extract_query_params'
|
7
|
+
gem.description = %q{Fluentd plugin to extract key/values from URL query parameters.}
|
8
|
+
gem.summary = %q{Fluentd plugin to extract key/values from URL query parameters}
|
9
|
+
|
10
|
+
gem.files = `git ls-files`.split($\)
|
11
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
12
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
13
|
+
gem.require_paths = ['lib']
|
14
|
+
|
15
|
+
gem.add_development_dependency 'rake'
|
16
|
+
gem.add_development_dependency 'fluentd'
|
17
|
+
gem.add_runtime_dependency 'fluentd'
|
18
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Fluent
|
4
|
+
class ExtractQueryParamsOutput < Output
|
5
|
+
include Fluent::HandleTagNameMixin
|
6
|
+
|
7
|
+
Fluent::Plugin.register_output('extract_query_params', self)
|
8
|
+
|
9
|
+
config_param :key, :string
|
10
|
+
config_param :only, :string, :default => nil
|
11
|
+
config_param :except, :string, :default => nil
|
12
|
+
|
13
|
+
def configure(conf)
|
14
|
+
super
|
15
|
+
|
16
|
+
if (
|
17
|
+
!remove_tag_prefix &&
|
18
|
+
!remove_tag_suffix &&
|
19
|
+
!add_tag_prefix &&
|
20
|
+
!add_tag_suffix
|
21
|
+
)
|
22
|
+
raise ConfigError, "out_extract_query_params: At least one of remove_tag_prefix/remove_tag_suffix/add_tag_prefix/add_tag_suffix is required to be set."
|
23
|
+
end
|
24
|
+
|
25
|
+
@include_keys = only && only.split(/\s*,\s*/).inject({}) do |hash, i|
|
26
|
+
hash[i] = true
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
@exclude_keys = except && except.split(/\s*,\s*/).inject({}) do |hash, i|
|
30
|
+
hash[i] = true
|
31
|
+
hash
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def emit(tag, es, chain)
|
36
|
+
es.each do |time, record|
|
37
|
+
filter_record(tag, time, record)
|
38
|
+
Engine.emit(tag, time, record)
|
39
|
+
end
|
40
|
+
|
41
|
+
chain.next
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_record(tag, time, record)
|
45
|
+
if record[key]
|
46
|
+
begin
|
47
|
+
url = URI.parse(record[key])
|
48
|
+
url.query.split('&').each do |pair|
|
49
|
+
key, value = pair.split('=').map { |i| URI.unescape(i) }
|
50
|
+
|
51
|
+
if only
|
52
|
+
record[key] = value if @include_keys.has_key?(key)
|
53
|
+
elsif except
|
54
|
+
record[key] = value if !@exclude_keys.has_key?(key)
|
55
|
+
else
|
56
|
+
record[key] = value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
rescue URI::InvalidURIError => error
|
60
|
+
$log.warn("out_extract_query_params: #{error.message}")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
super(tag, time, record)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class ExtractQueryParamsOutputTest < Test::Unit::TestCase
|
6
|
+
URL = 'http://example.com/?foo=bar&baz=qux&%E3%83%A2%E3%83%AA%E3%82%B9=%E3%81%99%E3%81%9F%E3%81%98%E3%81%8A'
|
7
|
+
|
8
|
+
def setup
|
9
|
+
Fluent::Test.setup
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_driver(conf, tag = 'test')
|
13
|
+
Fluent::Test::OutputTestDriver.new(
|
14
|
+
Fluent::ExtractQueryParamsOutput, tag
|
15
|
+
).configure(conf)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_configure
|
19
|
+
d = create_driver(%[
|
20
|
+
key url
|
21
|
+
add_tag_prefix extracted.
|
22
|
+
only foo, baz
|
23
|
+
])
|
24
|
+
|
25
|
+
assert_equal 'url', d.instance.key
|
26
|
+
assert_equal 'extracted.', d.instance.add_tag_prefix
|
27
|
+
assert_equal 'foo, baz', d.instance.only
|
28
|
+
|
29
|
+
# when mandatory keys not set
|
30
|
+
assert_raise(Fluent::ConfigError) do
|
31
|
+
create_driver(%[
|
32
|
+
key foo
|
33
|
+
])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_filter_record
|
38
|
+
d = create_driver(%[
|
39
|
+
key url
|
40
|
+
add_tag_prefix extracted.
|
41
|
+
])
|
42
|
+
|
43
|
+
tag = 'test'
|
44
|
+
record = {
|
45
|
+
'url' => URL,
|
46
|
+
}
|
47
|
+
d.instance.filter_record('test', Time.now, record)
|
48
|
+
|
49
|
+
assert_equal URL, record['url']
|
50
|
+
assert_equal 'bar', record['foo']
|
51
|
+
assert_equal 'qux', record['baz']
|
52
|
+
assert_equal 'すたじお', record['モリス']
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_filter_record_with_only
|
56
|
+
d = create_driver(%[
|
57
|
+
key url
|
58
|
+
add_tag_prefix extracted.
|
59
|
+
only foo, baz
|
60
|
+
])
|
61
|
+
|
62
|
+
tag = 'test'
|
63
|
+
record = { 'url' => URL }
|
64
|
+
d.instance.filter_record('test', Time.now, record)
|
65
|
+
|
66
|
+
assert_equal URL, record['url']
|
67
|
+
assert_equal 'bar', record['foo']
|
68
|
+
assert_equal 'qux', record['baz']
|
69
|
+
assert_nil record['モリス']
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_filter_record_with_except
|
73
|
+
d = create_driver(%[
|
74
|
+
key url
|
75
|
+
add_tag_prefix extracted.
|
76
|
+
except baz, モリス
|
77
|
+
])
|
78
|
+
|
79
|
+
tag = 'test'
|
80
|
+
record = { 'url' => URL }
|
81
|
+
d.instance.filter_record('test', Time.now, record)
|
82
|
+
|
83
|
+
assert_equal URL, record['url']
|
84
|
+
assert_equal 'bar', record['foo']
|
85
|
+
assert_nil record['baz']
|
86
|
+
assert_nil record['モリス']
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_emit
|
90
|
+
d = create_driver(%[
|
91
|
+
key url
|
92
|
+
add_tag_prefix extracted.
|
93
|
+
only foo, baz
|
94
|
+
])
|
95
|
+
d.run { d.emit('url' => URL) }
|
96
|
+
emits = d.emits
|
97
|
+
|
98
|
+
assert_equal 1, emits.count
|
99
|
+
assert_equal 'extracted.test', emits[0][0]
|
100
|
+
assert_equal URL, emits[0][2]['url']
|
101
|
+
assert_equal 'bar', emits[0][2]['foo']
|
102
|
+
assert_equal 'qux', emits[0][2]['baz']
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_emit_without_match_key
|
106
|
+
d = create_driver(%[
|
107
|
+
key no_such_key
|
108
|
+
add_tag_prefix extracted.
|
109
|
+
only foo, baz
|
110
|
+
])
|
111
|
+
d.run { d.emit('url' => URL) }
|
112
|
+
emits = d.emits
|
113
|
+
|
114
|
+
assert_equal 1, emits.count
|
115
|
+
assert_equal 'extracted.test', emits[0][0]
|
116
|
+
assert_equal URL, emits[0][2]['url']
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_emit_with_invalid_url
|
120
|
+
d = create_driver(%[
|
121
|
+
key url
|
122
|
+
add_tag_prefix extracted.
|
123
|
+
])
|
124
|
+
d.run { d.emit('url' => 'invalid url') }
|
125
|
+
emits = d.emits
|
126
|
+
|
127
|
+
assert_equal 1, emits.count
|
128
|
+
assert_equal 'extracted.test', emits[0][0]
|
129
|
+
assert_equal 'invalid url', emits[0][2]['url']
|
130
|
+
end
|
131
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
require 'fluent/test'
|
7
|
+
|
8
|
+
unless ENV.has_key?('VERBOSE')
|
9
|
+
nulllogger = Object.new
|
10
|
+
nulllogger.instance_eval {|obj|
|
11
|
+
def method_missing(method, *args)
|
12
|
+
# pass
|
13
|
+
end
|
14
|
+
}
|
15
|
+
$log = nulllogger
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'fluent/plugin/out_extract_query_params'
|
19
|
+
|
20
|
+
class Test::Unit::TestCase
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fluent-plugin-extract_query_params
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Kentaro Kuribayashi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: fluentd
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: fluentd
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Fluentd plugin to extract key/values from URL query parameters.
|
63
|
+
email:
|
64
|
+
- kentarok@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- .gitignore
|
70
|
+
- Gemfile
|
71
|
+
- LICENSE
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- fluent-plugin-extract_query_params.gemspec
|
75
|
+
- lib/fluent/plugin/out_extract_query_params.rb
|
76
|
+
- test/plugin/test_out_extract_query_params.rb
|
77
|
+
- test/test_helper.rb
|
78
|
+
homepage: http://github.com/kentaro/fluent-plugin-extract_query_params
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options: []
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.8.23
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Fluentd plugin to extract key/values from URL query parameters
|
102
|
+
test_files:
|
103
|
+
- test/plugin/test_out_extract_query_params.rb
|
104
|
+
- test/test_helper.rb
|