logstash-patterns-core 4.1.0 → 4.3.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.
Files changed (78) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +118 -0
  3. data/CONTRIBUTORS +1 -0
  4. data/Gemfile +8 -1
  5. data/LICENSE +199 -10
  6. data/README.md +12 -19
  7. data/lib/logstash/patterns/core.rb +11 -3
  8. data/logstash-patterns-core.gemspec +1 -1
  9. data/patterns/ecs-v1/aws +28 -0
  10. data/patterns/ecs-v1/bacula +53 -0
  11. data/patterns/ecs-v1/bind +13 -0
  12. data/patterns/ecs-v1/bro +30 -0
  13. data/patterns/ecs-v1/exim +26 -0
  14. data/patterns/ecs-v1/firewalls +111 -0
  15. data/patterns/ecs-v1/grok-patterns +95 -0
  16. data/patterns/ecs-v1/haproxy +40 -0
  17. data/patterns/ecs-v1/httpd +17 -0
  18. data/patterns/ecs-v1/java +34 -0
  19. data/patterns/ecs-v1/junos +13 -0
  20. data/patterns/ecs-v1/linux-syslog +16 -0
  21. data/patterns/{maven → ecs-v1/maven} +0 -0
  22. data/patterns/ecs-v1/mcollective +4 -0
  23. data/patterns/ecs-v1/mongodb +7 -0
  24. data/patterns/ecs-v1/nagios +124 -0
  25. data/patterns/ecs-v1/postgresql +2 -0
  26. data/patterns/ecs-v1/rails +13 -0
  27. data/patterns/ecs-v1/redis +3 -0
  28. data/patterns/ecs-v1/ruby +2 -0
  29. data/patterns/ecs-v1/squid +6 -0
  30. data/patterns/ecs-v1/zeek +33 -0
  31. data/patterns/{aws → legacy/aws} +1 -1
  32. data/patterns/{bacula → legacy/bacula} +5 -5
  33. data/patterns/legacy/bind +3 -0
  34. data/patterns/{bro → legacy/bro} +0 -0
  35. data/patterns/{exim → legacy/exim} +8 -2
  36. data/patterns/{firewalls → legacy/firewalls} +2 -2
  37. data/patterns/{grok-patterns → legacy/grok-patterns} +5 -5
  38. data/patterns/{haproxy → legacy/haproxy} +1 -1
  39. data/patterns/{httpd → legacy/httpd} +3 -3
  40. data/patterns/{java → legacy/java} +1 -3
  41. data/patterns/{junos → legacy/junos} +0 -0
  42. data/patterns/{linux-syslog → legacy/linux-syslog} +0 -0
  43. data/patterns/legacy/maven +1 -0
  44. data/patterns/{mcollective → legacy/mcollective} +0 -0
  45. data/patterns/{mcollective-patterns → legacy/mcollective-patterns} +0 -0
  46. data/patterns/{mongodb → legacy/mongodb} +0 -0
  47. data/patterns/{nagios → legacy/nagios} +1 -1
  48. data/patterns/{postgresql → legacy/postgresql} +0 -0
  49. data/patterns/{rails → legacy/rails} +0 -0
  50. data/patterns/{redis → legacy/redis} +0 -0
  51. data/patterns/{ruby → legacy/ruby} +0 -0
  52. data/patterns/legacy/squid +4 -0
  53. data/spec/patterns/aws_spec.rb +395 -0
  54. data/spec/patterns/bacula_spec.rb +367 -0
  55. data/spec/patterns/bind_spec.rb +78 -0
  56. data/spec/patterns/bro_spec.rb +613 -0
  57. data/spec/patterns/core_spec.rb +271 -6
  58. data/spec/patterns/exim_spec.rb +201 -0
  59. data/spec/patterns/firewalls_spec.rb +707 -66
  60. data/spec/patterns/haproxy_spec.rb +253 -28
  61. data/spec/patterns/httpd_spec.rb +255 -77
  62. data/spec/patterns/java_spec.rb +375 -0
  63. data/spec/patterns/junos_spec.rb +101 -0
  64. data/spec/patterns/mcollective_spec.rb +35 -0
  65. data/spec/patterns/mongodb_spec.rb +170 -33
  66. data/spec/patterns/nagios_spec.rb +299 -78
  67. data/spec/patterns/netscreen_spec.rb +123 -0
  68. data/spec/patterns/rails3_spec.rb +87 -29
  69. data/spec/patterns/redis_spec.rb +157 -121
  70. data/spec/patterns/shorewall_spec.rb +85 -74
  71. data/spec/patterns/squid_spec.rb +139 -0
  72. data/spec/patterns/syslog_spec.rb +266 -22
  73. data/spec/spec_helper.rb +83 -5
  74. metadata +70 -30
  75. data/patterns/bind +0 -3
  76. data/patterns/squid +0 -4
  77. data/spec/patterns/bro.rb +0 -126
  78. 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,242 +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) }
171
+ let(:message) { "[1427925600] TIMEPERIOD TRANSITION: 24X7;-1;1" }
87
172
 
88
- it "a pattern pass the grok expression" do
89
- expect(grok).to pass
90
- end
91
-
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
195
+ end
196
+
197
+ it "generates the period from/to fields" do
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
106
203
  end
107
204
 
108
205
  # Regression test for but fixed in Nagios patterns #30
109
206
  it "doesn't end in a semi-colon" do
110
- 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(";")
111
210
  end
112
211
 
113
212
  end
114
213
 
115
- describe "NAGIOSLOGLINE - SERVICE ALERT" do
214
+ describe_pattern "NAGIOSLOGLINE - SERVICE ALERT", [ 'legacy', 'ecs-v1' ] do
116
215
 
117
- let(:value) { "[1427925689] SERVICE ALERT: varnish;Varnish Backend Connections;CRITICAL;SOFT;1;Current value: 154.0, warn threshold: 10.0, crit threshold: 20.0" }
118
- 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" }
119
217
 
120
218
  it "a pattern pass the grok expression" do
121
219
  expect(grok).to pass
122
220
  end
123
221
 
124
222
  it "matches a simple message" do
125
- expect(subject).to match(value)
223
+ expect(pattern).to match(message)
126
224
  end
127
225
 
128
226
  it "generates the nagios_type field" do
129
- 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
130
232
  end
131
233
 
132
234
  it "generates the nagios_epoch field" do
133
- 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
134
240
  end
135
241
 
136
- it "generates the nagios_hostname field" do
137
- 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
138
248
  end
139
249
 
140
- it "generates the nagios_service field" do
141
- 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
142
256
  end
143
257
 
144
258
  it "generates the nagios_state field" do
145
- 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
146
264
  end
147
265
 
148
266
  it "generates the nagios_statelevel field" do
149
- 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
150
283
  end
151
284
 
152
285
  it "generates the nagios_message field" do
153
- 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
154
291
  end
155
292
 
156
293
  end
157
294
 
158
- describe "NAGIOSLOGLINE - SERVICE NOTIFICATION" do
295
+ describe_pattern "NAGIOSLOGLINE - SERVICE NOTIFICATION", [ 'legacy', 'ecs-v1' ] do
159
296
 
160
- 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" }
161
- 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" }
162
298
 
163
299
  it "a pattern pass the grok expression" do
164
300
  expect(grok).to pass
165
301
  end
166
302
 
167
303
  it "matches a simple message" do
168
- expect(subject).to match(value)
304
+ expect(pattern).to match(message)
169
305
  end
170
306
 
171
307
  it "generates the nagios_type field" do
172
- 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
173
313
  end
174
314
 
175
315
  it "generates the nagios_epoch field" do
176
- 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
177
321
  end
178
322
 
179
323
  it "generates the nagios_notifyname field" do
180
- 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
181
329
  end
182
330
 
183
- it "generates the nagios_hostname field" do
184
- 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
185
337
  end
186
338
 
187
- it "generates the nagios_service field" do
188
- 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
189
345
  end
190
346
 
191
347
  it "generates the nagios_state field" do
192
- 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
193
353
  end
194
354
 
195
355
  it "generates the nagios_contact field" do
196
- 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
197
361
  end
198
362
 
199
363
  it "generates the nagios_message field" do
200
- 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
201
369
  end
202
370
 
203
371
  end
204
372
 
205
373
 
206
- describe "NAGIOSLOGLINE - HOST NOTIFICATION" do
374
+ describe_pattern "NAGIOSLOGLINE - HOST NOTIFICATION", [ 'legacy', 'ecs-v1' ] do
207
375
 
208
- let(:value) { "[1429878690] HOST NOTIFICATION: nagiosadmin;nagioshost;DOWN;notify-host-by-email;CRITICAL - Socket timeout after 10 seconds" }
209
- let(:grok) { grok_match(subject, value) }
210
-
211
- it "a pattern pass the grok expression" do
212
- expect(grok).to pass
213
- end
376
+ let(:message) { "[1429878690] HOST NOTIFICATION: nagiosadmin;127.0.0.1;DOWN;host-notify-by-email;CRITICAL - Socket timeout after 10 seconds" }
214
377
 
215
378
  it "matches a simple message" do
216
- expect(subject).to match(value)
379
+ expect(pattern).to match(message)
217
380
  end
218
381
 
219
382
  it "generates the nagios_type field" do
220
- 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
221
388
  end
222
389
 
223
390
  it "generates the nagios_epoch field" do
224
- expect(grok).to include("nagios_epoch" => "1429878690")
391
+ expect(grok).to include("nagios_epoch" => "1429878690") unless ecs_compatibility?
225
392
  end
226
393
 
227
394
  it "generates the nagios_notifyname field" do
228
- 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
229
400
  end
230
401
 
231
402
  it "generates the nagios_hostname field" do
232
- 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
233
408
  end
234
409
 
235
410
  it "generates the nagios_contact field" do
236
- 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
237
416
  end
238
417
 
239
418
  it "generates the nagios_message field" do
240
- 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
241
424
  end
242
425
 
243
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