fluent-plugin-detect-exceptions-xiniaoyun 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,144 @@
1
+ #
2
+ # Copyright 2016 Google Inc. All rights reserved.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'fluent/plugin/exception_detector'
17
+ require 'fluent/output'
18
+
19
+ module Fluent
20
+ # This output plugin consumes a log stream of JSON objects which contain
21
+ # single-line log messages. If a consecutive sequence of log messages form
22
+ # an exception stack trace, they forwarded as a single, combined JSON
23
+ # object. Otherwise, the input log data is forwarded as is.
24
+ class DetectExceptionsOutput < Output
25
+ desc 'The field which contains the raw message text in the input JSON data.'
26
+ config_param :message, :string, default: ''
27
+ desc 'The prefix to be removed from the input tag when outputting a record.'
28
+ config_param :remove_tag_prefix, :string
29
+ desc 'The interval of flushing the buffer for multiline format.'
30
+ config_param :multiline_flush_interval, :time, default: nil
31
+ desc 'Programming languages for which to detect exceptions. Default: all.'
32
+ config_param :languages, :array, value_type: :string, default: []
33
+ desc 'Maximum number of lines to flush (0 means no limit). Default: 1000.'
34
+ config_param :max_lines, :integer, default: 1000
35
+ desc 'Maximum number of bytes to flush (0 means no limit). Default: 0.'
36
+ config_param :max_bytes, :integer, default: 0
37
+ desc 'Separate log streams by this field in the input JSON data.'
38
+ config_param :stream, :string, default: ''
39
+
40
+ Fluent::Plugin.register_output('detect_exceptions', self)
41
+
42
+ ERROR_EMPTY_REMOVE_TAG_PREFIX =
43
+ 'remove_tag_prefix must not be empty.'.freeze
44
+
45
+ def configure(conf)
46
+ super
47
+
48
+ if multiline_flush_interval
49
+ @check_flush_interval = [multiline_flush_interval * 0.1, 1].max
50
+ end
51
+
52
+ if remove_tag_prefix.empty?
53
+ raise ConfigError, ERROR_EMPTY_REMOVE_TAG_PREFIX
54
+ end
55
+
56
+ @languages = languages.map(&:to_sym)
57
+
58
+ # Maps log stream tags to a corresponding TraceAccumulator.
59
+ @accumulators = {}
60
+ end
61
+
62
+ def start
63
+ super
64
+
65
+ if multiline_flush_interval
66
+ @flush_buffer_mutex = Mutex.new
67
+ @stop_check = false
68
+ @thread = Thread.new(&method(:check_flush_loop))
69
+ end
70
+ end
71
+
72
+ def before_shutdown
73
+ flush_buffers
74
+ super if defined?(super)
75
+ end
76
+
77
+ def shutdown
78
+ # Before shutdown is not available in older fluentd versions.
79
+ # Hence, we make sure that we flush the buffers here as well.
80
+ flush_buffers
81
+ @thread.join if @multiline_flush_interval
82
+ super
83
+ end
84
+
85
+ def emit(tag, es, chain)
86
+ es.each do |time_sec, record|
87
+ process_record(tag, time_sec, record)
88
+ end
89
+ chain.next
90
+ end
91
+
92
+ private
93
+
94
+ def process_record(tag, time_sec, record)
95
+ synchronize do
96
+ log_id = [tag]
97
+ log_id.push(record.fetch(@stream, '')) unless @stream.empty?
98
+ unless @accumulators.key?(log_id)
99
+ out_tag = tag.sub(/^#{Regexp.escape(@remove_tag_prefix)}\./, '')
100
+ @accumulators[log_id] =
101
+ Fluent::TraceAccumulator.new(@message, @languages,
102
+ max_lines: @max_lines,
103
+ max_bytes: @max_bytes) do |t, r|
104
+ router.emit(out_tag, t, r)
105
+ end
106
+ end
107
+
108
+ @accumulators[log_id].push(time_sec, record)
109
+ end
110
+ end
111
+
112
+ def flush_buffers
113
+ synchronize do
114
+ @stop_check = true
115
+ @accumulators.each_value(&:force_flush)
116
+ end
117
+ end
118
+
119
+ def check_flush_loop
120
+ @flush_buffer_mutex.synchronize do
121
+ loop do
122
+ @flush_buffer_mutex.sleep(@check_flush_interval)
123
+ now = Time.now
124
+ break if @stop_check
125
+ @accumulators.each_value do |acc|
126
+ acc.force_flush if now - acc.buffer_start_time >
127
+ @multiline_flush_interval
128
+ end
129
+ end
130
+ end
131
+ rescue
132
+ log.error 'error in check_flush_loop', error: $ERROR_INFO.to_s
133
+ log.error_backtrace
134
+ end
135
+
136
+ def synchronize(&block)
137
+ if @multiline_flush_interval
138
+ @flush_buffer_mutex.synchronize(&block)
139
+ else
140
+ yield
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,46 @@
1
+ # Copyright 2016 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'rubygems'
16
+ require 'bundler'
17
+
18
+ begin
19
+ Bundler.setup(:default, :development)
20
+ rescue Bundler::BundlerError => e
21
+ $stderr.puts e.message
22
+ $stderr.puts 'Run `bundle install` to install missing gems'
23
+ exit e.status_code
24
+ end
25
+
26
+ require 'test/unit'
27
+
28
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
29
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
30
+ require 'fluent/test'
31
+
32
+ unless ENV.key?('VERBOSE')
33
+ nulllogger = Object.new
34
+ nulllogger.instance_eval do |_|
35
+ def respond_to_missing?
36
+ true
37
+ end
38
+
39
+ def method_missing(_method, *_args) # rubocop:disable Style/MethodMissing
40
+ end
41
+ end
42
+ # global $log variable is used by fluentd
43
+ $log = nulllogger # rubocop:disable Style/GlobalVars
44
+ end
45
+
46
+ require 'fluent/plugin/out_detect_exceptions'
@@ -0,0 +1,73 @@
1
+ # Copyright 2016 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'benchmark'
16
+
17
+ require 'fluent/plugin/exception_detector'
18
+
19
+ size_in_m = 25
20
+ line_length = 50
21
+
22
+ size = size_in_m << 20
23
+
24
+ JAVA_EXC = <<END.freeze
25
+ Jul 09, 2015 3:23:29 PM com.google.devtools.search.cloud.feeder.MakeLog: RuntimeException: Run from this message!
26
+ at com.my.app.Object.do$a1(MakeLog.java:50)
27
+ at java.lang.Thing.call(Thing.java:10)
28
+ at com.my.app.Object.help(MakeLog.java:40)
29
+ at sun.javax.API.method(API.java:100)
30
+ at com.jetty.Framework.main(MakeLog.java:30)
31
+ END
32
+
33
+ PYTHON_EXC = <<END.freeze
34
+ Traceback (most recent call last):
35
+ File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
36
+ rv = self.handle_exception(request, response, e)
37
+ File "/base/data/home/apps/s~nearfieldspy/1.378705245900539993/nearfieldspy.py", line 17, in start
38
+ return get()
39
+ File "/base/data/home/apps/s~nearfieldspy/1.378705245900539993/nearfieldspy.py", line 5, in get
40
+ raise Exception('spam', 'eggs')
41
+ Exception: ('spam', 'eggs')
42
+ END
43
+
44
+ chars = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
45
+
46
+ random_text = (1..(size / line_length)).collect do
47
+ (0...line_length).map { chars[rand(chars.length)] }.join
48
+ end
49
+
50
+ exceptions = {
51
+ java: (JAVA_EXC * (size / JAVA_EXC.length)).lines,
52
+ python: (PYTHON_EXC * (size / PYTHON_EXC.length)).lines
53
+ }
54
+
55
+ puts "Start benchmark. Input size #{size_in_m}M."
56
+ Benchmark.bm do |x|
57
+ languages = Fluent::ExceptionDetectorConfig::RULES_BY_LANG.keys
58
+ languages.each do |lang|
59
+ buffer = Fluent::TraceAccumulator.new(nil, lang) {}
60
+ x.report("#{lang}_detector_random_text") do
61
+ random_text.each { |l| buffer.push(0, l) }
62
+ end
63
+ end
64
+ [:java, :python, :all].each do |detector_lang|
65
+ buffer = Fluent::TraceAccumulator.new(nil, detector_lang) {}
66
+ exc_languages = detector_lang == :all ? exceptions.keys : [detector_lang]
67
+ exc_languages.each do |exc_lang|
68
+ x.report("#{detector_lang}_detector_#{exc_lang}_stacks") do
69
+ exceptions[exc_lang].each { |l| buffer.push(0, l) }
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,768 @@
1
+ # Copyright 2016 Google Inc. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative '../helper'
16
+ require 'fluent/plugin/exception_detector'
17
+
18
+ class ExceptionDetectorTest < Test::Unit::TestCase
19
+ JAVA_EXC_PART1 = <<END.freeze
20
+ Jul 09, 2015 3:23:29 PM com.google.devtools.search.cloud.feeder.MakeLog: RuntimeException: Run from this message!
21
+ at com.my.app.Object.do$a1(MakeLog.java:50)
22
+ at java.lang.Thing.call(Thing.java:10)
23
+ END
24
+
25
+ JAVA_EXC_PART2 = <<END.freeze
26
+ at com.my.app.Object.help(MakeLog.java:40)
27
+ at sun.javax.API.method(API.java:100)
28
+ at com.jetty.Framework.main(MakeLog.java:30)
29
+ END
30
+
31
+ JAVA_EXC = (JAVA_EXC_PART1 + JAVA_EXC_PART2).freeze
32
+
33
+ COMPLEX_JAVA_EXC = <<END.freeze
34
+ javax.servlet.ServletException: Something bad happened
35
+ at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)
36
+ at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
37
+ at com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:28)
38
+ at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
39
+ at com.example.myproject.OutputBufferFilter.doFilter(OutputBufferFilter.java:33)
40
+ at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
41
+ at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
42
+ at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
43
+ at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
44
+ at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
45
+ at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
46
+ at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
47
+ at org.mortbay.jetty.Server.handle(Server.java:326)
48
+ at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
49
+ at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
50
+ at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
51
+ at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
52
+ at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
53
+ at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)
54
+ at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
55
+ Caused by: com.example.myproject.MyProjectServletException
56
+ at com.example.myproject.MyServlet.doPost(MyServlet.java:169)
57
+ at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
58
+ at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
59
+ at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
60
+ at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
61
+ at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:30)
62
+ ... 27 more
63
+ END
64
+
65
+ NODE_JS_EXC = <<END.freeze
66
+ ReferenceError: myArray is not defined
67
+ at next (/app/node_modules/express/lib/router/index.js:256:14)
68
+ at /app/node_modules/express/lib/router/index.js:615:15
69
+ at next (/app/node_modules/express/lib/router/index.js:271:10)
70
+ at Function.process_params (/app/node_modules/express/lib/router/index.js:330:12)
71
+ at /app/node_modules/express/lib/router/index.js:277:22
72
+ at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
73
+ at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)
74
+ at next (/app/node_modules/express/lib/router/route.js:131:13)
75
+ at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
76
+ at /app/app.js:52:3
77
+ END
78
+
79
+ CLIENT_JS_EXC = <<END.freeze
80
+ Error
81
+ at bls (<anonymous>:3:9)
82
+ at <anonymous>:6:4
83
+ at a_function_name
84
+ at Object.InjectedScript._evaluateOn (http://<anonymous>/file.js?foo=bar:875:140)
85
+ at Object.InjectedScript.evaluate (<anonymous>)
86
+ END
87
+
88
+ V8_JS_EXC = <<END.freeze
89
+ V8 errors stack trace
90
+ eval at Foo.a (eval at Bar.z (myscript.js:10:3))
91
+ at new Contructor.Name (native)
92
+ at new FunctionName (unknown location)
93
+ at Type.functionName [as methodName] (file(copy).js?query='yes':12:9)
94
+ at functionName [as methodName] (native)
95
+ at Type.main(sample(copy).js:6:4)
96
+ END
97
+
98
+ PYTHON_EXC = <<END.freeze
99
+ Traceback (most recent call last):
100
+ File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
101
+ rv = self.handle_exception(request, response, e)
102
+ File "/base/data/home/apps/s~nearfieldspy/1.378705245900539993/nearfieldspy.py", line 17, in start
103
+ return get()
104
+ File "/base/data/home/apps/s~nearfieldspy/1.378705245900539993/nearfieldspy.py", line 5, in get
105
+ raise Exception('spam', 'eggs')
106
+ Exception: ('spam', 'eggs')
107
+ END
108
+
109
+ PHP_EXC = <<END.freeze
110
+ exception 'Exception' with message 'Custom exception' in /home/joe/work/test-php/test.php:5
111
+ Stack trace:
112
+ #0 /home/joe/work/test-php/test.php(9): func1()
113
+ #1 /home/joe/work/test-php/test.php(13): func2()
114
+ #2 {main}
115
+ END
116
+
117
+ PHP_ON_GAE_EXC = <<END.freeze
118
+ PHP Fatal error: Uncaught exception 'Exception' with message 'message' in /base/data/home/apps/s~crash-example-php/1.388306779641080894/errors.php:60
119
+ Stack trace:
120
+ #0 [internal function]: ErrorEntryGenerator::{closure}()
121
+ #1 /base/data/home/apps/s~crash-example-php/1.388306779641080894/errors.php(20): call_user_func_array(Object(Closure), Array)
122
+ #2 /base/data/home/apps/s~crash-example-php/1.388306779641080894/index.php(36): ErrorEntry->__call('raise', Array)
123
+ #3 /base/data/home/apps/s~crash-example-php/1.388306779641080894/index.php(36): ErrorEntry->raise()
124
+ #4 {main}
125
+ thrown in /base/data/home/apps/s~crash-example-php/1.388306779641080894/errors.php on line 60
126
+ END
127
+
128
+ GO_EXC = <<END.freeze
129
+ panic: my panic
130
+
131
+ goroutine 4 [running]:
132
+ panic(0x45cb40, 0x47ad70)
133
+ /usr/local/go/src/runtime/panic.go:542 +0x46c fp=0xc42003f7b8 sp=0xc42003f710 pc=0x422f7c
134
+ main.main.func1(0xc420024120)
135
+ foo.go:6 +0x39 fp=0xc42003f7d8 sp=0xc42003f7b8 pc=0x451339
136
+ runtime.goexit()
137
+ /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003f7e0 sp=0xc42003f7d8 pc=0x44b4d1
138
+ created by main.main
139
+ foo.go:5 +0x58
140
+
141
+ goroutine 1 [chan receive]:
142
+ runtime.gopark(0x4739b8, 0xc420024178, 0x46fcd7, 0xc, 0xc420028e17, 0x3)
143
+ /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc420053e30 sp=0xc420053e00 pc=0x42503c
144
+ runtime.goparkunlock(0xc420024178, 0x46fcd7, 0xc, 0x1000f010040c217, 0x3)
145
+ /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc420053e70 sp=0xc420053e30 pc=0x42512e
146
+ runtime.chanrecv(0xc420024120, 0x0, 0xc420053f01, 0x4512d8)
147
+ /usr/local/go/src/runtime/chan.go:506 +0x304 fp=0xc420053f20 sp=0xc420053e70 pc=0x4046b4
148
+ runtime.chanrecv1(0xc420024120, 0x0)
149
+ /usr/local/go/src/runtime/chan.go:388 +0x2b fp=0xc420053f50 sp=0xc420053f20 pc=0x40439b
150
+ main.main()
151
+ foo.go:9 +0x6f fp=0xc420053f80 sp=0xc420053f50 pc=0x4512ef
152
+ runtime.main()
153
+ /usr/local/go/src/runtime/proc.go:185 +0x20d fp=0xc420053fe0 sp=0xc420053f80 pc=0x424bad
154
+ runtime.goexit()
155
+ /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc420053fe8 sp=0xc420053fe0 pc=0x44b4d1
156
+
157
+ goroutine 2 [force gc (idle)]:
158
+ runtime.gopark(0x4739b8, 0x4ad720, 0x47001e, 0xf, 0x14, 0x1)
159
+ /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc42003e768 sp=0xc42003e738 pc=0x42503c
160
+ runtime.goparkunlock(0x4ad720, 0x47001e, 0xf, 0xc420000114, 0x1)
161
+ /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc42003e7a8 sp=0xc42003e768 pc=0x42512e
162
+ runtime.forcegchelper()
163
+ /usr/local/go/src/runtime/proc.go:238 +0xcc fp=0xc42003e7e0 sp=0xc42003e7a8 pc=0x424e5c
164
+ runtime.goexit()
165
+ /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003e7e8 sp=0xc42003e7e0 pc=0x44b4d1
166
+ created by runtime.init.4
167
+ /usr/local/go/src/runtime/proc.go:227 +0x35
168
+
169
+ goroutine 3 [GC sweep wait]:
170
+ runtime.gopark(0x4739b8, 0x4ad7e0, 0x46fdd2, 0xd, 0x419914, 0x1)
171
+ /usr/local/go/src/runtime/proc.go:280 +0x12c fp=0xc42003ef60 sp=0xc42003ef30 pc=0x42503c
172
+ runtime.goparkunlock(0x4ad7e0, 0x46fdd2, 0xd, 0x14, 0x1)
173
+ /usr/local/go/src/runtime/proc.go:286 +0x5e fp=0xc42003efa0 sp=0xc42003ef60 pc=0x42512e
174
+ runtime.bgsweep(0xc42001e150)
175
+ /usr/local/go/src/runtime/mgcsweep.go:52 +0xa3 fp=0xc42003efd8 sp=0xc42003efa0 pc=0x419973
176
+ runtime.goexit()
177
+ /usr/local/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003efe0 sp=0xc42003efd8 pc=0x44b4d1
178
+ created by runtime.gcenable
179
+ /usr/local/go/src/runtime/mgc.go:216 +0x58
180
+ END
181
+
182
+ GO_ON_GAE_EXC = <<END.freeze
183
+ panic: runtime error: index out of range
184
+
185
+ goroutine 12 [running]:
186
+ main88989.memoryAccessException()
187
+ crash_example_go.go:58 +0x12a
188
+ main88989.handler(0x2afb7042a408, 0xc01042f880, 0xc0104d3450)
189
+ crash_example_go.go:36 +0x7ec
190
+ net/http.HandlerFunc.ServeHTTP(0x13e5128, 0x2afb7042a408, 0xc01042f880, 0xc0104d3450)
191
+ go/src/net/http/server.go:1265 +0x56
192
+ net/http.(*ServeMux).ServeHTTP(0xc01045cab0, 0x2afb7042a408, 0xc01042f880, 0xc0104d3450)
193
+ go/src/net/http/server.go:1541 +0x1b4
194
+ appengine_internal.executeRequestSafely(0xc01042f880, 0xc0104d3450)
195
+ go/src/appengine_internal/api_prod.go:288 +0xb7
196
+ appengine_internal.(*server).HandleRequest(0x15819b0, 0xc010401560, 0xc0104c8180, 0xc010431380, 0x0, 0x0)
197
+ go/src/appengine_internal/api_prod.go:222 +0x102b
198
+ reflect.Value.call(0x1243fe0, 0x15819b0, 0x113, 0x12c8a20, 0x4, 0xc010485f78, 0x3, 0x3, 0x0, 0x0, ...)
199
+ /tmp/appengine/go/src/reflect/value.go:419 +0x10fd
200
+ reflect.Value.Call(0x1243fe0, 0x15819b0, 0x113, 0xc010485f78, 0x3, 0x3, 0x0, 0x0, 0x0)
201
+ /tmp/ap
202
+ END
203
+
204
+ GO_SIGNAL_EXC = <<END.freeze
205
+ panic: runtime error: invalid memory address or nil pointer dereference
206
+ [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7fd34f]
207
+
208
+ goroutine 5 [running]:
209
+ panics.nilPtrDereference()
210
+ panics/panics.go:33 +0x1f
211
+ panics.Wait()
212
+ panics/panics.go:16 +0x3b
213
+ created by main.main
214
+ server.go:20 +0x91
215
+ END
216
+
217
+ CSHARP_EXC = <<END.freeze
218
+ System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
219
+ at System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.Dictionary`2[System.Int32,System.Double]].get_Item (System.String key) [0x00000] in <filename unknown>:0
220
+ at File3.Consolidator_Class.Function5 (System.Collections.Generic.Dictionary`2 names, System.Text.StringBuilder param_4) [0x00007] in /usr/local/google/home/Csharp/another file.csharp:9
221
+ at File3.Consolidator_Class.Function4 (System.Text.StringBuilder param_4, System.Double[,,] array) [0x00013] in /usr/local/google/home/Csharp/another file.csharp:23
222
+ at File3.Consolidator_Class.Function3 (Int32 param_3) [0x0000f] in /usr/local/google/home/Csharp/another file.csharp:27
223
+ at File3.Consolidator_Class.Function3 (System.Text.StringBuilder param_3) [0x00007] in /usr/local/google/home/Csharp/another file.csharp:32
224
+ at File2.Processor.Function2 (System.Int32& param_2, System.Collections.Generic.Stack`1& numbers) [0x00003] in /usr/local/google/home/Csharp/File2.csharp:19
225
+ at File2.Processor.Random2 () [0x00037] in /usr/local/google/home/Csharp/File2.csharp:28
226
+ at File2.Processor.Function1 (Int32 param_1, System.Collections.Generic.Dictionary`2 map) [0x00007] in /usr/local/google/home/Csharp/File2.csharp:34
227
+ at Main.Welcome+<Main>c__AnonStorey0.<>m__0 () [0x00006] in /usr/local/google/home/Csharp/hello.csharp:48
228
+ at System.Threading.Thread.StartInternal () [0x00000] in <filename unknown>:0
229
+ END
230
+
231
+ RUBY_EXC = <<END.freeze
232
+ NoMethodError (undefined method `resursivewordload' for #<BooksController:0x007f8dd9a0c738>):
233
+ app/controllers/books_controller.rb:69:in `recursivewordload'
234
+ app/controllers/books_controller.rb:75:in `loadword'
235
+ app/controllers/books_controller.rb:79:in `loadline'
236
+ app/controllers/books_controller.rb:83:in `loadparagraph'
237
+ app/controllers/books_controller.rb:87:in `loadpage'
238
+ app/controllers/books_controller.rb:91:in `onload'
239
+ app/controllers/books_controller.rb:95:in `loadrecursive'
240
+ app/controllers/books_controller.rb:99:in `requestload'
241
+ app/controllers/books_controller.rb:118:in `generror'
242
+ config/error_reporting_logger.rb:62:in `tagged'
243
+ END
244
+
245
+ # The whitespace on the second line is significant.
246
+ # rubocop:disable TrailingWhitespace
247
+ RAILS_EXC = <<END.freeze
248
+ ActionController::RoutingError (No route matches [GET] "/settings"):
249
+
250
+ actionpack (5.1.4) lib/action_dispatch/middleware/debug_exceptions.rb:63:in `call'
251
+ actionpack (5.1.4) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
252
+ railties (5.1.4) lib/rails/rack/logger.rb:36:in `call_app'
253
+ railties (5.1.4) lib/rails/rack/logger.rb:24:in `block in call'
254
+ activesupport (5.1.4) lib/active_support/tagged_logging.rb:69:in `block in tagged'
255
+ activesupport (5.1.4) lib/active_support/tagged_logging.rb:26:in `tagged'
256
+ activesupport (5.1.4) lib/active_support/tagged_logging.rb:69:in `tagged'
257
+ railties (5.1.4) lib/rails/rack/logger.rb:24:in `call'
258
+ actionpack (5.1.4) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
259
+ actionpack (5.1.4) lib/action_dispatch/middleware/request_id.rb:25:in `call'
260
+ rack (2.0.3) lib/rack/method_override.rb:22:in `call'
261
+ rack (2.0.3) lib/rack/runtime.rb:22:in `call'
262
+ activesupport (5.1.4) lib/active_support/cache/strategy/local_cache_middleware.rb:27:in `call'
263
+ actionpack (5.1.4) lib/action_dispatch/middleware/executor.rb:12:in `call'
264
+ rack (2.0.3) lib/rack/sendfile.rb:111:in `call'
265
+ railties (5.1.4) lib/rails/engine.rb:522:in `call'
266
+ puma (3.10.0) lib/puma/configuration.rb:225:in `call'
267
+ puma (3.10.0) lib/puma/server.rb:605:in `handle_request'
268
+ puma (3.10.0) lib/puma/server.rb:437:in `process_client'
269
+ puma (3.10.0) lib/puma/server.rb:301:in `block in run'
270
+ puma (3.10.0) lib/puma/thread_pool.rb:120:in `block in spawn_thread'
271
+ END
272
+
273
+ DART_ERR = <<END.freeze
274
+ Unhandled exception:
275
+ Instance of 'MyError'
276
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:15:20)
277
+ #1 printError (file:///path/to/code/dartFile.dart:37:13)
278
+ #2 main (file:///path/to/code/dartFile.dart:15:3)
279
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
280
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
281
+ END
282
+
283
+ DART_EXC = <<END.freeze
284
+ Unhandled exception:
285
+ Exception: exception message
286
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:17:20)
287
+ #1 printError (file:///path/to/code/dartFile.dart:37:13)
288
+ #2 main (file:///path/to/code/dartFile.dart:17:3)
289
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
290
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
291
+ END
292
+
293
+ DART_ASYNC_ERR = <<END.freeze
294
+ Unhandled exception:
295
+ Bad state: oops
296
+ #0 handleFailure (file:///test/example/http/handling_an_httprequest_error.dart:16:3)
297
+ #1 main (file:///test/example/http/handling_an_httprequest_error.dart:24:5)
298
+ <asynchronous suspension>
299
+ #2 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
300
+ #3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
301
+ END
302
+
303
+ DART_DIVIDE_BY_ZERO_ERR = <<END.freeze
304
+ Unhandled exception:
305
+ IntegerDivisionByZeroException
306
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:27:20)
307
+ #1 printError (file:///path/to/code/dartFile.dart:42:13)
308
+ #2 main (file:///path/to/code/dartFile.dart:27:3)
309
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
310
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
311
+ END
312
+
313
+ DART_ARGUMENT_ERR = <<END.freeze
314
+ Unhandled exception:
315
+ Invalid argument(s): invalid argument
316
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:23:20)
317
+ #1 printError (file:///path/to/code/dartFile.dart:42:13)
318
+ #2 main (file:///path/to/code/dartFile.dart:23:3)
319
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
320
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
321
+ END
322
+
323
+ DART_RANGE_ERR = <<END.freeze
324
+ Unhandled exception:
325
+ RangeError (index): Invalid value: Valid value range is empty: 1
326
+ #0 List.[] (dart:core-patch/growable_array.dart:151)
327
+ #1 main.<anonymous closure> (file:///path/to/code/dartFile.dart:31:23)
328
+ #2 printError (file:///path/to/code/dartFile.dart:42:13)
329
+ #3 main (file:///path/to/code/dartFile.dart:29:3)
330
+ #4 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
331
+ #5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
332
+ END
333
+
334
+ DART_ASSERTION_ERR = <<END.freeze
335
+ Unhandled exception:
336
+ Assertion failed
337
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:9:20)
338
+ #1 printError (file:///path/to/code/dartFile.dart:36:13)
339
+ #2 main (file:///path/to/code/dartFile.dart:9:3)
340
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
341
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
342
+ END
343
+
344
+ DART_ABSTRACT_CLASS_ERR = <<END.freeze
345
+ Unhandled exception:
346
+ Cannot instantiate abstract class LNClassName: _url 'null' line null
347
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:12:20)
348
+ #1 printError (file:///path/to/code/dartFile.dart:36:13)
349
+ #2 main (file:///path/to/code/dartFile.dart:12:3)
350
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
351
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
352
+ END
353
+
354
+ DART_READ_STATIC_ERR = <<END.freeze
355
+ Unhandled exception:
356
+ Reading static variable 'variable' during its initialization
357
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:28:20)
358
+ #1 printError (file:///path/to/code/dartFile.dart:43:13)
359
+ #2 main (file:///path/to/code/dartFile.dart:28:3)
360
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
361
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
362
+ END
363
+
364
+ DART_UNIMPLEMENTED_ERROR = <<END.freeze
365
+ Unhandled exception:
366
+ UnimplementedError: unimplemented
367
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:38:20)
368
+ #1 printError (file:///path/to/code/dartFile.dart:61:13)
369
+ #2 main (file:///path/to/code/dartFile.dart:38:3)
370
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
371
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
372
+ END
373
+
374
+ DART_UNSUPPORTED_ERR = <<END.freeze
375
+ Unhandled exception:
376
+ Unsupported operation: unsupported
377
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:36:20)
378
+ #1 printError (file:///path/to/code/dartFile.dart:61:13)
379
+ #2 main (file:///path/to/code/dartFile.dart:36:3)
380
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
381
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
382
+ END
383
+
384
+ DART_CONCURRENT_MODIFICATION_ERR = <<END.freeze
385
+ Unhandled exception:
386
+ Concurrent modification during iteration.
387
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:35:20)
388
+ #1 printError (file:///path/to/code/dartFile.dart:61:13)
389
+ #2 main (file:///path/to/code/dartFile.dart:35:3)
390
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
391
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
392
+ END
393
+
394
+ DART_OOM_ERR = <<END.freeze
395
+ Unhandled exception:
396
+ Out of Memory
397
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:34:20)
398
+ #1 printError (file:///path/to/code/dartFile.dart:61:13)
399
+ #2 main (file:///path/to/code/dartFile.dart:34:3)
400
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
401
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
402
+ END
403
+
404
+ DART_STACK_OVERFLOW_ERR = <<END.freeze
405
+ Unhandled exception:
406
+ Stack Overflow
407
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:33:20)
408
+ #1 printError (file:///path/to/code/dartFile.dart:61:13)
409
+ #2 main (file:///path/to/code/dartFile.dart:33:3)
410
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
411
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
412
+ END
413
+
414
+ DART_FALLTHROUGH_ERR = <<END.freeze
415
+ Unhandled exception:
416
+ 'null': Switch case fall-through at line null.
417
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:39:20)
418
+ #1 printError (file:///path/to/code/dartFile.dart:51:13)
419
+ #2 main (file:///path/to/code/dartFile.dart:39:3)
420
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
421
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
422
+ END
423
+
424
+ DART_TYPE_ERR = <<END.freeze
425
+ Unhandled exception:
426
+ 'file:///path/to/code/dartFile.dart': malformed type: line 7 pos 24: cannot resolve class 'NoType' from '::'
427
+ printError( () { new NoType(); } );
428
+ ^
429
+
430
+
431
+ #0 _TypeError._throwNew (dart:core-patch/errors_patch.dart:82)
432
+ #1 main.<anonymous closure> (file:///path/to/code/dartFile.dart:7:24)
433
+ #2 printError (file:///path/to/code/dartFile.dart:36:13)
434
+ #3 main (file:///path/to/code/dartFile.dart:7:3)
435
+ #4 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
436
+ #5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
437
+ END
438
+
439
+ DART_FORMAT_ERR = <<END.freeze
440
+ Unhandled exception:
441
+ FormatException: format exception
442
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:25:20)
443
+ #1 printError (file:///path/to/code/dartFile.dart:42:13)
444
+ #2 main (file:///path/to/code/dartFile.dart:25:3)
445
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
446
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
447
+ END
448
+
449
+ DART_FORMAT_WITH_CODE_ERR = <<END.freeze
450
+ Unhandled exception:
451
+ FormatException: Invalid base64 data (at line 3, character 8)
452
+ this is not valid
453
+ ^
454
+
455
+ #0 main.<anonymous closure> (file:///path/to/code/dartFile.dart:24:20)
456
+ #1 printError (file:///path/to/code/dartFile.dart:42:13)
457
+ #2 main (file:///path/to/code/dartFile.dart:24:3)
458
+ #3 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
459
+ #4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
460
+ END
461
+
462
+ DART_NO_METHOD_ERR = <<END.freeze
463
+ Unhandled exception:
464
+ NoSuchMethodError: No constructor 'TypeError' with matching arguments declared in class 'TypeError'.
465
+ Receiver: Type: class 'TypeError'
466
+ Tried calling: new TypeError("Invalid base64 data", "invalid", 36)
467
+ Found: new TypeError()
468
+ #0 NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:196)
469
+ #1 main.<anonymous closure> (file:///path/to/code/dartFile.dart:8:39)
470
+ #2 printError (file:///path/to/code/dartFile.dart:36:13)
471
+ #3 main (file:///path/to/code/dartFile.dart:8:3)
472
+ #4 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
473
+ #5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
474
+ END
475
+
476
+ DART_NO_METHOD_GLOBAL_ERR = <<END.freeze
477
+ Unhandled exception:
478
+ NoSuchMethodError: No top-level method 'noMethod' declared.
479
+ Receiver: top-level
480
+ Tried calling: noMethod()
481
+ #0 NoSuchMethodError._throwNew (dart:core-patch/errors_patch.dart:196)
482
+ #1 main.<anonymous closure> (file:///path/to/code/dartFile.dart:10:20)
483
+ #2 printError (file:///path/to/code/dartFile.dart:36:13)
484
+ #3 main (file:///path/to/code/dartFile.dart:10:3)
485
+ #4 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:265)
486
+ #5 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
487
+ END
488
+
489
+ ARBITRARY_TEXT = <<END.freeze
490
+ This arbitrary text.
491
+ It sounds tympanic: a word which means like a drum.
492
+
493
+ I am glad it contains no exception.
494
+ END
495
+
496
+ def check_multiline(detector, expected_first, expected_last, multiline)
497
+ lines = multiline.lines
498
+ lines.each_with_index do |line, index|
499
+ action = detector.update(line)
500
+ case index
501
+ when 0
502
+ assert_equal(expected_first, action,
503
+ "unexpected action on first line: #{line}")
504
+ when lines.length - 1
505
+ assert_equal(expected_last, action,
506
+ "unexpected action on last line: #{line}")
507
+ else
508
+ assert_equal(:inside_trace, action, "line not buffered: #{line}")
509
+ end
510
+ end
511
+ end
512
+
513
+ def check_no_multiline(detector, text)
514
+ text.lines.each do |line|
515
+ action = detector.update(line)
516
+ assert_equal(:no_trace, action, "unexpected action on line: #{line}")
517
+ end
518
+ end
519
+
520
+ def check_exception(exception, detects_end)
521
+ detector = Fluent::ExceptionDetector.new
522
+ after_exc = detects_end ? :end_trace : :inside_trace
523
+ before_second_exc = detects_end ? :inside_trace : :start_trace
524
+ check_multiline(detector, :no_trace, :no_trace, 'This is not an exception.')
525
+ check_multiline(detector, :inside_trace, after_exc, exception)
526
+ check_multiline(detector, :no_trace, :no_trace, 'This is not an exception.')
527
+ check_multiline(detector, :inside_trace, after_exc, exception)
528
+ check_multiline(detector, before_second_exc, after_exc, exception)
529
+ end
530
+
531
+ def test_java
532
+ check_exception(JAVA_EXC, false)
533
+ check_exception(COMPLEX_JAVA_EXC, false)
534
+ end
535
+
536
+ def test_js
537
+ check_exception(NODE_JS_EXC, false)
538
+ check_exception(CLIENT_JS_EXC, false)
539
+ check_exception(V8_JS_EXC, false)
540
+ end
541
+
542
+ def test_csharp
543
+ check_exception(CSHARP_EXC, false)
544
+ end
545
+
546
+ def test_python
547
+ check_exception(PYTHON_EXC, true)
548
+ end
549
+
550
+ def test_php
551
+ check_exception(PHP_EXC, false)
552
+ check_exception(PHP_ON_GAE_EXC, true)
553
+ end
554
+
555
+ def test_go
556
+ check_exception(GO_EXC, false)
557
+ check_exception(GO_ON_GAE_EXC, false)
558
+ check_exception(GO_SIGNAL_EXC, false)
559
+ end
560
+
561
+ def test_ruby
562
+ check_exception(RUBY_EXC, false)
563
+ check_exception(RAILS_EXC, false)
564
+ end
565
+
566
+ def test_dart
567
+ check_exception(DART_ERR, false)
568
+ check_exception(DART_EXC, false)
569
+ check_exception(DART_ASYNC_ERR, false)
570
+ check_exception(DART_DIVIDE_BY_ZERO_ERR, false)
571
+ check_exception(DART_ARGUMENT_ERR, false)
572
+ check_exception(DART_RANGE_ERR, false)
573
+ check_exception(DART_READ_STATIC_ERR, false)
574
+ check_exception(DART_UNIMPLEMENTED_ERROR, false)
575
+ check_exception(DART_UNSUPPORTED_ERR, false)
576
+ check_exception(DART_CONCURRENT_MODIFICATION_ERR, false)
577
+ check_exception(DART_OOM_ERR, false)
578
+ check_exception(DART_STACK_OVERFLOW_ERR, false)
579
+ check_exception(DART_FALLTHROUGH_ERR, false)
580
+ check_exception(DART_TYPE_ERR, false)
581
+ check_exception(DART_FORMAT_ERR, false)
582
+ check_exception(DART_FORMAT_WITH_CODE_ERR, false)
583
+ check_exception(DART_NO_METHOD_ERR, false)
584
+ check_exception(DART_NO_METHOD_GLOBAL_ERR, false)
585
+ check_exception(DART_ASSERTION_ERR, false)
586
+ check_exception(DART_ABSTRACT_CLASS_ERR, false)
587
+ end
588
+
589
+ def test_mixed_languages
590
+ check_exception(JAVA_EXC, false)
591
+ check_exception(PYTHON_EXC, true)
592
+ check_exception(COMPLEX_JAVA_EXC, false)
593
+ check_exception(NODE_JS_EXC, false)
594
+ check_exception(PHP_EXC, false)
595
+ check_exception(PHP_ON_GAE_EXC, true)
596
+ check_exception(CLIENT_JS_EXC, false)
597
+ check_exception(GO_EXC, false)
598
+ check_exception(GO_ON_GAE_EXC, false)
599
+ check_exception(GO_SIGNAL_EXC, false)
600
+ check_exception(CSHARP_EXC, false)
601
+ check_exception(V8_JS_EXC, false)
602
+ check_exception(RUBY_EXC, false)
603
+ check_exception(DART_ERR, false)
604
+ check_exception(DART_EXC, false)
605
+ check_exception(DART_ASYNC_ERR, false)
606
+ check_exception(DART_DIVIDE_BY_ZERO_ERR, false)
607
+ check_exception(DART_ARGUMENT_ERR, false)
608
+ check_exception(DART_RANGE_ERR, false)
609
+ check_exception(DART_READ_STATIC_ERR, false)
610
+ check_exception(DART_UNIMPLEMENTED_ERROR, false)
611
+ check_exception(DART_UNSUPPORTED_ERR, false)
612
+ check_exception(DART_CONCURRENT_MODIFICATION_ERR, false)
613
+ check_exception(DART_OOM_ERR, false)
614
+ check_exception(DART_STACK_OVERFLOW_ERR, false)
615
+ check_exception(DART_FALLTHROUGH_ERR, false)
616
+ check_exception(DART_TYPE_ERR, false)
617
+ check_exception(DART_FORMAT_ERR, false)
618
+ check_exception(DART_FORMAT_WITH_CODE_ERR, false)
619
+ check_exception(DART_NO_METHOD_ERR, false)
620
+ check_exception(DART_NO_METHOD_GLOBAL_ERR, false)
621
+ check_exception(DART_ASSERTION_ERR, false)
622
+ check_exception(DART_ABSTRACT_CLASS_ERR, false)
623
+ end
624
+
625
+ def test_reset
626
+ detector = Fluent::ExceptionDetector.new
627
+
628
+ check_multiline(detector, :inside_trace, :inside_trace, JAVA_EXC_PART1)
629
+ check_multiline(detector, :inside_trace, :inside_trace, JAVA_EXC_PART2)
630
+
631
+ check_multiline(detector, :start_trace, :inside_trace, JAVA_EXC_PART1)
632
+ detector.reset
633
+ check_no_multiline(detector, JAVA_EXC_PART2)
634
+ end
635
+
636
+ def feed_lines(buffer, *messages)
637
+ messages.each do |m|
638
+ m.each_line do |line|
639
+ buffer.push(0, line)
640
+ end
641
+ buffer.flush
642
+ end
643
+ end
644
+
645
+ Struct.new('TestBufferScenario', :desc, :languages, :input, :expected)
646
+
647
+ def buffer_scenario(desc, languages, input, expected)
648
+ Struct::TestBufferScenario.new(desc, languages, input, expected)
649
+ end
650
+
651
+ def test_buffer
652
+ [
653
+ buffer_scenario('mixed languages',
654
+ [:all],
655
+ [JAVA_EXC, ARBITRARY_TEXT, PYTHON_EXC, GO_EXC],
656
+ [JAVA_EXC] + ARBITRARY_TEXT.lines + [PYTHON_EXC, GO_EXC]),
657
+ buffer_scenario('single language',
658
+ [:go],
659
+ [JAVA_EXC, ARBITRARY_TEXT, GO_EXC],
660
+ JAVA_EXC.lines + ARBITRARY_TEXT.lines + [GO_EXC]),
661
+ buffer_scenario('some exceptions from non-configured languages',
662
+ [:python],
663
+ [JAVA_EXC, PYTHON_EXC, GO_EXC],
664
+ JAVA_EXC.lines + [PYTHON_EXC] + GO_EXC.lines),
665
+ buffer_scenario('all exceptions from non-configured languages',
666
+ [:ruby],
667
+ [JAVA_EXC, PYTHON_EXC, GO_EXC],
668
+ JAVA_EXC.lines + PYTHON_EXC.lines + GO_EXC.lines)
669
+ ].each do |s|
670
+ out = []
671
+ buffer = Fluent::TraceAccumulator.new(nil,
672
+ s.languages) { |_, m| out << m }
673
+ feed_lines(buffer, *s.input)
674
+ assert_equal(s.expected, out, s.desc)
675
+ end
676
+ end
677
+
678
+ def feed_json(buffer, message_field, messages)
679
+ messages.each do |m|
680
+ m.each_line do |line|
681
+ buffer.push(0, message_field => line)
682
+ end
683
+ buffer.flush
684
+ end
685
+ end
686
+
687
+ def expected_json(message_field, messages)
688
+ messages.collect { |m| { message_field => [m].flatten.join } }
689
+ end
690
+
691
+ Struct.new('TestJsonScenario',
692
+ :desc, :configured_field, :actual_field, :input, :output)
693
+
694
+ def json_scenario(desc, configured_field, actual_field, input, output)
695
+ Struct::TestJsonScenario.new(desc, configured_field, actual_field,
696
+ input, output)
697
+ end
698
+
699
+ def test_json_messages
700
+ [
701
+ json_scenario('User-defined message field', 'mydata', 'mydata',
702
+ [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC],
703
+ [PYTHON_EXC] + ARBITRARY_TEXT.lines + [GO_EXC]),
704
+ json_scenario('Default message field "message"', '', 'message',
705
+ [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC],
706
+ [PYTHON_EXC] + ARBITRARY_TEXT.lines + [GO_EXC]),
707
+ json_scenario('Default message field "log"', '', 'log',
708
+ [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC],
709
+ [PYTHON_EXC] + ARBITRARY_TEXT.lines + [GO_EXC]),
710
+ json_scenario('Wrongly defined message field', 'doesnotexist', 'mydata',
711
+ [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC],
712
+ PYTHON_EXC.lines + ARBITRARY_TEXT.lines + GO_EXC.lines),
713
+ json_scenario('Undefined message field', '', 'mydata',
714
+ [PYTHON_EXC, ARBITRARY_TEXT, GO_EXC],
715
+ PYTHON_EXC.lines + ARBITRARY_TEXT.lines + GO_EXC.lines)
716
+ ].each do |s|
717
+ out = []
718
+ buffer = Fluent::TraceAccumulator.new(s.configured_field,
719
+ [:all]) { |_, m| out << m }
720
+ feed_json(buffer, s.actual_field, s.input)
721
+ assert_equal(expected_json(s.actual_field, s.output), out, s.desc)
722
+ end
723
+ end
724
+
725
+ def test_max_lines_limit
726
+ # Limit is equal to the first part of the exception and forces it to be
727
+ # flushed before the rest of the exception is processed.
728
+ max_lines = JAVA_EXC_PART1.lines.length
729
+ out = []
730
+ buffer = Fluent::TraceAccumulator.new(nil,
731
+ [:all],
732
+ max_lines: max_lines) do |_, m|
733
+ out << m
734
+ end
735
+ feed_lines(buffer, JAVA_EXC)
736
+ assert_equal([JAVA_EXC_PART1] + JAVA_EXC_PART2.lines, out)
737
+ end
738
+
739
+ def test_high_max_bytes_limit
740
+ # Limit is just too small to add one more line to the buffered first part of
741
+ # the exception.
742
+ max_bytes = JAVA_EXC_PART1.length + JAVA_EXC_PART2.lines[0].length - 1
743
+ out = []
744
+ buffer = Fluent::TraceAccumulator.new(nil,
745
+ [:all],
746
+ max_bytes: max_bytes) do |_, m|
747
+ out << m
748
+ end
749
+ feed_lines(buffer, JAVA_EXC)
750
+ # Check that the trace is flushed after the first part.
751
+ assert_equal([JAVA_EXC_PART1] + JAVA_EXC_PART2.lines, out)
752
+ end
753
+
754
+ def test_low_max_bytes_limit
755
+ # Limit is exceeded by the character that follows the buffered first part of
756
+ # the exception.
757
+ max_bytes = JAVA_EXC_PART1.length
758
+ out = []
759
+ buffer = Fluent::TraceAccumulator.new(nil,
760
+ [:all],
761
+ max_bytes: max_bytes) do |_, m|
762
+ out << m
763
+ end
764
+ feed_lines(buffer, JAVA_EXC)
765
+ # Check that the trace is flushed after the first part.
766
+ assert_equal([JAVA_EXC_PART1] + JAVA_EXC_PART2.lines, out)
767
+ end
768
+ end