logstash-filter-useragent 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -4
- data/README.md +3 -0
- data/lib/logstash/filters/useragent.rb +41 -32
- data/logstash-filter-useragent.gemspec +1 -1
- data/spec/filters/useragent_spec.rb +26 -6
- metadata +21 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b15dbfc5639b8beaf8ab72610de93b6f4639175f
|
4
|
+
data.tar.gz: c9966b10c9b5a543a48c35e8e6bb7d54d4f156db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83f573235d4e17df240c22281705b5755d429e6dc868d943418848f70d087b40723969800d6ac91f5c59b538931f8e930924171a572e9f7b54584580ec1338dd
|
7
|
+
data.tar.gz: 626a212f02ab445506b2caa8a6006bd0098ab493f347e85d3e23b17358ed5ee8bec43b76d77e95e441a1a570e1dbddfa69dcc4dbae3abf47ae5c9d5c2ccabe3d
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
## 2.0.4
|
2
|
+
- Fefactored field references, fixed specs and some cleanups
|
3
|
+
|
1
4
|
## 2.0.0
|
2
|
-
- Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
|
5
|
+
- Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
|
3
6
|
instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
|
4
7
|
- Dependency on logstash-core update to 2.0
|
5
8
|
|
6
|
-
|
9
|
+
## 2.0.1
|
7
10
|
- Add ability to replace source with target
|
8
|
-
|
9
|
-
|
11
|
+
|
12
|
+
## 1.1.0
|
13
|
+
- Add LRU cache
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Logstash Plugin
|
2
2
|
|
3
|
+
[![Build
|
4
|
+
Status](http://build-eu-00.elastic.co/view/LS%20Plugins/view/LS%20Filters/job/logstash-plugin-filter-useragent-unit/badge/icon)](http://build-eu-00.elastic.co/view/LS%20Plugins/view/LS%20Filters/job/logstash-plugin-filter-useragent-unit/)
|
5
|
+
|
3
6
|
This is a plugin for [Logstash](https://github.com/elastic/logstash).
|
4
7
|
|
5
8
|
It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
|
@@ -54,18 +54,18 @@ class LogStash::Filters::UserAgent < LogStash::Filters::Base
|
|
54
54
|
# number of cache misses and waste memory.
|
55
55
|
config :lru_cache_size, :validate => :number, :default => 1000
|
56
56
|
|
57
|
-
public
|
58
57
|
def register
|
59
58
|
require 'user_agent_parser'
|
59
|
+
|
60
60
|
if @regexes.nil?
|
61
61
|
begin
|
62
|
-
@parser = UserAgentParser::Parser.new
|
62
|
+
@parser = UserAgentParser::Parser.new
|
63
63
|
rescue Exception => e
|
64
64
|
begin
|
65
65
|
path = ::File.expand_path('../../../vendor/regexes.yaml', ::File.dirname(__FILE__))
|
66
66
|
@parser = UserAgentParser::Parser.new(:patterns_path => path)
|
67
67
|
rescue => ex
|
68
|
-
raise
|
68
|
+
raise("Failed to cache, due to: #{ex}\n")
|
69
69
|
end
|
70
70
|
end
|
71
71
|
else
|
@@ -74,14 +74,28 @@ class LogStash::Filters::UserAgent < LogStash::Filters::Base
|
|
74
74
|
end
|
75
75
|
|
76
76
|
LOOKUP_CACHE.max_size = @lru_cache_size
|
77
|
-
end #def register
|
78
77
|
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
# make @target in the format [field name] if defined, i.e. surrounded by brakets
|
79
|
+
normalized_target = (@target && @target !~ /^\[[^\[\]]+\]$/) ? "[#{@target}]" : ""
|
80
|
+
|
81
|
+
# predefine prefixed field names
|
82
|
+
@prefixed_name = "#{normalized_target}[#{@prefix}name]"
|
83
|
+
@prefixed_os = "#{normalized_target}[#{@prefix}os]"
|
84
|
+
@prefixed_os_name = "#{normalized_target}[#{@prefix}os_name]"
|
85
|
+
@prefixed_os_major = "#{normalized_target}[#{@prefix}os_major]"
|
86
|
+
@prefixed_os_minor = "#{normalized_target}[#{@prefix}os_minor]"
|
87
|
+
@prefixed_device = "#{normalized_target}[#{@prefix}device]"
|
88
|
+
@prefixed_major = "#{normalized_target}[#{@prefix}major]"
|
89
|
+
@prefixed_minor = "#{normalized_target}[#{@prefix}minor]"
|
90
|
+
@prefixed_patch = "#{normalized_target}[#{@prefix}patch]"
|
91
|
+
@prefixed_build = "#{normalized_target}[#{@prefix}build]"
|
92
|
+
end
|
82
93
|
|
94
|
+
def filter(event)
|
83
95
|
useragent = event[@source]
|
84
|
-
useragent = useragent.first if useragent.is_a?
|
96
|
+
useragent = useragent.first if useragent.is_a?(Array)
|
97
|
+
|
98
|
+
return if useragent.nil? || useragent.empty?
|
85
99
|
|
86
100
|
begin
|
87
101
|
ua_data = lookup_useragent(useragent)
|
@@ -92,19 +106,14 @@ class LogStash::Filters::UserAgent < LogStash::Filters::Base
|
|
92
106
|
|
93
107
|
return unless ua_data
|
94
108
|
|
95
|
-
if @target
|
96
|
-
|
97
|
-
elsif @target == @source
|
98
|
-
target = event[@source] = {}
|
99
|
-
else
|
100
|
-
target = event[@target] ||= {}
|
101
|
-
end
|
102
|
-
|
103
|
-
write_to_target(target, ua_data)
|
109
|
+
event.remove(@source) if @target == @source
|
110
|
+
set_fields(event, ua_data)
|
104
111
|
|
105
112
|
filter_matched(event)
|
106
|
-
end
|
113
|
+
end
|
107
114
|
|
115
|
+
# should be private but need to stay public for specs
|
116
|
+
# TODO: (colin) the related specs should be refactored to not rely on private methods.
|
108
117
|
def lookup_useragent(useragent)
|
109
118
|
return unless useragent
|
110
119
|
|
@@ -117,10 +126,12 @@ class LogStash::Filters::UserAgent < LogStash::Filters::Base
|
|
117
126
|
ua_data
|
118
127
|
end
|
119
128
|
|
120
|
-
|
129
|
+
private
|
130
|
+
|
131
|
+
def set_fields(event, ua_data)
|
121
132
|
# UserAgentParser outputs as US-ASCII.
|
122
133
|
|
123
|
-
|
134
|
+
event[@prefixed_name] = ua_data.name.dup.force_encoding(Encoding::UTF_8)
|
124
135
|
|
125
136
|
#OSX, Andriod and maybe iOS parse correctly, ua-agent parsing for Windows does not provide this level of detail
|
126
137
|
|
@@ -128,25 +139,23 @@ class LogStash::Filters::UserAgent < LogStash::Filters::Base
|
|
128
139
|
# and corrupt the cache. See uap source here for details https://github.com/ua-parser/uap-ruby/tree/master/lib/user_agent_parser
|
129
140
|
if (os = ua_data.os)
|
130
141
|
# The OS is a rich object
|
131
|
-
|
132
|
-
|
142
|
+
event[@prefixed_os] = ua_data.os.to_s.dup.force_encoding(Encoding::UTF_8)
|
143
|
+
event[@prefixed_os_name] = os.name.dup.force_encoding(Encoding::UTF_8) if os.name
|
133
144
|
|
134
145
|
# These are all strings
|
135
146
|
if (os_version = os.version)
|
136
|
-
|
137
|
-
|
147
|
+
event[@prefixed_os_major] = os_version.major.dup.force_encoding(Encoding::UTF_8) if os_version.major
|
148
|
+
event[@prefixed_os_minor] = os_version.minor.dup.force_encoding(Encoding::UTF_8) if os_version.minor
|
138
149
|
end
|
139
150
|
end
|
140
151
|
|
141
|
-
|
152
|
+
event[@prefixed_device] = ua_data.device.to_s.dup.force_encoding(Encoding::UTF_8) if ua_data.device
|
142
153
|
|
143
154
|
if (ua_version = ua_data.version)
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
155
|
+
event[@prefixed_major] = ua_version.major.dup.force_encoding(Encoding::UTF_8) if ua_version.major
|
156
|
+
event[@prefixed_minor] = ua_version.minor.dup.force_encoding(Encoding::UTF_8) if ua_version.minor
|
157
|
+
event[@prefixed_patch] = ua_version.patch.dup.force_encoding(Encoding::UTF_8) if ua_version.patch
|
158
|
+
event[@prefixed_build] = ua_version.patch_minor.dup.force_encoding(Encoding::UTF_8) if ua_version.patch_minor
|
148
159
|
end
|
149
160
|
end
|
150
|
-
|
151
|
-
end # class LogStash::Filters::UserAgent
|
152
|
-
|
161
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-filter-useragent'
|
4
|
-
s.version = '2.0.
|
4
|
+
s.version = '2.0.4'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "Parse user agent strings into structured data based on BrowserScope data"
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
@@ -41,12 +41,31 @@ describe LogStash::Filters::UserAgent do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
+
describe "Without user agent" do
|
45
|
+
config <<-CONFIG
|
46
|
+
filter {
|
47
|
+
useragent {
|
48
|
+
source => "message"
|
49
|
+
target => "ua"
|
50
|
+
}
|
51
|
+
}
|
52
|
+
CONFIG
|
53
|
+
|
54
|
+
sample "foo" => "bar" do
|
55
|
+
reject { subject }.include?("ua")
|
56
|
+
end
|
57
|
+
|
58
|
+
sample "" do
|
59
|
+
reject { subject }.include?("ua")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
44
63
|
describe "LRU object identity" do
|
64
|
+
let(:ua_string) { "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36" }
|
45
65
|
let(:uafilter) { LogStash::Filters::UserAgent.new("source" => "foo") }
|
46
|
-
let(:ua_data) {
|
47
|
-
|
48
|
-
}
|
49
|
-
subject(:target) { {} }
|
66
|
+
let(:ua_data) { uafilter.lookup_useragent(ua_string) }
|
67
|
+
|
68
|
+
subject(:target) { LogStash::Event.new("foo" => ua_string) }
|
50
69
|
|
51
70
|
before do
|
52
71
|
uafilter.register
|
@@ -54,7 +73,8 @@ describe LogStash::Filters::UserAgent do
|
|
54
73
|
# Stub this out because this UA doesn't have this field
|
55
74
|
allow(ua_data.version).to receive(:patch_minor).and_return("foo")
|
56
75
|
|
57
|
-
|
76
|
+
# expect(event).receive(:lookup_useragent)
|
77
|
+
uafilter.filter(target)
|
58
78
|
end
|
59
79
|
|
60
80
|
{
|
@@ -99,7 +119,7 @@ describe LogStash::Filters::UserAgent do
|
|
99
119
|
CONFIG
|
100
120
|
|
101
121
|
sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
|
102
|
-
insist { subject }.include?("message")
|
122
|
+
insist { subject.to_hash }.include?("message")
|
103
123
|
insist { subject["message"]["name"] } == "Chrome"
|
104
124
|
insist { subject["message"]["os"] } == "Linux"
|
105
125
|
insist { subject["message"]["major"] } == "26"
|
metadata
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-filter-useragent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
|
14
|
+
name: logstash-core
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
15
16
|
requirements:
|
16
17
|
- - '>='
|
17
18
|
- !ruby/object:Gem::Version
|
@@ -19,10 +20,7 @@ dependencies:
|
|
19
20
|
- - <
|
20
21
|
- !ruby/object:Gem::Version
|
21
22
|
version: 3.0.0
|
22
|
-
|
23
|
-
prerelease: false
|
24
|
-
type: :runtime
|
25
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirement: !ruby/object:Gem::Requirement
|
26
24
|
requirements:
|
27
25
|
- - '>='
|
28
26
|
- !ruby/object:Gem::Version
|
@@ -30,48 +28,50 @@ dependencies:
|
|
30
28
|
- - <
|
31
29
|
- !ruby/object:Gem::Version
|
32
30
|
version: 3.0.0
|
31
|
+
prerelease: false
|
32
|
+
type: :runtime
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
|
+
name: user_agent_parser
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 2.0.0
|
34
40
|
requirement: !ruby/object:Gem::Requirement
|
35
41
|
requirements:
|
36
42
|
- - '>='
|
37
43
|
- !ruby/object:Gem::Version
|
38
44
|
version: 2.0.0
|
39
|
-
name: user_agent_parser
|
40
45
|
prerelease: false
|
41
46
|
type: :runtime
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: lru_redux
|
42
49
|
version_requirements: !ruby/object:Gem::Requirement
|
43
50
|
requirements:
|
44
|
-
- -
|
51
|
+
- - ~>
|
45
52
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
47
|
-
- !ruby/object:Gem::Dependency
|
53
|
+
version: 1.1.0
|
48
54
|
requirement: !ruby/object:Gem::Requirement
|
49
55
|
requirements:
|
50
56
|
- - ~>
|
51
57
|
- !ruby/object:Gem::Version
|
52
58
|
version: 1.1.0
|
53
|
-
name: lru_redux
|
54
59
|
prerelease: false
|
55
60
|
type: :runtime
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: logstash-devutils
|
56
63
|
version_requirements: !ruby/object:Gem::Requirement
|
57
64
|
requirements:
|
58
|
-
- -
|
65
|
+
- - '>='
|
59
66
|
- !ruby/object:Gem::Version
|
60
|
-
version:
|
61
|
-
- !ruby/object:Gem::Dependency
|
67
|
+
version: '0'
|
62
68
|
requirement: !ruby/object:Gem::Requirement
|
63
69
|
requirements:
|
64
70
|
- - '>='
|
65
71
|
- !ruby/object:Gem::Version
|
66
72
|
version: '0'
|
67
|
-
name: logstash-devutils
|
68
73
|
prerelease: false
|
69
74
|
type: :development
|
70
|
-
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - '>='
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '0'
|
75
75
|
description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
|
76
76
|
email: info@elastic.co
|
77
77
|
executables: []
|