logstash-patterns-core 4.2.0 → 4.3.0

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +98 -0
  3. data/Gemfile +3 -0
  4. data/README.md +11 -18
  5. data/lib/logstash/patterns/core.rb +11 -3
  6. data/logstash-patterns-core.gemspec +1 -1
  7. data/patterns/ecs-v1/aws +28 -0
  8. data/patterns/ecs-v1/bacula +53 -0
  9. data/patterns/ecs-v1/bind +13 -0
  10. data/patterns/ecs-v1/bro +30 -0
  11. data/patterns/ecs-v1/exim +26 -0
  12. data/patterns/ecs-v1/firewalls +111 -0
  13. data/patterns/ecs-v1/grok-patterns +95 -0
  14. data/patterns/ecs-v1/haproxy +40 -0
  15. data/patterns/ecs-v1/httpd +17 -0
  16. data/patterns/ecs-v1/java +34 -0
  17. data/patterns/ecs-v1/junos +13 -0
  18. data/patterns/ecs-v1/linux-syslog +16 -0
  19. data/patterns/{maven → ecs-v1/maven} +0 -0
  20. data/patterns/ecs-v1/mcollective +4 -0
  21. data/patterns/ecs-v1/mongodb +7 -0
  22. data/patterns/ecs-v1/nagios +124 -0
  23. data/patterns/ecs-v1/postgresql +2 -0
  24. data/patterns/ecs-v1/rails +13 -0
  25. data/patterns/ecs-v1/redis +3 -0
  26. data/patterns/ecs-v1/ruby +2 -0
  27. data/patterns/ecs-v1/squid +6 -0
  28. data/patterns/ecs-v1/zeek +33 -0
  29. data/patterns/{aws → legacy/aws} +1 -1
  30. data/patterns/{bacula → legacy/bacula} +5 -5
  31. data/patterns/legacy/bind +3 -0
  32. data/patterns/{bro → legacy/bro} +0 -0
  33. data/patterns/{exim → legacy/exim} +8 -2
  34. data/patterns/{firewalls → legacy/firewalls} +2 -2
  35. data/patterns/{grok-patterns → legacy/grok-patterns} +0 -0
  36. data/patterns/{haproxy → legacy/haproxy} +0 -0
  37. data/patterns/{httpd → legacy/httpd} +1 -1
  38. data/patterns/{java → legacy/java} +0 -0
  39. data/patterns/{junos → legacy/junos} +0 -0
  40. data/patterns/{linux-syslog → legacy/linux-syslog} +0 -0
  41. data/patterns/legacy/maven +1 -0
  42. data/patterns/{mcollective → legacy/mcollective} +0 -0
  43. data/patterns/{mcollective-patterns → legacy/mcollective-patterns} +0 -0
  44. data/patterns/{mongodb → legacy/mongodb} +0 -0
  45. data/patterns/{nagios → legacy/nagios} +0 -0
  46. data/patterns/{postgresql → legacy/postgresql} +0 -0
  47. data/patterns/{rails → legacy/rails} +0 -0
  48. data/patterns/{redis → legacy/redis} +0 -0
  49. data/patterns/{ruby → legacy/ruby} +0 -0
  50. data/patterns/legacy/squid +4 -0
  51. data/spec/patterns/aws_spec.rb +395 -0
  52. data/spec/patterns/bacula_spec.rb +367 -0
  53. data/spec/patterns/bind_spec.rb +78 -0
  54. data/spec/patterns/bro_spec.rb +613 -0
  55. data/spec/patterns/core_spec.rb +51 -9
  56. data/spec/patterns/exim_spec.rb +201 -0
  57. data/spec/patterns/firewalls_spec.rb +669 -66
  58. data/spec/patterns/haproxy_spec.rb +246 -38
  59. data/spec/patterns/httpd_spec.rb +215 -94
  60. data/spec/patterns/java_spec.rb +357 -27
  61. data/spec/patterns/junos_spec.rb +101 -0
  62. data/spec/patterns/mcollective_spec.rb +35 -0
  63. data/spec/patterns/mongodb_spec.rb +170 -33
  64. data/spec/patterns/nagios_spec.rb +296 -79
  65. data/spec/patterns/netscreen_spec.rb +123 -0
  66. data/spec/patterns/rails3_spec.rb +87 -29
  67. data/spec/patterns/redis_spec.rb +157 -121
  68. data/spec/patterns/shorewall_spec.rb +85 -74
  69. data/spec/patterns/squid_spec.rb +139 -0
  70. data/spec/patterns/syslog_spec.rb +266 -22
  71. data/spec/spec_helper.rb +80 -6
  72. metadata +64 -28
  73. data/patterns/bind +0 -3
  74. data/patterns/squid +0 -4
  75. data/spec/patterns/bro.rb +0 -126
  76. data/spec/patterns/s3_spec.rb +0 -173
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+ require "logstash/patterns/core"
4
+
5
+ describe_pattern "MCOLLECTIVE", ['legacy', 'ecs-v1'] do
6
+
7
+ let(:message) { "I, [2010-12-29T11:15:32.321744 #11479] INFO -- : mcollectived:33 The Marionette Collective 1.1.0 started logging at info level" }
8
+
9
+ it do
10
+ should include("timestamp" => "2010-12-29T11:15:32.321744")
11
+ end
12
+
13
+ it do
14
+ if ecs_compatibility?
15
+ should include("process" => { "pid" => 11479 })
16
+ else
17
+ should include("pid" => "11479")
18
+ end
19
+ end
20
+
21
+ it do
22
+ if ecs_compatibility?
23
+ should include("log" => hash_including("level" => "INFO"))
24
+ else
25
+ should include("event_level" => "INFO")
26
+ end
27
+ end
28
+
29
+ # NOTE: pattern seems unfinished - missing match of remaining message
30
+ it 'should have extracted message' do
31
+ # but did not :
32
+ expect( subject['message'] ).to eql message
33
+ end
34
+
35
+ end
@@ -2,83 +2,220 @@
2
2
  require "spec_helper"
3
3
  require "logstash/patterns/core"
4
4
 
5
- describe "MONGO3_LOG" do
6
-
7
- let(:pattern) { "MONGO3_LOG" }
5
+ describe_pattern "MONGO3_LOG", ['legacy', 'ecs-v1'] do
8
6
 
9
7
  context "parsing an standard/basic message" do
10
8
 
11
- let(:value) { "2014-11-03T18:28:32.450-0500 I NETWORK [initandlisten] waiting for connections on port 27017" }
12
-
13
- subject { grok_match(pattern, value) }
9
+ let(:message) { "2014-11-03T18:28:32.450-0500 I NETWORK [initandlisten] waiting for connections on port 27017" }
14
10
 
15
11
  it { should include("timestamp" => "2014-11-03T18:28:32.450-0500") }
16
12
 
17
- it { should include("severity" => "I") }
13
+ it do
14
+ if ecs_compatibility?
15
+ should include("log" => { 'level' => "I" })
16
+ else
17
+ should include("severity" => "I")
18
+ end
19
+ end
18
20
 
19
- it { should include("component" => "NETWORK") }
21
+ it do
22
+ if ecs_compatibility?
23
+ should include("mongodb" => hash_including("component" => "NETWORK"))
24
+ else
25
+ should include("component" => "NETWORK")
26
+ end
27
+ end
20
28
 
21
- it { should include("context" => "initandlisten") }
29
+ it do
30
+ if ecs_compatibility?
31
+ should include("mongodb" => hash_including("context" => "initandlisten"))
32
+ else
33
+ should include("context" => "initandlisten")
34
+ end
35
+ end
22
36
 
23
37
  it "generates a message field" do
24
- expect(subject["message"]).to include("waiting for connections on port 27017")
38
+ expect(subject["message"]).to eql [ message, "waiting for connections on port 27017" ]
25
39
  end
26
40
  end
27
41
 
28
42
  context "parsing a message with a missing component" do
29
43
 
30
- let(:value) { "2015-02-24T18:17:47.148+0000 F - [conn11] Got signal: 11 (Segmentation fault)." }
44
+ let(:message) { "2015-02-24T18:17:47.148+0000 F - [conn11] Got signal: 11 (Segmentation fault)." }
31
45
 
32
- subject { grok_match(pattern, value) }
46
+ it 'matches' do
47
+ should include("timestamp" => "2015-02-24T18:17:47.148+0000")
33
48
 
34
- it { should include("timestamp" => "2015-02-24T18:17:47.148+0000") }
49
+ if ecs_compatibility?
50
+ expect( grok_result['mongodb'].keys ).to_not include("component")
51
+ else
52
+ should include("component" => "-")
53
+ end
35
54
 
36
- it { should include("severity" => "F") }
55
+ if ecs_compatibility?
56
+ should include("log" => { 'level' => "F" })
57
+ else
58
+ should include("severity" => "F")
59
+ end
37
60
 
38
- it { should include("component" => "-") }
39
-
40
- it { should include("context" => "conn11") }
61
+ if ecs_compatibility?
62
+ should include("mongodb" => hash_including("context" => "conn11"))
63
+ else
64
+ should include("context" => "conn11")
65
+ end
66
+ end
41
67
 
42
68
  it "generates a message field" do
43
- expect(subject["message"]).to include("Got signal: 11 (Segmentation fault).")
69
+ expect(subject["message"]).to eql [ message, "Got signal: 11 (Segmentation fault)." ]
44
70
  end
45
71
  end
46
72
 
47
73
  context "parsing a message with a multiwords context" do
48
74
 
49
- let(:value) { "2015-04-23T06:57:28.256+0200 I JOURNAL [journal writer] Journal writer thread started" }
50
-
51
- subject { grok_match(pattern, value) }
75
+ let(:message) { "2015-04-23T06:57:28.256+0200 I JOURNAL [journal writer] Journal writer thread started" }
52
76
 
53
- it { should include("timestamp" => "2015-04-23T06:57:28.256+0200") }
77
+ it 'matches' do
78
+ should include("timestamp" => "2015-04-23T06:57:28.256+0200")
54
79
 
55
- it { should include("severity" => "I") }
80
+ if ecs_compatibility?
81
+ should include("log" => { 'level' => "I" })
82
+ else
83
+ should include("severity" => "I")
84
+ end
56
85
 
57
- it { should include("component" => "JOURNAL") }
86
+ if ecs_compatibility?
87
+ should include("mongodb" => hash_including("component" => "JOURNAL"))
88
+ else
89
+ should include("component" => "JOURNAL")
90
+ end
58
91
 
59
- it { should include("context" => "journal writer") }
92
+ if ecs_compatibility?
93
+ should include("mongodb" => hash_including("context" => "journal writer"))
94
+ else
95
+ should include("context" => "journal writer")
96
+ end
97
+ end
60
98
 
61
99
  it "generates a message field" do
62
100
  expect(subject["message"]).to include("Journal writer thread started")
63
101
  end
102
+
103
+ context '3.6 simple log line' do
104
+
105
+ let(:message) do
106
+ '2020-08-13T11:58:09.672+0200 I NETWORK [conn2] end connection 127.0.0.1:41258 (1 connection now open)'
107
+ end
108
+
109
+ it 'matches' do
110
+ should include("timestamp" => "2020-08-13T11:58:09.672+0200")
111
+
112
+ if ecs_compatibility?
113
+ should include("mongodb" => hash_including("component" => "NETWORK"))
114
+ else
115
+ should include("component" => "NETWORK")
116
+ end
117
+
118
+ if ecs_compatibility?
119
+ should include("mongodb" => hash_including("context" => "conn2"))
120
+ else
121
+ should include("context" => "conn2")
122
+ end
123
+
124
+ expect(subject["message"]).to include("end connection 127.0.0.1:41258 (1 connection now open)")
125
+ end
126
+
127
+ end
128
+
129
+ context '3.6 long log line' do
130
+
131
+ let(:command) do
132
+ 'command config.$cmd command: createIndexes { createIndexes: "system.sessions", ' +
133
+ 'indexes: [ { key: { lastUse: 1 }, name: "lsidTTLIndex", expireAfterSeconds: 1800 } ], $db: "config" } ' +
134
+ 'numYields:0 reslen:101 locks:{ Global: { acquireCount: { r: 2, w: 2 } }, Database: { acquireCount: { w: 2 } }, ' +
135
+ 'Collection: { acquireCount: { w: 1 } } } protocol:op_msg 0ms'
136
+ end
137
+
138
+ let(:message) do
139
+ '2020-08-13T11:57:45.259+0200 I COMMAND [LogicalSessionCacheRefresh] ' + command
140
+ end
141
+
142
+ it 'matches' do
143
+ should include("timestamp" => "2020-08-13T11:57:45.259+0200")
144
+
145
+ if ecs_compatibility?
146
+ should include("mongodb" => hash_including("component" => "COMMAND"))
147
+ else
148
+ should include("component" => "COMMAND")
149
+ end
150
+
151
+ if ecs_compatibility?
152
+ should include("mongodb" => hash_including("context" => "LogicalSessionCacheRefresh"))
153
+ else
154
+ should include("context" => "LogicalSessionCacheRefresh")
155
+ end
156
+
157
+ expect(subject["message"]).to eql [message, command]
158
+ end
159
+
160
+ end
161
+
64
162
  end
65
163
 
66
164
  context "parsing a message without context" do
67
165
 
68
- let(:value) { "2015-04-23T07:00:13.864+0200 I CONTROL Ctrl-C signal" }
69
-
70
- subject { grok_match(pattern, value) }
166
+ let(:message) { "2015-04-23T07:00:13.864+0200 I CONTROL Ctrl-C signal" }
71
167
 
72
- it { should include("timestamp" => "2015-04-23T07:00:13.864+0200") }
168
+ it 'matches' do
169
+ should include("timestamp" => "2015-04-23T07:00:13.864+0200")
73
170
 
74
- it { should include("severity" => "I") }
171
+ if ecs_compatibility?
172
+ should include("log" => { 'level' => "I" })
173
+ else
174
+ should include("severity" => "I")
175
+ end
75
176
 
76
- it { should include("component" => "CONTROL") }
177
+ if ecs_compatibility?
178
+ should include("mongodb" => hash_including("component" => "CONTROL"))
179
+ else
180
+ should include("component" => "CONTROL")
181
+ end
77
182
 
78
- it { should_not have_key("context") }
183
+ if ecs_compatibility?
184
+ expect( grok_result['mongodb'].keys ).to_not include("context")
185
+ else
186
+ should_not have_key("context")
187
+ end
188
+ end
79
189
 
80
190
  it "generates a message field" do
81
- expect(subject["message"]).to include("Ctrl-C signal")
191
+ expect(subject["message"]).to eql [ message, "Ctrl-C signal" ]
82
192
  end
83
193
  end
84
194
  end
195
+
196
+ describe_pattern "MONGO_SLOWQUERY", ['legacy', 'ecs-v1'] do
197
+
198
+ let(:message) do
199
+ "[conn11485496] query sample.User query: { clientId: 12345 } ntoreturn:0 ntoskip:0 nscanned:287011 keyUpdates:0 numYields: 2 locks(micros) r:4187700 nreturned:18 reslen:14019 2340ms"
200
+ end
201
+
202
+ it do
203
+ if ecs_compatibility?
204
+ should include("mongodb" => {
205
+ "database" => "sample", "collection" => "User",
206
+ "query" => { "original"=>"{ clientId: 12345 }" },
207
+ "profile" => {
208
+ "op" => "query",
209
+ "ntoreturn" => 0, "ntoskip" => 0, "nscanned" => 287011, "nreturned" => 18,
210
+ "duration" => 2340
211
+ }
212
+ })
213
+ else
214
+ should include("database" => "sample", "collection" => "User")
215
+ should include("ntoreturn" => '0', "ntoskip" => '0', "nscanned" => "287011", "nreturned" => "18")
216
+ should include("query" => "{ clientId: 12345 }")
217
+ should include("duration" => "2340")
218
+ end
219
+ end
220
+
221
+ end
@@ -2,246 +2,463 @@
2
2
  require "spec_helper"
3
3
  require "logstash/patterns/core"
4
4
 
5
- describe "NAGIOSLOGLINE - CURRENT HOST STATE" do
5
+ describe_pattern "NAGIOSLOGLINE - CURRENT HOST STATE", [ 'legacy', 'ecs-v1' ] do
6
6
 
7
- let(:value) { "[1427925600] CURRENT HOST STATE: nagioshost;UP;HARD;1;PING OK - Packet loss = 0%, RTA = 2.24 ms" }
8
- let(:grok) { grok_match(subject, value) }
7
+ let(:message) { "[1427925600] CURRENT HOST STATE: nagioshost;UP;HARD;1;PING OK - Packet loss = 0%, RTA = 2.24 ms" }
9
8
 
10
9
  it "a pattern pass the grok expression" do
11
10
  expect(grok).to pass
12
11
  end
13
12
 
14
13
  it "matches a simple message" do
15
- expect(subject).to match(value)
14
+ expect(pattern).to match(message)
16
15
  end
17
16
 
18
17
  it "generates the nagios_epoch field" do
19
- expect(grok).to include("nagios_epoch" => "1427925600")
18
+ if ecs_compatibility?
19
+ expect(grok).to include("timestamp" => "1427925600")
20
+ else
21
+ expect(grok).to include("nagios_epoch" => "1427925600")
22
+ end
20
23
  end
21
24
 
22
25
  it "generates the nagios_message field" do
23
- expect(grok).to include("nagios_message" => "PING OK - Packet loss = 0%, RTA = 2.24 ms")
26
+ if ecs_compatibility?
27
+ expect(grok).to include("message" => [message, "PING OK - Packet loss = 0%, RTA = 2.24 ms"])
28
+ else
29
+ expect(grok).to include("nagios_message" => "PING OK - Packet loss = 0%, RTA = 2.24 ms")
30
+ end
24
31
  end
25
32
 
26
33
  it "generates the nagios_hostname field" do
27
- expect(grok).to include("nagios_hostname" => "nagioshost")
34
+ if ecs_compatibility?
35
+ expect(grok).to include("host" => { "hostname" => "nagioshost" })
36
+ else
37
+ expect(grok).to include("nagios_hostname" => "nagioshost")
38
+ end
28
39
  end
29
40
 
30
41
  it "generates the nagios_state field" do
31
- expect(grok).to include("nagios_state" => "UP")
42
+ if ecs_compatibility?
43
+ expect(grok).to include("service" => hash_including("state" => "UP"))
44
+ else
45
+ expect(grok).to include("nagios_state" => "UP")
46
+ end
32
47
  end
33
48
 
34
49
  it "generates the nagios_statetype field" do
35
- expect(grok).to include("nagios_statetype" => "HARD")
50
+ if ecs_compatibility?
51
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("state_type" => "HARD")))
52
+ else
53
+ expect(grok).to include("nagios_statetype" => "HARD")
54
+ end
36
55
  end
37
56
 
38
57
  end
39
58
 
40
- describe "NAGIOSLOGLINE - CURRENT SERVICE STATE" do
59
+ describe_pattern "NAGIOSLOGLINE - CURRENT SERVICE STATE", [ 'legacy', 'ecs-v1' ] do
41
60
 
42
- let(:value) { "[1427925600] CURRENT SERVICE STATE: nagioshost;nagiosservice;OK;HARD;1;nagiosmessage" }
43
- let(:grok) { grok_match(subject, value) }
61
+ let(:message) { "[1427925600] CURRENT SERVICE STATE: nagioshost;SSH;OK;HARD;1;nagiosmessage" }
44
62
 
45
63
  it "a pattern pass the grok expression" do
46
64
  expect(grok).to pass
47
65
  end
48
66
 
49
67
  it "matches a simple message" do
50
- expect(subject).to match(value)
68
+ expect(pattern).to match(message)
51
69
  end
52
70
 
53
71
  it "generates the nagios_type field" do
54
- expect(grok).to include("nagios_type" => "CURRENT SERVICE STATE")
72
+ if ecs_compatibility?
73
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("type" => "CURRENT SERVICE STATE")))
74
+ else
75
+ expect(grok).to include("nagios_type" => "CURRENT SERVICE STATE")
76
+ end
55
77
  end
56
78
 
57
79
  it "generates the nagios_epoch field" do
58
- expect(grok).to include("nagios_epoch" => "1427925600")
80
+ if ecs_compatibility?
81
+ expect(grok).to include("timestamp" => "1427925600")
82
+ else
83
+ expect(grok).to include("nagios_epoch" => "1427925600")
84
+ end
59
85
  end
60
86
 
61
87
  it "generates the nagios_message field" do
62
- expect(grok).to include("nagios_message" => "nagiosmessage")
88
+ if ecs_compatibility?
89
+ expect(grok).to include("message" => [message, "nagiosmessage"])
90
+ else
91
+ expect(grok).to include("nagios_message" => "nagiosmessage")
92
+ end
63
93
  end
64
94
 
65
- it "generates the nagios_hostname field" do
66
- expect(grok).to include("nagios_hostname" => "nagioshost")
95
+ it "generates the hostname field" do
96
+ if ecs_compatibility?
97
+ expect(grok).to include("host" => { "hostname" => "nagioshost" })
98
+ else
99
+ expect(grok).to include("nagios_hostname" => "nagioshost")
100
+ end
67
101
  end
68
102
 
69
- it "generates the nagios_service field" do
70
- expect(grok).to include("nagios_service" => "nagiosservice")
103
+ it "generates the service field" do
104
+ if ecs_compatibility?
105
+ expect(grok).to include("service" => hash_including("name" => "SSH"))
106
+ else
107
+ expect(grok).to include("nagios_service" => "SSH")
108
+ end
71
109
  end
72
110
 
73
111
  it "generates the nagios_state field" do
74
- expect(grok).to include("nagios_state" => "OK")
112
+ if ecs_compatibility?
113
+ expect(grok).to include("service" => hash_including("state" => "OK"))
114
+ else
115
+ expect(grok).to include("nagios_state" => "OK")
116
+ end
75
117
  end
76
118
 
77
119
  it "generates the nagios_statetype field" do
78
- expect(grok).to include("nagios_statetype" => "HARD")
79
- end
120
+ if ecs_compatibility?
121
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("state_type" => "HARD")))
122
+ else
123
+ expect(grok).to include("nagios_statetype" => "HARD")
124
+ end
125
+ end
126
+
127
+ it "generates the nagios_statecode field" do
128
+ if ecs_compatibility?
129
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("attempt" => 1)))
130
+ else
131
+ # NOTE: (legacy) nagios_statecode corresponds to current_attempt (according to Nagios' source)
132
+ expect(grok).to include("nagios_statecode" => "1")
133
+ end
134
+ end
135
+
136
+ context 'real-world example' do
137
+
138
+ let(:message) do
139
+ '[1427956600] CURRENT SERVICE STATE: prod-virtual-ESz06;check_vmfs_prod-PvDC2;CRITICAL;HARD;3;CRITICAL - /vmfs/volumes/prod-vsRoot - total: 8191.75 Gb - used: 7859.84 Gb (95%)- free: 331.90 Gb (5%)'
140
+ end
141
+
142
+ it 'matches' do
143
+ if ecs_compatibility?
144
+ expect(grok).to include(
145
+ "host" => { "hostname" => "prod-virtual-ESz06" },
146
+ "service" => { "name" => "check_vmfs_prod-PvDC2", "state" => 'CRITICAL' },
147
+ "nagios" => { "log" => {
148
+ "type" => "CURRENT SERVICE STATE",
149
+ "state_type" => "HARD",
150
+ "attempt" => 3
151
+ }},
152
+ "message" => [message, "CRITICAL - /vmfs/volumes/prod-vsRoot - total: 8191.75 Gb - used: 7859.84 Gb (95%)- free: 331.90 Gb (5%)"]
153
+ )
154
+ else
155
+ expect(grok).to include(
156
+ "nagios_type"=>"CURRENT SERVICE STATE",
157
+ "nagios_state"=>"CRITICAL",
158
+ "nagios_statetype"=>"HARD",
159
+ "nagios_hostname"=>"prod-virtual-ESz06",
160
+ "nagios_statecode"=>"3", # NOTE: "incorrect" - corresponds to current_attempt (according to Nagios' source)
161
+ "nagios_message"=>"CRITICAL - /vmfs/volumes/prod-vsRoot - total: 8191.75 Gb - used: 7859.84 Gb (95%)- free: 331.90 Gb (5%)"
162
+ )
163
+ end
164
+ end
80
165
 
166
+ end
81
167
  end
82
168
 
83
- describe "NAGIOSLOGLINE - TIMEPERIOD TRANSITION" do
169
+ describe_pattern "NAGIOSLOGLINE - TIMEPERIOD TRANSITION", [ 'legacy', 'ecs-v1' ] do
84
170
 
85
- let(:value) { "[1427925600] TIMEPERIOD TRANSITION: 24X7;-1;1" }
86
- let(:grok) { grok_match(subject, value) }
87
-
88
- it "a pattern pass the grok expression" do
89
- expect(grok).to pass
90
- end
171
+ let(:message) { "[1427925600] TIMEPERIOD TRANSITION: 24X7;-1;1" }
91
172
 
92
- it "matches a simple message" do
93
- expect(subject).to match(value)
173
+ it "matches the message" do
174
+ expect(pattern).to match(message)
94
175
  end
95
176
 
96
177
  it "generates the nagios_type field" do
97
- expect(grok).to include("nagios_type" => "TIMEPERIOD TRANSITION")
178
+ if ecs_compatibility?
179
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("type" => 'TIMEPERIOD TRANSITION')))
180
+ else
181
+ expect(grok).to include("nagios_type" => "TIMEPERIOD TRANSITION")
182
+ end
98
183
  end
99
184
 
100
185
  it "generates the nagios_epoch field" do
101
- expect(grok).to include("nagios_epoch" => "1427925600")
186
+ expect(grok).to include("nagios_epoch" => "1427925600") unless ecs_compatibility?
102
187
  end
103
188
 
104
- it "generates the nagios_esrvice field" do
105
- expect(grok).to include("nagios_service" => "24X7")
189
+ it "generates the service field" do
190
+ if ecs_compatibility?
191
+ expect(grok).to include("service" => hash_including("name" => '24X7'))
192
+ else
193
+ expect(grok).to include("nagios_service" => "24X7")
194
+ end
106
195
  end
107
196
 
108
197
  it "generates the period from/to fields" do
109
- expect(grok).to include("nagios_unknown1" => "-1", "nagios_unknown2" => "1")
198
+ if ecs_compatibility?
199
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("period_from" => -1, "period_to" => 1)))
200
+ else
201
+ expect(grok).to include("nagios_unknown1" => "-1", "nagios_unknown2" => "1")
202
+ end
110
203
  end
111
204
 
112
205
  # Regression test for but fixed in Nagios patterns #30
113
206
  it "doesn't end in a semi-colon" do
114
- expect(grok['message']).to_not end_with(";")
207
+ message = grok['message']
208
+ message = message.last if message.is_a?(Array)
209
+ expect(message).to_not end_with(";")
115
210
  end
116
211
 
117
212
  end
118
213
 
119
- describe "NAGIOSLOGLINE - SERVICE ALERT" do
214
+ describe_pattern "NAGIOSLOGLINE - SERVICE ALERT", [ 'legacy', 'ecs-v1' ] do
120
215
 
121
- let(:value) { "[1427925689] SERVICE ALERT: varnish;Varnish Backend Connections;CRITICAL;SOFT;1;Current value: 154.0, warn threshold: 10.0, crit threshold: 20.0" }
122
- let(:grok) { grok_match(subject, value) }
216
+ let(:message) { "[1427925689] SERVICE ALERT: varnish;Varnish Backend Connections;CRITICAL;SOFT;1;Current value: 154.0, warn threshold: 10.0, crit threshold: 20.0" }
123
217
 
124
218
  it "a pattern pass the grok expression" do
125
219
  expect(grok).to pass
126
220
  end
127
221
 
128
222
  it "matches a simple message" do
129
- expect(subject).to match(value)
223
+ expect(pattern).to match(message)
130
224
  end
131
225
 
132
226
  it "generates the nagios_type field" do
133
- expect(grok).to include("nagios_type" => "SERVICE ALERT")
227
+ if ecs_compatibility?
228
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("type" => 'SERVICE ALERT')))
229
+ else
230
+ expect(grok).to include("nagios_type" => "SERVICE ALERT")
231
+ end
134
232
  end
135
233
 
136
234
  it "generates the nagios_epoch field" do
137
- expect(grok).to include("nagios_epoch" => "1427925689")
235
+ if ecs_compatibility?
236
+ expect(grok).to include("timestamp" => "1427925689")
237
+ else
238
+ expect(grok).to include("nagios_epoch" => "1427925689")
239
+ end
138
240
  end
139
241
 
140
- it "generates the nagios_hostname field" do
141
- expect(grok).to include("nagios_hostname" => "varnish")
242
+ it "generates the hostname field" do
243
+ if ecs_compatibility?
244
+ expect(grok).to include("host" => { "hostname" => "varnish" })
245
+ else
246
+ expect(grok).to include("nagios_hostname" => "varnish")
247
+ end
142
248
  end
143
249
 
144
- it "generates the nagios_service field" do
145
- expect(grok).to include("nagios_service" => "Varnish Backend Connections")
250
+ it "generates the service field" do
251
+ if ecs_compatibility?
252
+ expect(grok).to include("service" => hash_including("name" => 'Varnish Backend Connections'))
253
+ else
254
+ expect(grok).to include("nagios_service" => "Varnish Backend Connections")
255
+ end
146
256
  end
147
257
 
148
258
  it "generates the nagios_state field" do
149
- expect(grok).to include("nagios_state" => "CRITICAL")
259
+ if ecs_compatibility?
260
+ expect(grok).to include("service" => hash_including("state" => "CRITICAL"))
261
+ else
262
+ expect(grok).to include("nagios_state" => "CRITICAL")
263
+ end
150
264
  end
151
265
 
152
266
  it "generates the nagios_statelevel field" do
153
- expect(grok).to include("nagios_statelevel" => "SOFT")
267
+ if ecs_compatibility?
268
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("state_type" => "SOFT")))
269
+ else
270
+ expect(grok).to include("nagios_statelevel" => "SOFT")
271
+ end
272
+ end
273
+
274
+ it "generates the nagios_attempt field" do
275
+ if ecs_compatibility?
276
+ pending "TODO: are we hitting a grok bug here ?!?"
277
+ # [nagios][log][attempt]:int is clearly there (changing to :float gets this passing)
278
+ # ... but in this particular case we still get the raw "1" string back
279
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("attempt" => 1)))
280
+ else
281
+ expect(grok).to include("nagios_attempt" => "1")
282
+ end
154
283
  end
155
284
 
156
285
  it "generates the nagios_message field" do
157
- expect(grok).to include("nagios_message" => "Current value: 154.0, warn threshold: 10.0, crit threshold: 20.0")
286
+ if ecs_compatibility?
287
+ expect(grok['message'].last).to eql "Current value: 154.0, warn threshold: 10.0, crit threshold: 20.0"
288
+ else
289
+ expect(grok).to include("nagios_message" => "Current value: 154.0, warn threshold: 10.0, crit threshold: 20.0")
290
+ end
158
291
  end
159
292
 
160
293
  end
161
294
 
162
- describe "NAGIOSLOGLINE - SERVICE NOTIFICATION" do
295
+ describe_pattern "NAGIOSLOGLINE - SERVICE NOTIFICATION", [ 'legacy', 'ecs-v1' ] do
163
296
 
164
- let(:value) { "[1427950229] SERVICE NOTIFICATION: nagiosadmin;varnish;Varnish Backend Connections;CRITICAL;notify-service-by-email;Current value: 337.0, warn threshold: 10.0, crit threshold: 20.0" }
165
- let(:grok) { grok_match(subject, value) }
297
+ let(:message) { "[1427950229] SERVICE NOTIFICATION: nagiosadmin;varnish;Varnish Backend Connections;CRITICAL;notify-service-by-email;Current value: 337.0, warn threshold: 10.0, crit threshold: 20.0" }
166
298
 
167
299
  it "a pattern pass the grok expression" do
168
300
  expect(grok).to pass
169
301
  end
170
302
 
171
303
  it "matches a simple message" do
172
- expect(subject).to match(value)
304
+ expect(pattern).to match(message)
173
305
  end
174
306
 
175
307
  it "generates the nagios_type field" do
176
- expect(grok).to include("nagios_type" => "SERVICE NOTIFICATION")
308
+ if ecs_compatibility?
309
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("type" => 'SERVICE NOTIFICATION')))
310
+ else
311
+ expect(grok).to include("nagios_type" => "SERVICE NOTIFICATION")
312
+ end
177
313
  end
178
314
 
179
315
  it "generates the nagios_epoch field" do
180
- expect(grok).to include("nagios_epoch" => "1427950229")
316
+ if ecs_compatibility?
317
+ expect(grok).to include("timestamp" => "1427950229")
318
+ else
319
+ expect(grok).to include("nagios_epoch" => "1427950229")
320
+ end
181
321
  end
182
322
 
183
323
  it "generates the nagios_notifyname field" do
184
- expect(grok).to include("nagios_notifyname" => "nagiosadmin")
324
+ if ecs_compatibility?
325
+ expect(grok).to include("user" => { "name" => "nagiosadmin" }) # Nagios contact's contact_name
326
+ else
327
+ expect(grok).to include("nagios_notifyname" => "nagiosadmin")
328
+ end
185
329
  end
186
330
 
187
- it "generates the nagios_hostname field" do
188
- expect(grok).to include("nagios_hostname" => "varnish")
331
+ it "generates the hostname field" do
332
+ if ecs_compatibility?
333
+ expect(grok).to include("host" => { "hostname" => "varnish" })
334
+ else
335
+ expect(grok).to include("nagios_hostname" => "varnish")
336
+ end
189
337
  end
190
338
 
191
- it "generates the nagios_service field" do
192
- expect(grok).to include("nagios_service" => "Varnish Backend Connections")
339
+ it "generates the service field" do
340
+ if ecs_compatibility?
341
+ expect(grok).to include("service" => hash_including("name" => 'Varnish Backend Connections'))
342
+ else
343
+ expect(grok).to include("nagios_service" => "Varnish Backend Connections")
344
+ end
193
345
  end
194
346
 
195
347
  it "generates the nagios_state field" do
196
- expect(grok).to include("nagios_state" => "CRITICAL")
348
+ if ecs_compatibility?
349
+ expect(grok).to include("service" => hash_including("state" => "CRITICAL"))
350
+ else
351
+ expect(grok).to include("nagios_state" => "CRITICAL")
352
+ end
197
353
  end
198
354
 
199
355
  it "generates the nagios_contact field" do
200
- expect(grok).to include("nagios_contact" => "notify-service-by-email")
356
+ if ecs_compatibility?
357
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("notification_command" => "notify-service-by-email")))
358
+ else
359
+ expect(grok).to include("nagios_contact" => "notify-service-by-email")
360
+ end
201
361
  end
202
362
 
203
363
  it "generates the nagios_message field" do
204
- expect(grok).to include("nagios_message" => "Current value: 337.0, warn threshold: 10.0, crit threshold: 20.0")
364
+ if ecs_compatibility?
365
+ expect(grok['message'].last).to eql "Current value: 337.0, warn threshold: 10.0, crit threshold: 20.0"
366
+ else
367
+ expect(grok).to include("nagios_message" => "Current value: 337.0, warn threshold: 10.0, crit threshold: 20.0")
368
+ end
205
369
  end
206
370
 
207
371
  end
208
372
 
209
373
 
210
- describe "NAGIOSLOGLINE - HOST NOTIFICATION" do
374
+ describe_pattern "NAGIOSLOGLINE - HOST NOTIFICATION", [ 'legacy', 'ecs-v1' ] do
211
375
 
212
- let(:value) { "[1429878690] HOST NOTIFICATION: nagiosadmin;nagioshost;DOWN;notify-host-by-email;CRITICAL - Socket timeout after 10 seconds" }
213
- let(:grok) { grok_match(subject, value) }
214
-
215
- it "a pattern pass the grok expression" do
216
- expect(grok).to pass
217
- end
376
+ let(:message) { "[1429878690] HOST NOTIFICATION: nagiosadmin;127.0.0.1;DOWN;host-notify-by-email;CRITICAL - Socket timeout after 10 seconds" }
218
377
 
219
378
  it "matches a simple message" do
220
- expect(subject).to match(value)
379
+ expect(pattern).to match(message)
221
380
  end
222
381
 
223
382
  it "generates the nagios_type field" do
224
- expect(grok).to include("nagios_type" => "HOST NOTIFICATION")
383
+ if ecs_compatibility?
384
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("type" => "HOST NOTIFICATION")))
385
+ else
386
+ expect(grok).to include("nagios_type" => "HOST NOTIFICATION")
387
+ end
225
388
  end
226
389
 
227
390
  it "generates the nagios_epoch field" do
228
- expect(grok).to include("nagios_epoch" => "1429878690")
391
+ expect(grok).to include("nagios_epoch" => "1429878690") unless ecs_compatibility?
229
392
  end
230
393
 
231
394
  it "generates the nagios_notifyname field" do
232
- expect(grok).to include("nagios_notifyname" => "nagiosadmin")
395
+ if ecs_compatibility?
396
+ expect(grok).to include("user" => { "name" => "nagiosadmin" }) # Nagios contact's contact_name
397
+ else
398
+ expect(grok).to include("nagios_notifyname" => "nagiosadmin")
399
+ end
233
400
  end
234
401
 
235
402
  it "generates the nagios_hostname field" do
236
- expect(grok).to include("nagios_hostname" => "nagioshost")
403
+ if ecs_compatibility?
404
+ expect(grok).to include("host" => { "hostname" => "127.0.0.1" })
405
+ else
406
+ expect(grok).to include("nagios_hostname" => "127.0.0.1")
407
+ end
237
408
  end
238
409
 
239
410
  it "generates the nagios_contact field" do
240
- expect(grok).to include("nagios_contact" => "notify-host-by-email")
411
+ if ecs_compatibility?
412
+ expect(grok).to include("nagios" => hash_including("log" => hash_including("notification_command" => "host-notify-by-email")))
413
+ else
414
+ expect(grok).to include("nagios_contact" => "host-notify-by-email")
415
+ end
241
416
  end
242
417
 
243
418
  it "generates the nagios_message field" do
244
- expect(grok).to include("nagios_message" => "CRITICAL - Socket timeout after 10 seconds")
419
+ if ecs_compatibility?
420
+ expect(grok['message'].last).to eql "CRITICAL - Socket timeout after 10 seconds"
421
+ else
422
+ expect(grok).to include("nagios_message" => "CRITICAL - Socket timeout after 10 seconds")
423
+ end
245
424
  end
246
425
 
247
426
  end
427
+
428
+ describe_pattern "NAGIOSLOGLINE - SCHEDULE_HOST_DOWNTIME", [ 'legacy', 'ecs-v1' ] do
429
+
430
+ let(:message) { "[1334609999] EXTERNAL COMMAND: SCHEDULE_HOST_DOWNTIME;sputnik;1334665800;1334553600;1;0;120;nagiosadmin;test;" }
431
+
432
+ it "matches" do
433
+ if ecs_compatibility?
434
+ expect(grok).to include(
435
+ "host" => { "hostname" => "sputnik" },
436
+ "nagios" => { "log" => {
437
+ "type" => "EXTERNAL COMMAND",
438
+ "command" => "SCHEDULE_HOST_DOWNTIME",
439
+ "start_time" => "1334665800",
440
+ "end_time" => "1334553600",
441
+ "fixed" => '1',
442
+ "trigger_id" => '0',
443
+ "duration" => 120,
444
+
445
+ }},
446
+ "user" => { "name" => 'nagiosadmin' },
447
+ "message" => message
448
+ )
449
+ else
450
+ expect(grok).to include(
451
+ "nagios_epoch"=>"1334609999",
452
+ "nagios_type"=>"EXTERNAL COMMAND",
453
+ "nagios_command"=>"SCHEDULE_HOST_DOWNTIME",
454
+ "nagios_hostname"=>"sputnik",
455
+ "nagios_duration"=>"120",
456
+ "nagios_fixed"=>"1",
457
+ "nagios_trigger_id"=>"0",
458
+ "nagios_start_time"=>"1334665800",
459
+ "nagios_end_time"=>"1334553600",
460
+ "author"=>"nagiosadmin"
461
+ )
462
+ end
463
+ end
464
+ end