logstash-patterns-core 4.1.2 → 4.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +119 -0
  3. data/Gemfile +8 -1
  4. data/LICENSE +199 -10
  5. data/README.md +12 -19
  6. data/lib/logstash/patterns/core.rb +11 -3
  7. data/logstash-patterns-core.gemspec +1 -1
  8. data/patterns/ecs-v1/aws +28 -0
  9. data/patterns/ecs-v1/bacula +53 -0
  10. data/patterns/ecs-v1/bind +13 -0
  11. data/patterns/ecs-v1/bro +30 -0
  12. data/patterns/ecs-v1/exim +26 -0
  13. data/patterns/ecs-v1/firewalls +111 -0
  14. data/patterns/ecs-v1/grok-patterns +95 -0
  15. data/patterns/ecs-v1/haproxy +40 -0
  16. data/patterns/ecs-v1/httpd +17 -0
  17. data/patterns/ecs-v1/java +34 -0
  18. data/patterns/ecs-v1/junos +13 -0
  19. data/patterns/ecs-v1/linux-syslog +16 -0
  20. data/patterns/{maven → ecs-v1/maven} +0 -0
  21. data/patterns/ecs-v1/mcollective +4 -0
  22. data/patterns/ecs-v1/mongodb +7 -0
  23. data/patterns/ecs-v1/nagios +124 -0
  24. data/patterns/ecs-v1/postgresql +2 -0
  25. data/patterns/ecs-v1/rails +13 -0
  26. data/patterns/ecs-v1/redis +3 -0
  27. data/patterns/ecs-v1/ruby +2 -0
  28. data/patterns/ecs-v1/squid +6 -0
  29. data/patterns/ecs-v1/zeek +33 -0
  30. data/patterns/{aws → legacy/aws} +1 -1
  31. data/patterns/{bacula → legacy/bacula} +5 -5
  32. data/patterns/legacy/bind +3 -0
  33. data/patterns/{bro → legacy/bro} +0 -0
  34. data/patterns/{exim → legacy/exim} +8 -2
  35. data/patterns/{firewalls → legacy/firewalls} +2 -2
  36. data/patterns/{grok-patterns → legacy/grok-patterns} +4 -4
  37. data/patterns/{haproxy → legacy/haproxy} +1 -1
  38. data/patterns/{httpd → legacy/httpd} +2 -2
  39. data/patterns/{java → legacy/java} +1 -3
  40. data/patterns/{junos → legacy/junos} +0 -0
  41. data/patterns/{linux-syslog → legacy/linux-syslog} +0 -0
  42. data/patterns/legacy/maven +1 -0
  43. data/patterns/{mcollective → legacy/mcollective} +0 -0
  44. data/patterns/{mcollective-patterns → legacy/mcollective-patterns} +0 -0
  45. data/patterns/{mongodb → legacy/mongodb} +0 -0
  46. data/patterns/{nagios → legacy/nagios} +1 -1
  47. data/patterns/{postgresql → legacy/postgresql} +0 -0
  48. data/patterns/{rails → legacy/rails} +0 -0
  49. data/patterns/{redis → legacy/redis} +0 -0
  50. data/patterns/{ruby → legacy/ruby} +0 -0
  51. data/patterns/legacy/squid +4 -0
  52. data/spec/patterns/aws_spec.rb +395 -0
  53. data/spec/patterns/bacula_spec.rb +367 -0
  54. data/spec/patterns/bind_spec.rb +92 -0
  55. data/spec/patterns/bro_spec.rb +613 -0
  56. data/spec/patterns/core_spec.rb +260 -15
  57. data/spec/patterns/exim_spec.rb +201 -0
  58. data/spec/patterns/firewalls_spec.rb +707 -66
  59. data/spec/patterns/haproxy_spec.rb +253 -28
  60. data/spec/patterns/httpd_spec.rb +248 -86
  61. data/spec/patterns/java_spec.rb +375 -0
  62. data/spec/patterns/junos_spec.rb +101 -0
  63. data/spec/patterns/mcollective_spec.rb +35 -0
  64. data/spec/patterns/mongodb_spec.rb +170 -33
  65. data/spec/patterns/nagios_spec.rb +299 -78
  66. data/spec/patterns/netscreen_spec.rb +123 -0
  67. data/spec/patterns/rails3_spec.rb +87 -29
  68. data/spec/patterns/redis_spec.rb +216 -140
  69. data/spec/patterns/shorewall_spec.rb +85 -74
  70. data/spec/patterns/squid_spec.rb +139 -0
  71. data/spec/patterns/syslog_spec.rb +266 -22
  72. data/spec/spec_helper.rb +83 -5
  73. metadata +70 -31
  74. data/patterns/bind +0 -3
  75. data/patterns/squid +0 -4
  76. data/spec/patterns/bro.rb +0 -126
  77. data/spec/patterns/s3_spec.rb +0 -173
@@ -2,55 +2,113 @@
2
2
  require "spec_helper"
3
3
  require "logstash/patterns/core"
4
4
 
5
- describe "RAILS" do
6
- let(:rails3_pattern) { "RAILS3" }
5
+ describe_pattern "RAILS3", ['legacy', 'ecs-v1'] do
7
6
 
8
- context "Parsing RAILS3 single-line log from raw log file" do
7
+ context "single-line log" do
9
8
 
10
- let(:value) { 'Started POST "/api/v3/internal/allowed" for 127.0.0.1 at 2015-08-05 11:37:01 +0200' }
11
-
12
- subject { grok_match(rails3_pattern, value) }
9
+ let(:message) { 'Started POST "/api/v3/internal/allowed" for 127.0.0.1 at 2015-08-05 11:37:01 +0200' }
13
10
 
14
11
  # Started
15
- it { should include("verb" => "POST" ) }
16
- it { should include("request" => "/api/v3/internal/allowed" ) }
12
+ it do
13
+ if ecs_compatibility?
14
+ should include("http" => hash_including("request" => { "method" => "POST" }))
15
+ else
16
+ should include("verb" => "POST")
17
+ end
18
+ end
19
+
20
+ it do
21
+ if ecs_compatibility?
22
+ else
23
+ should include("request" => "/api/v3/internal/allowed")
24
+ end
25
+ end
17
26
  # for
18
- it { should include("clientip" => "127.0.0.1" ) }
27
+ it do
28
+ if ecs_compatibility?
29
+ should include("source" => { "address" => "127.0.0.1" })
30
+ else
31
+ should include("clientip" => "127.0.0.1")
32
+ end
33
+ end
19
34
  # at
20
35
  it { should include("timestamp" => "2015-08-05 11:37:01 +0200" ) }
21
36
  end
22
37
 
23
- context "Parsing RAILS3 multi-line log from raw log file" do
38
+ context "multi-line log" do
24
39
 
25
- let(:value) { 'Started GET "/puppet/postfix/notes?target_id=162&target_type=issue&last_fetched_at=1438695732" for 127.0.0.1 at 2015-08-05 07:40:22 +0200
40
+ let(:message) { 'Started GET "/puppet/postfix/notes?target_id=162&target_type=issue&last_fetched_at=1438695732" for 127.0.0.1 at 2015-08-05 07:40:22 +0200
26
41
  Processing by Projects::NotesController#index as JSON
27
42
  Parameters: {"target_id"=>"162", "target_type"=>"issue", "last_fetched_at"=>"1438695732", "namespace_id"=>"puppet", "project_id"=>"postfix"}
28
- Completed 200 OK in 640ms (Views: 1.7ms | ActiveRecord: 91.0ms)' }
29
- subject { grok_match(rails3_pattern, value) }
43
+ Completed 200 OK in 640ms (Views: 1.7ms | ActiveRecord: 91.0ms)' }
30
44
 
31
45
  # started
32
- it { should include("verb" => "GET" ) }
33
- it { should include("request" => "/puppet/postfix/notes?target_id=162&target_type=issue&last_fetched_at=1438695732" ) }
46
+ it do
47
+ if ecs_compatibility?
48
+ should include("http" => hash_including("request" => { "method" => "GET" }))
49
+ else
50
+ should include("verb" => "GET")
51
+ end
52
+ end
53
+
54
+ it do
55
+ if ecs_compatibility?
56
+ should include("url" => {"original"=>"/puppet/postfix/notes?target_id=162&target_type=issue&last_fetched_at=1438695732"})
57
+ else
58
+ should include("request" => "/puppet/postfix/notes?target_id=162&target_type=issue&last_fetched_at=1438695732" )
59
+ end
60
+ end
34
61
  # for
35
- it { should include("clientip" => "127.0.0.1" ) }
62
+ it do
63
+ if ecs_compatibility?
64
+ should include("source" => { "address" => "127.0.0.1" })
65
+ else
66
+ should include("clientip" => "127.0.0.1")
67
+ end
68
+ end
36
69
  # at
37
- it { should include("timestamp" => "2015-08-05 07:40:22 +0200" ) }
70
+ it { should include("timestamp" => "2015-08-05 07:40:22 +0200") }
38
71
  # Processing by
39
- it { should include("controller" => "Projects::NotesController" ) }
40
- it { should include("action" => "index" ) }
72
+ it do
73
+ if ecs_compatibility?
74
+ should include("rails" => hash_including("controller" => { "class"=>"Projects::NotesController", "action"=>"index" }))
75
+ else
76
+ should include("controller" => "Projects::NotesController")
77
+ should include("action" => "index")
78
+ end
79
+ end
41
80
  # as
42
- it { should include("format" => "JSON" ) }
81
+ it do
82
+ if ecs_compatibility?
83
+ should include("rails" => hash_including("request" => hash_including("format" => 'JSON')))
84
+ else
85
+ should include("format" => "JSON" )
86
+ end
87
+ end
43
88
  # Parameters
44
- it { should include("params" => '"target_id"=>"162", "target_type"=>"issue", "last_fetched_at"=>"1438695732", "namespace_id"=>"puppet", "project_id"=>"postfix"' ) }
89
+ it do
90
+ params = '"target_id"=>"162", "target_type"=>"issue", "last_fetched_at"=>"1438695732", "namespace_id"=>"puppet", "project_id"=>"postfix"'
91
+ if ecs_compatibility?
92
+ should include("rails" => hash_including("request" => hash_including("params" => params)))
93
+ else
94
+ should include("params" => params)
95
+ end
96
+ end
45
97
  # Completed
46
- it { should include("response" => "200" ) }
98
+ it do
99
+ if ecs_compatibility?
100
+ should include("http" => hash_including("response" => { "status_code" => 200 }))
101
+ else
102
+ should include("response" => "200" )
103
+ end
104
+ end
47
105
  # in
48
- it { should include("totalms" => "640" ) }
49
- # (Views:
50
- it { should include("viewms" => "1.7" ) }
51
- # | ActiveRecord:
52
- it { should include("activerecordms" => "91.0" ) }
53
-
106
+ it do
107
+ if ecs_compatibility?
108
+ should include("rails" => hash_including("request" => hash_including("duration" => { "total" => 640.0, "view" => 1.7, "active_record" => 91.0 })))
109
+ else
110
+ should include("totalms" => "640", "viewms" => "1.7", "activerecordms" => "91.0")
111
+ end
112
+ end
54
113
  end
55
-
56
114
  end
@@ -2,170 +2,246 @@
2
2
  require "spec_helper"
3
3
  require "logstash/patterns/core"
4
4
 
5
- describe "REDISTIMESTAMP" do
5
+ describe_pattern 'REDISTIMESTAMP', [ 'legacy', 'ecs-v1' ] do
6
6
 
7
- let(:value) { '14 Nov 07:01:22.119'}
8
- let(:pattern) { "REDISTIMESTAMP" }
7
+ let(:message) { '14 Nov 07:01:22.119'}
9
8
 
10
9
  it "a pattern pass the grok expression" do
11
- expect(grok_match(pattern, value)).to pass
10
+ expect(grok_match(pattern, message)).to pass
12
11
  end
13
12
 
14
13
  end
15
14
 
16
- describe "REDISLOG" do
15
+ describe_pattern 'REDISLOG', [ 'legacy', 'ecs-v1' ] do
17
16
 
18
- let(:value) { "[4018] 14 Nov 07:01:22.119 * Background saving terminated with success" }
19
- let(:pattern) { "REDISLOG" }
20
- let(:grok) { grok_match(pattern, value) }
17
+ let(:message) { "[4018] 14 Nov 07:01:22.119 * Background saving terminated with success" }
21
18
 
22
19
  it "a pattern pass the grok expression" do
23
20
  expect(grok).to pass
24
21
  end
25
22
 
26
23
  it "generates the pid field" do
27
- expect(grok).to include("pid" => "4018")
24
+ if ecs_compatibility?
25
+ expect(grok).to include("process" => { 'pid' => 4018 })
26
+ else
27
+ expect(grok).to include("pid" => "4018")
28
+ end
28
29
  end
29
30
 
30
31
  end
31
32
 
33
+ describe_pattern 'REDISMONLOG', [ 'legacy', 'ecs-v1' ] do
34
+
35
+ context "simple command" do
36
+
37
+ let(:message) { "1470637867.953466 [0 195.168.1.1:52500] \"info\"" }
38
+
39
+ it "a pattern pass the grok expression" do
40
+ expect(grok).to pass
41
+ end
42
+
43
+ it "generates the timestamp field" do
44
+ expect(grok).to include("timestamp" => "1470637867.953466")
45
+ end
46
+
47
+ it "generates the database field" do
48
+ if ecs_compatibility?
49
+ expect(grok).to include("redis" => hash_including('database' => { 'id' => '0' }))
50
+ else
51
+ expect(grok).to include("database" => "0")
52
+ end
53
+ end
54
+
55
+ it "generates the client field" do
56
+ if ecs_compatibility?
57
+ expect(grok).to include("client" => hash_including('ip' => '195.168.1.1'))
58
+ else
59
+ expect(grok).to include("client" => "195.168.1.1")
60
+ end
61
+ end
62
+
63
+ it "generates the port field" do
64
+ if ecs_compatibility?
65
+ expect(grok).to include("client" => hash_including('port' => 52500))
66
+ else
67
+ expect(grok).to include("port" => "52500")
68
+ end
69
+ end
70
+
71
+ it "generates the command field" do
72
+ if ecs_compatibility?
73
+ expect(grok).to include("redis" => hash_including('command' => { 'name' => 'info' }))
74
+ else
75
+ expect(grok).to include("command" => "info")
76
+ end
77
+ end
78
+
79
+ end
80
+
81
+ context "one param command" do
82
+
83
+ let(:message) { "1339518083.107412 [0 127.0.0.1:60866] \"keys\" \"*\"" }
84
+
85
+ it "a pattern pass the grok expression" do
86
+ expect(grok).to pass
87
+ end
88
+
89
+ it "generates the timestamp field" do
90
+ expect(grok).to include("timestamp" => "1339518083.107412")
91
+ end
92
+
93
+ it "generates the database field" do
94
+ if ecs_compatibility?
95
+ expect(grok).to include("redis" => hash_including('database' => { 'id' => '0' }))
96
+ else
97
+ expect(grok).to include("database" => "0")
98
+ end
99
+ end
100
+
101
+ it "generates the client field" do
102
+ if ecs_compatibility?
103
+ expect(grok).to include("client" => hash_including('ip' => '127.0.0.1'))
104
+ else
105
+ expect(grok).to include("client" => "127.0.0.1")
106
+ end
107
+ end
108
+
109
+ it "generates the port field" do
110
+ if ecs_compatibility?
111
+ expect(grok).to include("client" => hash_including('port' => 60866))
112
+ else
113
+ expect(grok).to include("port" => "60866")
114
+ end
115
+ end
116
+
117
+ it "generates the command field" do
118
+ if ecs_compatibility?
119
+ expect(grok).to include("redis" => hash_including('command' => hash_including('name' => 'keys')))
120
+ else
121
+ expect(grok).to include("command" => "keys")
122
+ end
123
+ end
124
+
125
+ it "generates the params field" do
126
+ if ecs_compatibility?
127
+ expect(grok).to include("redis" => hash_including('command' => hash_including('args' => '"*"')))
128
+ else
129
+ expect(grok).to include("params" => "\"*\"")
130
+ end
131
+ end
32
132
 
33
- describe "REDISMONLOG - SIMPLE COMMAND" do
34
-
35
- let(:value) { "1470637867.953466 [0 195.168.1.1:52500] \"info\"" }
36
- let(:pattern) { "REDISMONLOG" }
37
- let(:grok) { grok_match(pattern, value) }
38
-
39
- it "a pattern pass the grok expression" do
40
- expect(grok).to pass
41
- end
42
-
43
- it "generates the timestamp field" do
44
- expect(grok).to include("timestamp" => "1470637867.953466")
45
- end
46
-
47
- it "generates the database field" do
48
- expect(grok).to include("database" => "0")
49
- end
50
-
51
- it "generates the client field" do
52
- expect(grok).to include("client" => "195.168.1.1")
53
- end
54
-
55
- it "generates the port field" do
56
- expect(grok).to include("port" => "52500")
57
- end
58
-
59
- it "generates the command field" do
60
- expect(grok).to include("command" => "info")
61
- end
62
-
63
- end
64
-
65
- describe "REDISMONLOG - ONE PARAM COMMAND" do
66
-
67
- let(:value) { "1339518083.107412 [0 127.0.0.1:60866] \"keys\" \"*\"" }
68
- let(:pattern) { "REDISMONLOG" }
69
- let(:grok) { grok_match(pattern, value) }
70
-
71
- it "a pattern pass the grok expression" do
72
- expect(grok).to pass
73
- end
74
-
75
- it "generates the timestamp field" do
76
- expect(grok).to include("timestamp" => "1339518083.107412")
77
- end
78
-
79
- it "generates the database field" do
80
- expect(grok).to include("database" => "0")
81
- end
82
-
83
- it "generates the client field" do
84
- expect(grok).to include("client" => "127.0.0.1")
85
- end
86
-
87
- it "generates the port field" do
88
- expect(grok).to include("port" => "60866")
89
- end
90
-
91
- it "generates the command field" do
92
- expect(grok).to include("command" => "keys")
93
- end
94
-
95
- it "generates the params field" do
96
- expect(grok).to include("params" => "\"*\"")
97
133
  end
98
134
 
99
135
  end
100
136
 
101
- describe "REDISMONLOG - TWO PARAM COMMAND" do
137
+ describe_pattern "REDISMONLOG", [ 'legacy', 'ecs-v1' ] do
138
+
139
+ context 'two param command' do
140
+
141
+ let(:message) { "1470637925.186681 [0 127.0.0.1:39404] \"rpush\" \"my:special:key\" \"{\\\"data\\\":\"cdr\\\",\\\"payload\\\":\\\"json\\\"}\"" }
142
+
143
+ it "a pattern pass the grok expression" do
144
+ expect(grok).to pass
145
+ end
146
+
147
+ it "generates the timestamp field" do
148
+ expect(grok).to include("timestamp" => "1470637925.186681")
149
+ end
150
+
151
+ it "generates the database field" do
152
+ if ecs_compatibility?
153
+ expect(grok).to include("redis" => hash_including('database' => hash_including('id' => '0')))
154
+ else
155
+ expect(grok).to include("database" => "0")
156
+ end
157
+ end
158
+
159
+ it "generates the client field" do
160
+ if ecs_compatibility?
161
+ expect(grok).to include("client" => hash_including('ip' => '127.0.0.1'))
162
+ else
163
+ expect(grok).to include("client" => "127.0.0.1")
164
+ end
165
+ end
166
+
167
+ it "generates the port field" do
168
+ if ecs_compatibility?
169
+ expect(grok).to include("client" => hash_including('port' => 39404))
170
+ else
171
+ expect(grok).to include("port" => "39404")
172
+ end
173
+ end
174
+
175
+ it "generates the command field" do
176
+ if ecs_compatibility?
177
+ expect(grok).to include("redis" => hash_including('command' => hash_including('name' => 'rpush')))
178
+ else
179
+ expect(grok).to include("command" => "rpush")
180
+ end
181
+ end
182
+
183
+ it "generates the params field" do
184
+ if ecs_compatibility?
185
+ expect(grok).to include("redis" => hash_including('command' => hash_including('args' => "\"my:special:key\" \"{\\\"data\\\":\"cdr\\\",\\\"payload\\\":\\\"json\\\"}\"")))
186
+ else
187
+ expect(grok).to include("params" => "\"my:special:key\" \"{\\\"data\\\":\"cdr\\\",\\\"payload\\\":\\\"json\\\"}\"")
188
+ end
189
+ end
190
+
191
+ end
192
+
193
+ context "variadic command" do
194
+
195
+ let(:message) { "1470637875.777457 [15 195.168.1.1:52500] \"intentionally\" \"broken\" \"variadic\" \"log\" \"entry\"" }
196
+
197
+ it "a pattern pass the grok expression" do
198
+ expect(grok).to pass
199
+ end
200
+
201
+ it "generates the timestamp field" do
202
+ expect(grok).to include("timestamp" => "1470637875.777457")
203
+ end
204
+
205
+ it "generates the database field" do
206
+ if ecs_compatibility?
207
+ expect(grok).to include("redis" => hash_including('database' => hash_including('id' => '15')))
208
+ else
209
+ expect(grok).to include("database" => "15")
210
+ end
211
+ end
212
+
213
+ it "generates the client field" do
214
+ if ecs_compatibility?
215
+ expect(grok).to include("client" => hash_including('ip' => '195.168.1.1'))
216
+ else
217
+ expect(grok).to include("client" => "195.168.1.1")
218
+ end
219
+ end
220
+
221
+ it "generates the port field" do
222
+ if ecs_compatibility?
223
+ expect(grok).to include("client" => hash_including('port' => 52500))
224
+ else
225
+ expect(grok).to include("port" => "52500")
226
+ end
227
+ end
228
+
229
+ it "generates the command field" do
230
+ if ecs_compatibility?
231
+ expect(grok).to include("redis" => hash_including('command' => hash_including('name' => 'intentionally')))
232
+ else
233
+ expect(grok).to include("command" => "intentionally")
234
+ end
235
+ end
236
+
237
+ it "generates the params field" do
238
+ if ecs_compatibility?
239
+ expect(grok).to include("redis" => hash_including('command' => hash_including('args' => "\"broken\" \"variadic\" \"log\" \"entry\"")))
240
+ else
241
+ expect(grok).to include("params" => "\"broken\" \"variadic\" \"log\" \"entry\"")
242
+ end
243
+ end
102
244
 
103
- let(:value) { "1470637925.186681 [0 127.0.0.1:39404] \"rpush\" \"my:special:key\" \"{\\\"data\\\":\"cdr\\\",\\\"payload\\\":\\\"json\\\"}\"" }
104
- let(:pattern) { "REDISMONLOG" }
105
- let(:grok) { grok_match(pattern, value) }
106
-
107
- it "a pattern pass the grok expression" do
108
- expect(grok).to pass
109
- end
110
-
111
- it "generates the timestamp field" do
112
- expect(grok).to include("timestamp" => "1470637925.186681")
113
- end
114
-
115
- it "generates the database field" do
116
- expect(grok).to include("database" => "0")
117
- end
118
-
119
- it "generates the client field" do
120
- expect(grok).to include("client" => "127.0.0.1")
121
- end
122
-
123
- it "generates the port field" do
124
- expect(grok).to include("port" => "39404")
125
- end
126
-
127
- it "generates the command field" do
128
- expect(grok).to include("command" => "rpush")
129
- end
130
-
131
- it "generates the params field" do
132
- expect(grok).to include("params" => "\"my:special:key\" \"{\\\"data\\\":\"cdr\\\",\\\"payload\\\":\\\"json\\\"}\"")
133
245
  end
134
246
 
135
247
  end
136
-
137
- describe "REDISMONLOG - VARIADIC COMMAND" do
138
-
139
- let(:value) { "1470637875.777457 [15 195.168.1.1:52500] \"intentionally\" \"broken\" \"variadic\" \"log\" \"entry\"" }
140
- let(:pattern) { "REDISMONLOG" }
141
- let(:grok) { grok_match(pattern, value) }
142
-
143
- it "a pattern pass the grok expression" do
144
- expect(grok).to pass
145
- end
146
-
147
- it "generates the timestamp field" do
148
- expect(grok).to include("timestamp" => "1470637875.777457")
149
- end
150
-
151
- it "generates the database field" do
152
- expect(grok).to include("database" => "15")
153
- end
154
-
155
- it "generates the client field" do
156
- expect(grok).to include("client" => "195.168.1.1")
157
- end
158
-
159
- it "generates the port field" do
160
- expect(grok).to include("port" => "52500")
161
- end
162
-
163
- it "generates the command field" do
164
- expect(grok).to include("command" => "intentionally")
165
- end
166
-
167
- it "generates the params field" do
168
- expect(grok).to include("params" => "\"broken\" \"variadic\" \"log\" \"entry\"")
169
- end
170
-
171
- end