logstash-filter-useragent 3.2.4-java → 3.3.1-java

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.
@@ -22,6 +22,7 @@ Gem::Specification.new do |s|
22
22
 
23
23
  # Gem dependencies
24
24
  s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
25
+ s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~> 1.1'
25
26
  s.add_development_dependency 'logstash-devutils'
26
27
  end
27
28
 
@@ -1,116 +1,448 @@
1
1
  # encoding: utf-8
2
-
3
2
  require "logstash/devutils/rspec/spec_helper"
3
+ require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
4
4
  require "logstash/filters/useragent"
5
5
 
6
6
  describe LogStash::Filters::UserAgent do
7
7
 
8
- describe "defaults" do
9
- config <<-CONFIG
10
- filter {
11
- useragent {
12
- source => "message"
13
- target => "ua"
8
+ subject { LogStash::Filters::UserAgent.new(options) }
9
+
10
+ let(:options) { { 'source' => 'message' } }
11
+ let(:message) { "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" }
12
+
13
+ let(:event) { LogStash::Event.new('message' => message) }
14
+
15
+ context 'with target', :ecs_compatibility_support do
16
+ ecs_compatibility_matrix(:disabled, :v1) do |ecs_select|
17
+
18
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
19
+
20
+ before(:each) do
21
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
22
+ end
23
+
24
+ config <<-CONFIG
25
+ filter {
26
+ useragent {
27
+ source => "message"
28
+ target => "ua"
29
+ }
14
30
  }
15
- }
16
- CONFIG
31
+ CONFIG
32
+
33
+ sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
34
+ expect( subject.to_hash ).to include("ua")
35
+ expect( subject.get("[ua][name]") ).to eql "Chrome"
36
+ if ecs_compatibility?
37
+ expect( subject.get("[ua][os][name]") ).to eql "Linux"
38
+ expect( subject.get("[ua][os][full]") ).to eql "Linux"
39
+ expect( subject.get("[ua][device][name]") ).to eql "Other"
40
+ ua_metadata = subject.get("[@metadata][filter][user_agent]")
41
+ expect( ua_metadata ).to include 'version' => { 'major' => '26', 'minor' => '0', 'patch' => '1410' }
42
+ expect( subject.get("[ua][version]") ).to eql "26.0.1410.63"
43
+ expect( subject.get("[ua]").keys ).to_not include 'major'
44
+ expect( subject.get("[ua]").keys ).to_not include 'minor'
45
+ else
46
+ expect( subject.get("[ua][os_name]") ).to eql "Linux"
47
+ expect( subject.get("[ua][os_full]") ).to eql "Linux"
48
+ expect( subject.get("[ua][os]") ).to eql "Linux"
49
+ expect( subject.get("[ua][device]") ).to eql "Other"
50
+ expect( subject.get("[ua][major]") ).to eql "26"
51
+ expect( subject.get("[ua][minor]") ).to eql "0"
52
+ end
53
+
54
+ expect( subject.get("[ua][name]").encoding ).to eql Encoding::UTF_8
55
+ end
56
+
57
+ sample "MacOutlook/16.24.0.190414 (Intelx64 Mac OS X Version 10.14.4 (Build 18E226))" do
58
+ expect( subject.to_hash ).to include("ua")
59
+ expect( subject.get("[ua][name]") ).to eql "MacOutlook"
60
+ if ecs_compatibility?
61
+ expect( subject.get("[ua][version]") ).to eql "16.24.0.190414"
62
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.14.4"
63
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
64
+ expect( subject.get("[ua][os][version]") ).to eql '10.14.4'
65
+ expect( subject.get("[ua][device][name]") ).to eql 'Mac'
66
+
67
+ expect( subject.get("[ua][os][name]").encoding ).to eql Encoding::UTF_8
68
+ else
69
+ expect( subject.get("[ua][major]") ).to eql "16"
70
+ expect( subject.get("[ua][minor]") ).to eql "24"
71
+ expect( subject.get("[ua][patch]") ).to eql "0"
72
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.14.4"
73
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
74
+ expect( subject.get("[ua][os_major]") ).to eql '10'
75
+ expect( subject.get("[ua][os_minor]") ).to eql '14'
76
+ expect( subject.get("[ua][device]") ).to eql 'Mac'
77
+
78
+ expect( subject.get("[ua][os]") ).to eql "Mac OS X"
79
+ expect( subject.get("[ua][os]").encoding ).to eql Encoding::UTF_8
80
+ end
81
+ end
82
+
83
+ # Safari 12 on Mojave
84
+ sample "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Safari/605.1.15" do
85
+ expect( subject.to_hash ).to include("ua")
86
+ expect( subject.get("[ua][name]") ).to eql "Safari"
87
+ if ecs_compatibility?
88
+ expect( subject.get("[ua][version]") ).to eql "12.0"
89
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.14"
90
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
91
+ expect( subject.get("[ua][os][version]") ).to eql '10.14'
92
+ ua_metadata = subject.get("[@metadata][filter][user_agent][os]")
93
+ expect( ua_metadata ).to include 'version' => { 'major' => '10', 'minor' => '14' }
94
+
95
+ expect( subject.get("[@metadata][filter][user_agent][os][version][major]").encoding ).to eql Encoding::UTF_8
96
+ else
97
+ expect( subject.get("[ua][major]") ).to eql "12"
98
+ expect( subject.get("[ua][minor]") ).to eql "0"
99
+ expect( subject.get("[ua][patch]") ).to be nil
100
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.14"
101
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
102
+ expect( subject.get("[ua][os_major]") ).to eql '10'
103
+ expect( subject.get("[ua][os_minor]") ).to eql '14'
104
+
105
+ expect( subject.get("[ua][os_major]").encoding ).to eql Encoding::UTF_8
106
+ end
107
+ end
108
+
109
+ # Safari 7 on Mac OS X (Mavericks)
110
+ sample "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A" do
111
+ expect( subject.to_hash ).to include("ua")
112
+ expect( subject.get("[ua][name]") ).to eql "Safari"
113
+ if ecs_compatibility?
114
+ expect( subject.get("[ua][version]") ).to eql "7.0.3"
115
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.9.3"
116
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
117
+ expect( subject.get("[ua][device][name]") ).to eql 'Mac'
118
+ else
119
+ expect( subject.get("[ua][major]") ).to eql "7"
120
+ expect( subject.get("[ua][minor]") ).to eql "0"
121
+ expect( subject.get("[ua][patch]") ).to eql "3"
122
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.9.3"
123
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
124
+ expect( subject.get("[ua][os_major]") ).to eql '10'
125
+ expect( subject.get("[ua][os_minor]") ).to eql '9'
126
+ expect( subject.get("[ua][device]") ).to eql 'Mac'
127
+ end
128
+ end
129
+
130
+ sample "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Firefox/45.0" do
131
+ expect( subject.to_hash ).to include("ua")
132
+ expect( subject.get("[ua][name]") ).to eql "Firefox"
133
+ if ecs_compatibility?
134
+ expect( subject.get("[ua][version]") ).to eql "45.0"
135
+ expect( subject.get("[ua][os][full]") ).to eql "Mac OS X 10.11"
136
+ expect( subject.get("[ua][os][name]") ).to eql "Mac OS X"
137
+ expect( subject.get("[ua][os][version]") ).to eql '10.11'
138
+ expect( subject.get("[ua][device][name]") ).to eql 'Mac'
139
+ else
140
+ expect( subject.get("[ua][major]") ).to eql "45"
141
+ expect( subject.get("[ua][minor]") ).to eql "0"
142
+ expect( subject.get("[ua][patch]") ).to be nil
143
+ expect( subject.get("[ua][os_full]") ).to eql "Mac OS X 10.11"
144
+ expect( subject.get("[ua][os_name]") ).to eql "Mac OS X"
145
+ expect( subject.get("[ua][os_major]") ).to eql '10'
146
+ expect( subject.get("[ua][os_minor]") ).to eql '11'
147
+ expect( subject.get("[ua][device]") ).to eql 'Mac'
148
+ end
149
+ end
150
+
151
+ # IE7 Vista
152
+ sample "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)" do
153
+ expect( subject.to_hash ).to include("ua")
154
+ if ecs_compatibility?
155
+ expect( subject.get("[ua][os][name]") ).to eql "Windows"
156
+ expect( subject.get("[ua][os][version]") ).to eql 'Vista'
157
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
158
+
159
+ expect( subject.get("[ua][device][name]").encoding ).to eql Encoding::UTF_8
160
+ else
161
+ expect( subject.get("[ua][os_name]") ).to eql "Windows"
162
+ expect( subject.get("[ua][os_major]") ).to eql 'Vista'
163
+ expect( subject.get("[ua][os_minor]") ).to be nil
164
+ expect( subject.get("[ua][device]") ).to eql 'Other'
165
+
166
+ expect( subject.get("[ua][device]").encoding ).to eql Encoding::UTF_8
167
+ end
168
+ end
169
+
170
+ # IE8 XP
171
+ sample "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.5.30729)" do
172
+ expect( subject.to_hash ).to include("ua")
173
+ expect( subject.get("[ua][name]") ).to eql 'IE'
174
+ if ecs_compatibility?
175
+ expect( subject.get("[ua][os][name]") ).to eql 'Windows'
176
+ expect( subject.get("[ua][os][version]") ).to eql 'XP'
177
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
178
+ else
179
+ expect( subject.get("[ua][os_name]") ).to eql 'Windows'
180
+ expect( subject.get("[ua][os_major]") ).to eql 'XP'
181
+ expect( subject.get("[ua][os_minor]") ).to be nil
182
+ expect( subject.get("[ua][device]") ).to eql 'Other'
183
+ end
184
+ end
185
+
186
+ # # Windows 8.1
187
+ sample "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246" do
188
+ expect( subject.to_hash ).to include("ua")
189
+ expect( subject.get("[ua][name]") ).to eql 'Edge'
190
+ if ecs_compatibility?
191
+ expect( subject.get("[ua][os][name]") ).to eql 'Windows'
192
+ expect( subject.get("[ua][os][version]") ).to eql '8.1'
193
+ else
194
+ expect( subject.get("[ua][os_name]") ).to eql 'Windows'
195
+ expect( subject.get("[ua][os_major]") ).to eql '8'
196
+ expect( subject.get("[ua][os_minor]") ).to eql '1'
197
+ end
198
+ end
199
+
200
+ # Windows 10
201
+ sample "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.50" do
202
+ expect( subject.to_hash ).to include("ua")
203
+ expect( subject.get("[ua][name]") ).to eql "Edge"
204
+ if ecs_compatibility?
205
+ expect( subject.get("[ua][version]") ).to eql "89.0.774.50"
206
+ expect( subject.get("[ua][os][full]") ).to eql "Windows 10"
207
+ expect( subject.get("[ua][os][name]") ).to eql "Windows"
208
+ expect( subject.get("[ua][os][version]") ).to eql '10'
209
+ ua_metadata = subject.get("[@metadata][filter][user_agent][os]")
210
+ expect( ua_metadata ).to include 'version' => { 'major' => '10' }
211
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
212
+ else
213
+ expect( subject.get("[ua][os_name]") ).to eql "Windows"
214
+ expect( subject.get("[ua][os_major]") ).to eql '10'
215
+ expect( subject.get("[ua][os_minor]") ).to be nil
216
+ expect( subject.get("[ua][device]") ).to eql 'Other'
217
+ end
218
+ end
219
+
220
+ # Chrome on Linux
221
+ sample "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36" do
222
+ expect( subject.to_hash ).to include("ua")
223
+ expect( subject.get("[ua][name]") ).to eql 'Chrome'
224
+ if ecs_compatibility?
225
+ expect( subject.get("[ua][os][name]") ).to eql "Linux"
226
+ expect( subject.get("[ua][os][version]") ).to be nil
227
+ expect( subject.get("[ua][device][name]") ).to eql 'Other'
228
+ else
229
+ expect( subject.get("[ua][os_name]") ).to eql "Linux"
230
+ expect( subject.get("[ua][os_major]") ).to be nil
231
+ expect( subject.get("[ua][os_minor]") ).to be nil
232
+ expect( subject.get("[ua][device]") ).to eql 'Other'
233
+ end
234
+ end
17
235
 
18
- sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
19
- insist { subject }.include?("ua")
20
- insist { subject.get("[ua][name]") } == "Chrome"
21
- insist { subject.get("[ua][os]") } == "Linux"
22
- insist { subject.get("[ua][major]") } == "26"
23
- insist { subject.get("[ua][minor]") } == "0"
24
236
  end
237
+ end
238
+
239
+ context "manually specified regexes file", :ecs_compatibility_support do
240
+ ecs_compatibility_matrix(:disabled, :v1) do |ecs_select|
241
+
242
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
243
+
244
+ before(:each) do
245
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
246
+ end
247
+
248
+ config <<-CONFIG
249
+ filter {
250
+ useragent {
251
+ source => "message"
252
+ target => "[ua]"
253
+ regexes => "build/resources/main/regexes.yaml"
254
+ }
255
+ }
256
+ CONFIG
257
+
258
+ sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
259
+ expect( subject.to_hash ).to include("ua")
260
+ if ecs_compatibility?
261
+ expect( subject.get("[ua][name]") ).to eql "Chrome"
262
+ expect( subject.get("[ua][os][name]") ).to eql "Linux"
263
+ expect( subject.get("[ua][version]") ).to eql "26.0.1410.63"
264
+ expect( subject.get("[@metadata][filter][user_agent][version][major]") ).to eql "26"
265
+ expect( subject.get("[@metadata][filter][user_agent][version][minor]") ).to eql "0"
266
+ else
267
+ expect( subject.get("[ua][name]") ).to eql "Chrome"
268
+ expect( subject.get("[ua][os]") ).to eql "Linux"
269
+ expect( subject.get("[ua][major]") ).to eql "26"
270
+ expect( subject.get("[ua][minor]") ).to eql "0"
271
+ end
272
+ end
25
273
 
26
- sample "MacOutlook/16.24.0.190414 (Intelx64 Mac OS X Version 10.14.4 (Build 18E226))" do
27
- insist { subject }.include?("ua")
28
- insist { subject.get("[ua][name]") } == "MacOutlook"
29
- insist { subject.get("[ua][major]") } == "16"
30
- insist { subject.get("[ua][minor]") } == "24"
31
- insist { subject.get("[ua][os]") } == "Mac OS X"
32
- insist { subject.get("[ua][os_name]") } == "Mac OS X"
33
- insist { subject.get("[ua][os_major]") } == "10"
34
- insist { subject.get("[ua][os_minor]") } == "14"
35
274
  end
36
275
  end
37
276
 
38
- describe "manually specified regexes file" do
39
- config <<-CONFIG
40
- filter {
41
- useragent {
42
- source => "message"
43
- target => "ua"
44
- regexes => "build/resources/main/regexes.yaml"
277
+ context "without target field", :ecs_compatibility_support do
278
+ ecs_compatibility_matrix(:disabled, :v1) do |ecs_select|
279
+
280
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
281
+
282
+ before(:each) do
283
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
284
+ end
285
+
286
+ config <<-CONFIG
287
+ filter {
288
+ useragent {
289
+ source => "message"
290
+ }
45
291
  }
46
- }
47
- CONFIG
292
+ CONFIG
48
293
 
49
- sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
50
- insist { subject }.include?("ua")
51
- insist { subject.get("[ua][name]") } == "Chrome"
52
- insist { subject.get("[ua][os]") } == "Linux"
53
- insist { subject.get("[ua][major]") } == "26"
54
- insist { subject.get("[ua][minor]") } == "0"
294
+ sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
295
+ if ecs_compatibility? # [user_agent] default target in ECS
296
+ expect( subject.get("user_agent") ).to include 'name' => 'Chrome'
297
+ expect( subject.get("user_agent") ).to include 'os' => hash_including('name' => 'Linux')
298
+ expect( subject.get("user_agent") ).to include 'version' => '26.0.1410.63'
299
+ else
300
+ expect( subject.get("name") ).to eql "Chrome"
301
+ expect( subject.get("os_name") ).to eql "Linux"
302
+ expect( subject.get("os") ).to eql "Linux"
303
+ expect( subject.get("major") ).to eql "26"
304
+ expect( subject.get("minor") ).to eql "0"
305
+ expect( subject.get("patch") ).to eql "1410"
306
+ expect( subject.get("version") ).to eql "26.0.1410.63"
307
+ end
308
+ end
55
309
  end
56
310
  end
57
-
58
- describe "Without target field" do
59
- config <<-CONFIG
60
- filter {
61
- useragent {
62
- source => "message"
311
+
312
+ context "nested target field", :ecs_compatibility_support do
313
+ ecs_compatibility_matrix(:disabled, :v1) do
314
+
315
+ before(:each) do
316
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
317
+ end
318
+
319
+ config <<-CONFIG
320
+ filter {
321
+ useragent {
322
+ source => "message"
323
+ target => "[foo][bar]"
324
+ }
63
325
  }
64
- }
65
- CONFIG
326
+ CONFIG
327
+
328
+ # Facebook App User Agent
329
+ sample "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) " +
330
+ "Mobile/15E148 [FBAN/FBIOS;FBDV/iPhone11,8;FBMD/iPhone;FBSN/iOS;FBSV/13.3.1;FBSS/2;FBID/phone;FBLC/en_US;FBOP/5;FBCR/]" do
331
+ expect( subject ).to include 'foo'
332
+ expect( subject.get('foo') ).to include 'bar'
333
+ expect( subject.get('foo')['bar'] ).to include "name" => "Facebook"
334
+ end
335
+
336
+ end
337
+ end
338
+
339
+ context "without user agent", :ecs_compatibility_support do
340
+ ecs_compatibility_matrix(:disabled, :v1) do |ecs_select|
341
+
342
+ let(:ecs_compatibility?) { ecs_select.active_mode != :disabled }
343
+
344
+ before(:each) do
345
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
346
+ end
347
+
348
+ config <<-CONFIG
349
+ filter {
350
+ useragent {
351
+ source => "message"
352
+ target => "ua"
353
+ }
354
+ }
355
+ CONFIG
356
+
357
+ sample "foo" => "bar" do
358
+ expect( subject.to_hash ).to_not include("ua")
359
+ end
360
+
361
+ sample "" do
362
+ expect( subject.to_hash ).to_not include("ua")
363
+ end
66
364
 
67
- sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
68
- insist { subject.get("name") } == "Chrome"
69
- insist { subject.get("os") } == "Linux"
70
- insist { subject.get("major") } == "26"
71
- insist { subject.get("minor") } == "0"
72
365
  end
73
366
  end
74
367
 
75
- describe "Without user agent" do
368
+ describe "non-exact UA data" do
76
369
  config <<-CONFIG
77
370
  filter {
78
371
  useragent {
79
372
  source => "message"
80
- target => "ua"
373
+ target => "user_agent"
81
374
  }
82
375
  }
83
376
  CONFIG
84
377
 
85
- sample "foo" => "bar" do
86
- reject { subject }.include?("ua")
378
+ sample 'Prefix DATA! Mozilla/5.0 (Android 11; Mobile; rv:68.0) Gecko/68.0 Firefox/86.0' do
379
+ expect( subject.to_hash ).to include("user_agent")
380
+ expect( subject.get('user_agent') ).to include "name" => "Firefox Mobile", "version" => '86.0', "os_name" => "Android"
87
381
  end
88
382
 
89
- sample "" do
90
- reject { subject }.include?("ua")
383
+ end
384
+
385
+ context "with prefix", :ecs_compatibility_support do
386
+ ecs_compatibility_matrix(:disabled, :v1) do |ecs_select|
387
+
388
+ let(:message) { 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0' }
389
+ let(:options) { super().merge('prefix' => 'pre_') }
390
+
391
+ before(:each) do
392
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
393
+ end
394
+
395
+ it 'works in legacy mode with prefix (without a warning)' do
396
+ expect( subject.logger ).to_not receive(:warn)
397
+ subject.register
398
+
399
+ subject.filter(event)
400
+
401
+ expect( event.to_hash ).to include('pre_name' => 'Firefox', 'pre_version' => '78.0')
402
+ end if ecs_select.active_mode == :disabled
403
+
404
+ it 'warns in ECS mode (and ignores prefix)' do
405
+ expect( subject.logger ).to receive(:warn).with /Field prefix isn't supported in ECS compatibility mode/
406
+ subject.register
407
+
408
+ subject.filter(event)
409
+
410
+ expect( event.to_hash.keys.find { |key| key.index('pre_') } ).to be nil
411
+ expect( event.get('user_agent').keys.find { |key| key.index('pre_') } ).to be nil
412
+ expect( event.get('user_agent') ).to include('name' => 'Firefox', 'version' => '78.0')
413
+ end if ecs_select.active_mode != :disabled
414
+
91
415
  end
92
416
  end
93
417
 
94
- describe "LRU object identity" do
95
- 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" }
96
- let(:uafilter) { LogStash::Filters::UserAgent.new("source" => "foo") }
97
- let(:ua_data) { uafilter.lookup_useragent(ua_string) }
418
+ context "no prefix", :ecs_compatibility_support do
419
+ ecs_compatibility_matrix(:disabled, :v1) do
98
420
 
99
- subject(:target) { LogStash::Event.new("foo" => ua_string) }
421
+ let(:message) { 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0' }
100
422
 
101
- before do
102
- uafilter.register
423
+ before(:each) do
424
+ allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
425
+ end
103
426
 
104
- # Stub this out because this UA doesn't have this field
105
- allow(ua_data.userAgent).to receive(:patchMinor).and_return("foo")
427
+ it 'does not warn' do
428
+ expect( subject.logger ).to_not receive(:warn)
429
+ subject.register
430
+ end
106
431
 
107
- # expect(event).receive(:lookup_useragent)
108
- uafilter.filter(target)
432
+ end
433
+ end
434
+
435
+ describe "LRU object identity" do
436
+
437
+ let(:ua_data) { subject.send :lookup_useragent, message }
438
+
439
+ before do
440
+ subject.register
441
+ subject.filter(event)
109
442
  end
110
443
 
111
444
  {
112
445
  "name" => lambda {|uad| uad.userAgent.family},
113
- "os" => lambda {|uad| uad.os.family},
114
446
  "os_name" => lambda {|uad| uad.os.family},
115
447
  "os_major" => lambda {|uad| uad.os.major},
116
448
  "os_minor" => lambda {|uad| uad.os.minor},
@@ -118,11 +450,10 @@ describe LogStash::Filters::UserAgent do
118
450
  "major" => lambda {|uad| uad.userAgent.major},
119
451
  "minor" => lambda {|uad| uad.userAgent.minor},
120
452
  "patch" => lambda {|uad| uad.userAgent.patch},
121
- "build" => lambda {|uad| uad.userAgent.patchMinor}
122
453
  }.each do |field, uad_getter|
123
454
  context "for the #{field} field" do
124
- let(:value) {uad_getter.call(ua_data)}
125
- let(:target_field) { target.get(field)}
455
+ let(:value) { uad_getter.call(ua_data) }
456
+ let(:target_field) { event.get(field) }
126
457
 
127
458
  it "should not have a nil value" do
128
459
  expect(target_field).to be_truthy
@@ -135,6 +466,10 @@ describe LogStash::Filters::UserAgent do
135
466
  it "should dup/clone the field to prevent cache corruption" do
136
467
  expect(target_field.object_id).not_to eql(value.object_id)
137
468
  end
469
+
470
+ it "should be an utf-8 string" do
471
+ expect(target_field.encoding.name).to eql 'UTF-8'
472
+ end
138
473
  end
139
474
  end
140
475
  end
@@ -150,11 +485,25 @@ describe LogStash::Filters::UserAgent do
150
485
  CONFIG
151
486
 
152
487
  sample "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.63 Safari/537.31" do
153
- insist { subject.to_hash }.include?("message")
154
- insist { subject.get("[message][name]") } == "Chrome"
155
- insist { subject.get("[message][os]") } == "Linux"
156
- insist { subject.get("[message][major]") } == "26"
157
- insist { subject.get("[message][minor]") } == "0"
488
+ expect( subject.to_hash ).to include("message")
489
+ expect( subject.get("[message][name]") ).to eql "Chrome"
490
+ expect( subject.get("[message][os]") ).to eql "Linux"
491
+ expect( subject.get("[message][major]") ).to eql "26"
492
+ expect( subject.get("[message][minor]") ).to eql "0"
158
493
  end
159
494
  end
495
+
496
+ context 'exception handling' do
497
+
498
+ before do
499
+ subject.register
500
+ expect(subject).to receive(:lookup_useragent).and_raise RuntimeError.new('this is a test')
501
+ end
502
+
503
+ it 'errors do not propagate' do
504
+ expect(subject.logger).to receive(:error).with(/Unknown error while parsing user agent data/, hash_including(exception: RuntimeError, message: 'this is a test'))
505
+ expect { subject.filter(event) }.not_to raise_error
506
+ end
507
+
508
+ end
160
509
  end