fluent-plugin-tail-multiline 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +42 -0
- data/fluent-plugin-tail-multiline.gemspec +1 -1
- data/lib/fluent/plugin/in_tail_multiline.rb +28 -1
- data/test/plugin/test_in_tail_multiline.rb +73 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dff2631e00656f109380d6b27c4f145d8149dc45
|
4
|
+
data.tar.gz: 1a14e17bae8ef5f85754e766321354e9d6620351
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0205218e761d286422953179e61bcce121b89af151a5e277ae7a4ae9c84198bf9d127ed24d6942a830e0b9b2229a65c587298c2cac8ac37e59b5af18dbe38de
|
7
|
+
data.tar.gz: fa0c1f06d70ad1a08bf25644f8804085ecb07e33a186f2db9e575706f4a66af69696d72c4c549e1ca581d0afdc7ca888c910e31520f5599f5a9dc1d55e98056b
|
data/README.md
CHANGED
@@ -26,6 +26,7 @@ Tail-Multiline extends [tail plugin](http://docs.fluentd.org/categories/in_tail)
|
|
26
26
|
----------------------|---------------------------------|---------------------------
|
27
27
|
format_firstline | string(default = format) | RegEx to detect first line of multiple line log, no name capture required
|
28
28
|
rawdata_key | string(default = null) | Store raw data with given key
|
29
|
+
format{1..20} | string(default = null) | The substitute for too long `format`
|
29
30
|
|
30
31
|
## Examples
|
31
32
|
### Java log with exception
|
@@ -73,6 +74,47 @@ format_firstline /----/
|
|
73
74
|
2013-03-03 14:27:34 +0900 test: {"message":"test2"}
|
74
75
|
```
|
75
76
|
|
77
|
+
### Case where too long regexp is required
|
78
|
+
#### Input
|
79
|
+
```
|
80
|
+
Started GET "/users/" for 127.0.0.1 at 2013-06-14 12:00:04 +0900
|
81
|
+
Processing by UsersController#index as HTML
|
82
|
+
Rendered users/index.html.erb within layouts/application (0.5ms)
|
83
|
+
Completed 200 OK in 821ms (Views: 819.5ms | ActiveRecord: 0.0ms)
|
84
|
+
|
85
|
+
|
86
|
+
Started GET "/users/123/" for 127.0.0.1 at 2013-06-14 12:00:11 +0900
|
87
|
+
Processing by UsersController#show as HTML
|
88
|
+
Parameters: {"user_id"=>"123"}
|
89
|
+
Rendered users/show.html.erb within layouts/application (0.3ms)
|
90
|
+
Completed 200 OK in 4ms (Views: 3.2ms | ActiveRecord: 0.0ms)
|
91
|
+
```
|
92
|
+
|
93
|
+
#### Parameters
|
94
|
+
```
|
95
|
+
tag test
|
96
|
+
format_firstline /^Started/
|
97
|
+
format /Started (?<method>[^ ]+) "(?<path>[^"]+)" for (?<host>[^ ]+) at (?<time>[^ ]+ [^ ]+ [^ ]+)\nProcessing by (?<controller>[^\u0023]+)\u0023(?<controller_method>[^ ]+) as (?<format>[^ ]+?)\n( Parameters: (?<parameters>[^ ]+)\n)? Rendered (?<template>[^ ]+) within (?<layout>.+) \([\d\.]+ms\)\nCompleted (?<code>[^ ]+) [^ ]+ in (?<runtime>[\d\.]+)ms \(Views: (?<view_runtime>[\d\.]+)ms \| ActiveRecord: (?<ar_runtime>[\d\.]+)ms\)/
|
98
|
+
```
|
99
|
+
|
100
|
+
It's too long format. You can rewrite above parameters with `format{1..20}`.
|
101
|
+
|
102
|
+
```
|
103
|
+
tag test
|
104
|
+
format_firstline /^Started/
|
105
|
+
format1 /Started (?<method>[^ ]+) "(?<path>[^"]+)" for (?<host>[^ ]+) at (?<time>[^ ]+ [^ ]+ [^ ]+)\n/
|
106
|
+
format2 /Processing by (?<controller>[^\u0023]+)\u0023(?<controller_method>[^ ]+) as (?<format>[^ ]+?)\n/
|
107
|
+
format3 /( Parameters: (?<parameters>[^ ]+)\n)?/
|
108
|
+
format4 / Rendered (?<template>[^ ]+) within (?<layout>.+) \([\d\.]+ms\)\n/
|
109
|
+
format5 /Completed (?<code>[^ ]+) [^ ]+ in (?<runtime>[\d\.]+)ms \(Views: (?<view_runtime>[\d\.]+)ms \| ActiveRecord: (?<ar_runtime>[\d\.]+)ms\)/
|
110
|
+
```
|
111
|
+
|
112
|
+
#### Output
|
113
|
+
```
|
114
|
+
2013-06-14 12:00:04 +0900 test: {"method":"GET","path":"/users/","host":"127.0.0.1","controller":"UsersController","controller_method":"index","format":"HTML","template":"users/index.html.erb","layout":"layouts/application","code":"200","runtime":"821","view_runtime":"819.5","ar_runtime":"0.0"}
|
115
|
+
2013-06-14 12:00:11 +0900 test: {"method":"GET","path":"/users/123/","host":"127.0.0.1","controller":"UsersController","controller_method":"show","format":"HTML","parameters":"{\"user_id\"=>\"123\"}","template":"users/show.html.erb","layout":"layouts/application","code":"200","runtime":"4","view_runtime":"3.2","ar_runtime":"0.0"}
|
116
|
+
```
|
117
|
+
|
76
118
|
## Contributing
|
77
119
|
|
78
120
|
1. Fork it
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
6
|
gem.name = "fluent-plugin-tail-multiline"
|
7
|
-
gem.version = "0.1.
|
7
|
+
gem.version = "0.1.2"
|
8
8
|
gem.authors = ["Tomohisa Ota"]
|
9
9
|
gem.email = ["tomohisa.ota+github@gmail.com"]
|
10
10
|
gem.description = "Extend tail plugin to support log with multiple line"
|
@@ -45,11 +45,16 @@ module Fluent
|
|
45
45
|
end
|
46
46
|
|
47
47
|
Plugin.register_input('tail_multiline', self)
|
48
|
+
|
49
|
+
FORMAT_MAX_NUM = 20
|
48
50
|
|
49
51
|
config_param :format, :string
|
50
52
|
config_param :format_firstline, :string, :default => nil
|
51
53
|
config_param :rawdata_key, :string, :default => nil
|
52
54
|
config_param :auto_flush_sec, :integer, :default => 1
|
55
|
+
(1..FORMAT_MAX_NUM).each do |i|
|
56
|
+
config_param "format#{i}".to_sym, :string, :default => nil
|
57
|
+
end
|
53
58
|
|
54
59
|
def initialize
|
55
60
|
super
|
@@ -57,6 +62,28 @@ module Fluent
|
|
57
62
|
@logbuf = nil
|
58
63
|
@logbuf_flusher = CallLater::new
|
59
64
|
end
|
65
|
+
|
66
|
+
def configure(conf)
|
67
|
+
if conf['format'].nil?
|
68
|
+
invalids = conf.keys.select{|k| k =~ /^format(\d+)$/ and not (1..FORMAT_MAX_NUM).include?($1.to_i)}
|
69
|
+
if invalids.size > 0
|
70
|
+
raise ConfigError, "invalid number formats (valid format number:1-#{FORMAT_MAX_NUM}):" + invalids.join(",")
|
71
|
+
end
|
72
|
+
format_index_list = conf.keys.select{|s| s =~ /^format\d+$/}.map{|v| (/^format(\d+)$/.match(v))[1].to_i}
|
73
|
+
if (1..format_index_list.max).map{|i| conf["format#{i}"]}.include?(nil)
|
74
|
+
raise Fluent::ConfigError, "jump of format index found"
|
75
|
+
end
|
76
|
+
formats = (1..FORMAT_MAX_NUM).map {|i|
|
77
|
+
conf["format#{i}"]
|
78
|
+
}.delete_if {|format|
|
79
|
+
format.nil?
|
80
|
+
}.map {|format|
|
81
|
+
format[1..-2]
|
82
|
+
}.join
|
83
|
+
conf['format'] = '/' + formats + '/'
|
84
|
+
end
|
85
|
+
super
|
86
|
+
end
|
60
87
|
|
61
88
|
def configure_parser(conf)
|
62
89
|
@parser = MultilineTextParser.new
|
@@ -127,8 +154,8 @@ module Fluent
|
|
127
154
|
class CallLater
|
128
155
|
def initialize
|
129
156
|
@locker = Monitor::new
|
130
|
-
@thread = Thread.new(&method(:run))
|
131
157
|
initExecBlock()
|
158
|
+
@thread = Thread.new(&method(:run))
|
132
159
|
end
|
133
160
|
|
134
161
|
def call_later(delay,&block)
|
@@ -200,4 +200,76 @@ class TailMultilineInputTest < Test::Unit::TestCase
|
|
200
200
|
end
|
201
201
|
end
|
202
202
|
|
203
|
-
|
203
|
+
def test_multilinelog_with_serial_number_format
|
204
|
+
tmpFile = Tempfile.new("in_tail_multiline-")
|
205
|
+
begin
|
206
|
+
d = create_driver %[
|
207
|
+
path #{tmpFile.path}
|
208
|
+
tag test
|
209
|
+
format1 /^s (?<message1>[^\\n]+)\\n?/
|
210
|
+
format2 /(f (?<message2>[^\\n]+)\\n?)?/
|
211
|
+
format3 /(f (?<message3>.*))?/
|
212
|
+
format_firstline /^[s]/
|
213
|
+
rawdata_key rawdata
|
214
|
+
]
|
215
|
+
d.run do
|
216
|
+
File.open(tmpFile.path, "w") {|f|
|
217
|
+
f.puts "f test1"
|
218
|
+
f.puts "s test2"
|
219
|
+
f.puts "f test3"
|
220
|
+
f.puts "f test4"
|
221
|
+
f.puts "s test5"
|
222
|
+
f.puts "s test6"
|
223
|
+
f.puts "f test7"
|
224
|
+
f.puts "s test8"
|
225
|
+
}
|
226
|
+
sleep 1
|
227
|
+
end
|
228
|
+
|
229
|
+
emits = d.emits
|
230
|
+
assert_equal(true, emits.length > 0)
|
231
|
+
n = -1
|
232
|
+
assert_equal({"message1"=>"test2","message2"=>"test3","message3"=>"test4","rawdata"=>"s test2\nf test3\nf test4"}, emits[0][2])
|
233
|
+
assert_equal({"message1"=>"test5","rawdata"=>"s test5"}, emits[1][2])
|
234
|
+
assert_equal({"message1"=>"test6","message2"=>"test7","rawdata"=>"s test6\nf test7"}, emits[2][2])
|
235
|
+
assert_equal({"message1"=>"test8","rawdata"=>"s test8"}, emits[3][2])
|
236
|
+
ensure
|
237
|
+
tmpFile.close(true)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_multilinelog_with_invalid_number_format
|
242
|
+
tmpFile = Tempfile.new("in_tail_multiline-")
|
243
|
+
begin
|
244
|
+
e = assert_raise(Fluent::ConfigError) {
|
245
|
+
create_driver %[
|
246
|
+
path #{tmpFile.path}
|
247
|
+
tag test
|
248
|
+
format21 /(?<message1>.*)/
|
249
|
+
format22 /(?<message2>.*)/
|
250
|
+
]
|
251
|
+
}
|
252
|
+
assert_equal(e.message, "invalid number formats (valid format number:1-20):format21,format22")
|
253
|
+
ensure
|
254
|
+
tmpFile.close(true)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def test_multilinelog_with_jump_of_number_format
|
259
|
+
tmpFile = Tempfile.new("in_tail_multiline-")
|
260
|
+
begin
|
261
|
+
e = assert_raise(Fluent::ConfigError) {
|
262
|
+
create_driver %[
|
263
|
+
path #{tmpFile.path}
|
264
|
+
tag test
|
265
|
+
format1 /(?<message1>.*)/
|
266
|
+
format3 /(?<message2>.*)/
|
267
|
+
]
|
268
|
+
}
|
269
|
+
assert_equal(e.message, "jump of format index found")
|
270
|
+
ensure
|
271
|
+
tmpFile.close(true)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-tail-multiline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomohisa Ota
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|