sqreen 1.18.2-java → 1.18.3-java

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/LICENSE +3 -0
  4. data/lib/sqreen/actions.rb +11 -337
  5. data/lib/sqreen/actions/base.rb +110 -0
  6. data/lib/sqreen/actions/block_ip.rb +32 -0
  7. data/lib/sqreen/actions/block_user.rb +44 -0
  8. data/lib/sqreen/actions/ip_range_indexed_action_class.rb +36 -0
  9. data/lib/sqreen/actions/ip_ranges_index.rb +36 -0
  10. data/lib/sqreen/actions/redirect_ip.rb +40 -0
  11. data/lib/sqreen/actions/redirect_user.rb +45 -0
  12. data/lib/sqreen/actions/repository.rb +24 -0
  13. data/lib/sqreen/actions/unknown_action_type.rb +16 -0
  14. data/lib/sqreen/actions/user_action_class.rb +41 -0
  15. data/lib/sqreen/agent.rb +4 -1
  16. data/lib/sqreen/attack_blocked.rb +17 -0
  17. data/lib/sqreen/binding_accessor.rb +9 -102
  18. data/lib/sqreen/binding_accessor/path_elem.rb +8 -0
  19. data/lib/sqreen/binding_accessor/transforms.rb +107 -0
  20. data/lib/sqreen/capped_queue.rb +2 -0
  21. data/lib/sqreen/{callbacks.rb → cb.rb} +1 -53
  22. data/lib/sqreen/{callback_tree.rb → cb_tree.rb} +2 -2
  23. data/lib/sqreen/condition_evaluator.rb +22 -5
  24. data/lib/sqreen/configuration.rb +5 -0
  25. data/lib/sqreen/default_cb.rb +20 -0
  26. data/lib/sqreen/deferred_logger.rb +63 -0
  27. data/lib/sqreen/deliveries.rb +10 -0
  28. data/lib/sqreen/deliveries/batch.rb +7 -1
  29. data/lib/sqreen/deliveries/simple.rb +5 -0
  30. data/lib/sqreen/dependency/detector.rb +1 -1
  31. data/lib/sqreen/dependency/libsqreen.rb +28 -0
  32. data/lib/sqreen/dependency/rails.rb +4 -0
  33. data/lib/sqreen/dependency/sinatra.rb +47 -14
  34. data/lib/sqreen/error_handling_middleware.rb +30 -0
  35. data/lib/sqreen/event.rb +2 -0
  36. data/lib/sqreen/events/attack.rb +2 -0
  37. data/lib/sqreen/events/request_record.rb +11 -56
  38. data/lib/sqreen/exception.rb +9 -40
  39. data/lib/sqreen/formatter_with_tid.rb +45 -0
  40. data/lib/sqreen/framework_cb.rb +28 -0
  41. data/lib/sqreen/frameworks.rb +7 -0
  42. data/lib/sqreen/frameworks/generic.rb +20 -2
  43. data/lib/sqreen/frameworks/rails.rb +2 -0
  44. data/lib/sqreen/frameworks/request_recorder.rb +3 -0
  45. data/lib/sqreen/frameworks/sinatra.rb +2 -0
  46. data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
  47. data/lib/sqreen/instrumentation.rb +5 -5
  48. data/lib/sqreen/invalid_signature_exception.rb +8 -0
  49. data/lib/{sqreen-alt.rb → sqreen/js.rb} +6 -1
  50. data/lib/sqreen/js/call_context.rb +10 -0
  51. data/lib/sqreen/js/context_pool.rb +60 -0
  52. data/lib/sqreen/js/exec_js_runnable.rb +20 -0
  53. data/lib/sqreen/js/execjs_adapter.rb +6 -47
  54. data/lib/sqreen/js/executable_js.rb +12 -0
  55. data/lib/sqreen/js/js_service.rb +2 -22
  56. data/lib/sqreen/js/js_service_adapter.rb +18 -0
  57. data/lib/sqreen/js/mini_racer_adapter.rb +6 -180
  58. data/lib/sqreen/js/mini_racer_executable_js.rb +142 -0
  59. data/lib/sqreen/js/thread_local_exec_js_runnable.rb +47 -0
  60. data/lib/sqreen/log.rb +8 -188
  61. data/lib/sqreen/logger.rb +83 -0
  62. data/lib/sqreen/metrics_store.rb +3 -11
  63. data/lib/sqreen/metrics_store/already_registered_metric.rb +11 -0
  64. data/lib/sqreen/metrics_store/unknown_metric.rb +11 -0
  65. data/lib/sqreen/metrics_store/unregistered_metric.rb +11 -0
  66. data/lib/sqreen/middleware.rb +0 -34
  67. data/lib/sqreen/mono_time.rb +2 -0
  68. data/lib/sqreen/node.rb +44 -0
  69. data/lib/sqreen/not_implemented_yet.rb +8 -0
  70. data/lib/sqreen/null_logger.rb +24 -0
  71. data/lib/sqreen/payload_creator.rb +2 -19
  72. data/lib/sqreen/payload_creator/header_section.rb +28 -0
  73. data/lib/sqreen/prefix.rb +33 -0
  74. data/lib/sqreen/rails_middleware.rb +14 -0
  75. data/lib/sqreen/remote_command.rb +1 -8
  76. data/lib/sqreen/remote_command/failure_output.rb +11 -0
  77. data/lib/sqreen/rules.rb +32 -2
  78. data/lib/sqreen/{rule_attributes.rb → rules/attrs.rb} +0 -0
  79. data/lib/sqreen/{rules_callbacks/sdk_auth_track.rb → rules/auth_track_cb.rb} +2 -2
  80. data/lib/sqreen/{rules_callbacks/binding_accessor_matcher.rb → rules/binding_accessor_matcher_cb.rb} +4 -8
  81. data/lib/sqreen/{rules_callbacks → rules}/binding_accessor_metrics.rb +1 -1
  82. data/lib/sqreen/{rules_callbacks/blacklist_ips.rb → rules/blacklist_ips_cb.rb} +3 -2
  83. data/lib/sqreen/{rules_callbacks → rules}/count_http_codes.rb +2 -2
  84. data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches.rb → rules/crawler_user_agent_matches_cb.rb} +1 -1
  85. data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches_metrics.rb → rules/crawler_user_agent_matches_metrics_cb.rb} +1 -1
  86. data/lib/sqreen/{rules_callbacks/custom_error.rb → rules/custom_error_cb.rb} +1 -1
  87. data/lib/sqreen/{rules_callbacks/devise_auth_track.rb → rules/devise_auth_track_cb.rb} +2 -2
  88. data/lib/sqreen/{rules_callbacks/devise_signup_track.rb → rules/devise_signup_track_cb.rb} +2 -2
  89. data/lib/sqreen/{rules_callbacks/execjs.rb → rules/execjs_cb.rb} +49 -50
  90. data/lib/sqreen/{rules_callbacks/headers_insert.rb → rules/headers_insert_cb.rb} +1 -1
  91. data/lib/sqreen/{rules_callbacks → rules}/matcher_rule.rb +2 -2
  92. data/lib/sqreen/{rules_callbacks/not_found.rb → rules/not_found_cb.rb} +2 -2
  93. data/lib/sqreen/{rules_callbacks/rails_parameters.rb → rules/rails_parameters_cb.rb} +1 -1
  94. data/lib/sqreen/{rules_callbacks → rules}/record_request_context.rb +1 -1
  95. data/lib/sqreen/{rules_callbacks/regexp_rule.rb → rules/regexp_rule_cb.rb} +1 -1
  96. data/lib/sqreen/{rule_callback.rb → rules/rule_cb.rb} +2 -2
  97. data/lib/sqreen/{rules_callbacks → rules}/run_req_start_actions.rb +4 -2
  98. data/lib/sqreen/{rules_callbacks → rules}/run_user_actions.rb +1 -1
  99. data/lib/sqreen/{rules_callbacks/shell_env.rb → rules/shell_env_cb.rb} +1 -1
  100. data/lib/sqreen/{rules_callbacks/sdk_signup_track.rb → rules/signup_track_cb.rb} +2 -2
  101. data/lib/sqreen/rules/update_request_context.rb +20 -0
  102. data/lib/sqreen/{rules_callbacks/url_matches.rb → rules/url_matches_cb.rb} +1 -1
  103. data/lib/sqreen/{rules_callbacks/user_agent_matches.rb → rules/user_agent_matches_cb.rb} +1 -1
  104. data/lib/sqreen/{rules_callbacks/waf.rb → rules/waf_cb.rb} +10 -14
  105. data/lib/sqreen/{rules_callbacks/reflected_xss.rb → rules/xss_cb.rb} +10 -7
  106. data/lib/sqreen/run_when_called_cb.rb +21 -0
  107. data/lib/sqreen/runtime_infos.rb +2 -9
  108. data/lib/sqreen/sensitive_data_redactor.rb +111 -0
  109. data/lib/sqreen/signature_verifier.rb +20 -0
  110. data/lib/sqreen/sinatra_middleware.rb +14 -0
  111. data/lib/sqreen/{rules_signature.rb → sqreen_signed_verifier.rb} +5 -17
  112. data/lib/sqreen/token_invalid_exception.rb +8 -0
  113. data/lib/sqreen/token_not_found_exception.rb +9 -0
  114. data/lib/sqreen/trie.rb +3 -64
  115. data/lib/sqreen/unauthorized.rb +8 -0
  116. data/lib/sqreen/util.rb +2 -0
  117. data/lib/sqreen/util/capped_array.rb +33 -0
  118. data/lib/sqreen/util/capped_hash.rb +39 -0
  119. data/lib/sqreen/util/capped_string.rb +24 -0
  120. data/lib/sqreen/util/capper.rb +65 -0
  121. data/lib/sqreen/version.rb +1 -1
  122. data/lib/sqreen/waf_error.rb +18 -0
  123. metadata +87 -35
  124. data/lib/sqreen/rules_callbacks.rb +0 -35
  125. data/lib/sqreen/rules_callbacks/inspect_rule.rb +0 -25
@@ -0,0 +1,142 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
+
4
+ # TODO: => Sqreen::JS:MiniRacer
5
+ # TODO: remove class vars
6
+
7
+ require 'sqreen/log'
8
+
9
+ module Sqreen
10
+ module Js
11
+ class MiniRacerExecutableJs < ExecutableJs
12
+ @@ctx_defined = false # rubocop:disable Style/ClassVars
13
+
14
+ def ctx_defined?
15
+ @@ctx_defined
16
+ end
17
+
18
+ def define_ctx!
19
+ @@ctx_defined = true # rubocop:disable Style/ClassVars
20
+ end
21
+
22
+ def initialize(pool, code, vendored)
23
+ @pool = pool
24
+ @code = code
25
+ @code_id = self.class.code_id(code)
26
+
27
+ @module = vendored ? Sqreen::MiniRacer : MiniRacer
28
+
29
+ mod = vendored ? Sqreen::MiniRacer : MiniRacer
30
+
31
+ return if ctx_defined?
32
+
33
+ self.class.define_sqreen_context(mod)
34
+ define_ctx!
35
+ end
36
+
37
+ def run_js_cb(cb_name, budget, arguments)
38
+ @pool.with_context do |ctx|
39
+ if ctx.code_failed?(@code_id)
40
+ Sqreen.log.debug do
41
+ "Skipping execution of callback #{cb_name} (code md5 #{@code_id})" \
42
+ " due to prev failure of definition evaluation"
43
+ end
44
+ return nil
45
+ end
46
+
47
+ ctx.add_code(@code_id, @code) unless ctx.code?(@code_id)
48
+
49
+ # mini_racer expects timeout to be in ms
50
+ ctx.timeout = budget ? budget * 1000.0 : nil
51
+ begin
52
+ ctx.call("sqreen_#{@code_id}_#{cb_name}", *arguments)
53
+ rescue @module::ScriptTerminatedError
54
+ Sqreen.log.debug "ScriptTerminatedError/#{cb_name}"
55
+ nil
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.code_id(code)
61
+ Digest::MD5.hexdigest(code)
62
+ end
63
+
64
+ class << self
65
+ def define_sqreen_context(modoole)
66
+ # Context specialized for Sqreen usage
67
+ Sqreen::Js.const_set 'SqreenContext', Class.new(modoole.const_get('Context'))
68
+ SqreenContext.class_eval do
69
+ attr_accessor :gc_threshold_in_bytes
70
+ attr_accessor :gc_load
71
+ attr_writer :timeout
72
+
73
+ def code?(code_id)
74
+ return false unless @code_ids
75
+ @code_ids.include?(code_id)
76
+ end
77
+
78
+ def code_failed?(code_id)
79
+ return false unless @failed_code_ids
80
+ @failed_code_ids.include?(code_id)
81
+ end
82
+
83
+ def add_code(code_id, code)
84
+ # It's important that the definition is run in its own scope (by executing it inside an anonymous function)
85
+ # Otherwise some auxiliary functions that the backend server sends will collide the name
86
+ # Because they're defined with `var`, running the definitions inside a function is enough
87
+ eval_unsafe "(function() { #{code} })()"
88
+ transf_global_funcs code_id
89
+ @code_ids ||= Set.new
90
+ @code_ids << code_id
91
+ rescue StandardError
92
+ @failed_code_ids ||= Set.new
93
+ @failed_code_ids << code_id
94
+ raise
95
+ end
96
+
97
+ def eval_unsafe(str, filename = nil, timeoutv = nil)
98
+ # Beware, timeout could be kept in the context
99
+ # if perf cap is removed after having been activated
100
+ # As it's unused by execjscb we are not cleaning it
101
+ return super(str, filename) if timeoutv.nil?
102
+ return if timeoutv <= 0.0
103
+ timeoutv *= 1000 # Timeout are currently expressed in seconds
104
+ @timeout = timeoutv
105
+ @eval_thread = Thread.current
106
+ timeout do
107
+ super(str, filename)
108
+ end
109
+ end
110
+
111
+ def possibly_gc
112
+ @gc_threshold_in_bytes ||= DEFAULT_GC_THRESHOLD
113
+ @gc_load ||= 0
114
+
115
+ # garbage collections max 1 in every 4 calls (avg)
116
+ if heap_stats[:total_heap_size] > @gc_threshold_in_bytes
117
+ low_memory_notification
118
+ @gc_load += 4
119
+ else
120
+ @gc_load = [0, @gc_load - 1].max
121
+ end
122
+ end
123
+
124
+ private
125
+
126
+ def transf_global_funcs(code_id)
127
+ # Multiple callbacks may share the same name. In order to avoid collisions, we rename them here.
128
+ eval_unsafe <<-JS
129
+ Object.keys(this).forEach(name => {
130
+ if (typeof this[name] === "function" && !name.startsWith("sqreen_")) {
131
+ this['sqreen_#{code_id}_' + name] = this[name];
132
+ this[name] = undefined;
133
+ }
134
+ });
135
+ JS
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
+
4
+ # TODO: => Sqreen::JS:ExecJS
5
+
6
+ require 'sqreen/js/executable_js'
7
+
8
+ module Sqreen
9
+ module Js
10
+ class ThreadLocalExecJsRunnable < ExecutableJs
11
+ def initialize(code)
12
+ @code = code
13
+ @tl_key = "SQREEN_EXECJS_CONTEXT_#{object_id}".freeze
14
+ @runtimes = [] # place where to keep strong references
15
+ @runtimes_mutex = Mutex.new
16
+ end
17
+
18
+ def run_js_cb(cbname, _budget, arguments)
19
+ tl_exec_js_runnable.call(cbname, *arguments)
20
+ end
21
+
22
+ def with_runtimes_mutex
23
+ @runtimes_mutex.synchronize { yield }
24
+ end
25
+
26
+ private
27
+
28
+ def dispose_from_dead_threads
29
+ with_runtimes_mutex do
30
+ @runtimes.delete_if { |th, _runtime| !th.alive? }
31
+ end
32
+ end
33
+
34
+ def tl_exec_js_runnable
35
+ runnable = Thread.current[@tl_key]
36
+ return runnable if runnable && runnable.weakref_alive?
37
+
38
+ dispose_from_dead_threads
39
+ runtime = ExecJS.compile(@code)
40
+ with_runtimes_mutex do
41
+ @runtimes << [Thread.current, runtime]
42
+ end
43
+ Thread.current[@tl_key] = WeakRef.new(runtime)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,207 +1,27 @@
1
1
  # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
2
  # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
3
 
4
- require 'logger'
5
- require 'singleton'
6
-
7
4
  require 'sqreen/performance_notifications/log'
8
5
  require 'sqreen/performance_notifications/log_performance'
9
6
  require 'sqreen/configuration'
10
7
 
8
+ require 'sqreen/logger'
9
+ require 'sqreen/deferred_logger'
10
+
11
+ # TODO: fold into Sqreen::Logger
12
+
11
13
  module Sqreen
12
14
  def self.log_init
13
- @logger = Logger.new(
15
+ @logger = Sqreen::Logger.new(
14
16
  Sqreen.config_get(:log_level).to_s.upcase,
15
17
  Sqreen.config_get(:log_location)
16
18
  )
17
- DeferredLogger.instance.flush_to(@logger.instance_eval { @logger })
19
+ Sqreen::DeferredLogger.instance.flush_to(@logger.instance_eval { @logger })
18
20
  rescue => e
19
21
  warn "Sqreen logger exception: #{e}"
20
22
  end
21
23
 
22
24
  def self::log
23
- @logger || DeferredLogger.instance
24
- end
25
-
26
- # Ruby default formatter modified to display current thread_id
27
- class FormatterWithTid
28
- Format = "%s, [%s#%d.%s] %5s -- %s: %s\n".freeze
29
- DatetimeFormat = '%Y-%m-%dT%H:%M:%S.%6N '.freeze
30
-
31
- attr_accessor :datetime_format
32
-
33
- def initialize
34
- @datetime_format = nil
35
- end
36
-
37
- def call(severity, time, progname, msg)
38
- format(Format,
39
- severity[0..0], format_datetime(time), $$,
40
- Thread.current.object_id.to_s(36),
41
- severity, progname, msg2str(msg)
42
- )
43
- end
44
-
45
- private
46
-
47
- def format_datetime(time)
48
- time.strftime(DatetimeFormat)
49
- end
50
-
51
- def msg2str(msg)
52
- case msg
53
- when ::String
54
- msg
55
- when ::Exception
56
- "#{msg.message} (#{msg.class})\n" << (msg.backtrace || []).join("\n")
57
- else
58
- msg.inspect
59
- end
60
- end
61
- end
62
-
63
- # Wrapper class for sqreen logging
64
- class Logger
65
- SEVERITY_TO_METHOD = ::Logger::Severity.constants.each_with_object({}) do |s, h|
66
- h[::Logger::Severity.const_get(s)] = s.downcase
67
- end
68
-
69
- def initialize(desired_level, log_location, force_logger = nil)
70
- if force_logger
71
- @logger = force_logger
72
- else
73
- init_logger_output(log_location)
74
- end
75
- init_log_level(desired_level)
76
- enforce_log_format(@logger)
77
- create_error_logger
78
- end
79
-
80
- def debug(msg = nil, &block)
81
- @logger.debug(msg, &block)
82
- end
83
-
84
- def info(msg = nil, &block)
85
- @logger.info(msg, &block)
86
- end
87
-
88
- def warn(msg = nil, &block)
89
- @logger.warn(msg, &block)
90
- end
91
-
92
- def error(msg = nil, &block)
93
- @error_logger.error(msg, &block)
94
- @logger.error(msg, &block)
95
- end
96
-
97
- def add(severity, msg = nil, &block)
98
- send(SEVERITY_TO_METHOD[severity], msg, &block)
99
- end
100
-
101
- protected
102
-
103
- def init_logger_output(path)
104
- path = File.expand_path(path)
105
- if File.writable?(path) || File.writable?(File.dirname(path))
106
- @logger = ::Logger.new(path)
107
- else
108
- @logger = ::Logger.new(STDOUT)
109
- @logger.info("Cannot access #{path} for writing. Defaulting to stdout")
110
- end
111
- rescue => e
112
- @logger = ::Logger.new(STDOUT)
113
- @logger.error('Got error while trying to setting logger up, '\
114
- "falling back to stdout #{e.inspect}")
115
- end
116
-
117
- def init_log_level(level)
118
- log_level = ::Logger.const_get(level)
119
- @logger.level = log_level
120
- Sqreen::PerformanceNotifications::Log.enable if level == 'DEBUG'
121
- return if level != 'DEBUG' && !Sqreen.config_get(:report_perf)
122
- Sqreen::PerformanceNotifications::LogPerformance.enable
123
- end
124
-
125
- def create_error_logger
126
- @error_logger = Kernel.const_defined?('MiniTest') ? NullLogger.instance : ::Logger.new(STDERR)
127
- enforce_log_format(@error_logger)
128
- end
129
-
130
- def enforce_log_format(logger)
131
- logger.formatter = FormatterWithTid.new
132
- end
133
- end
134
-
135
- class NullLogger
136
- include Singleton
137
-
138
- def debug(_msg = nil); end
139
-
140
- def info(_msg = nil); end
141
-
142
- def warn(_msg = nil); end
143
-
144
- def error(_msg = nil); end
145
-
146
- def fatal(_msg = nil); end
147
-
148
- def add(_severity, _msg = nil); end
149
-
150
- def formatter=(_); end
151
- end
152
-
153
- class DeferredLogger
154
- include Singleton
155
-
156
- def initialize
157
- @buffer = StringIO.new
158
- @logger = ::Logger.new(@buffer)
159
- end
160
-
161
- def debug(msg = nil, &block)
162
- @logger.debug(msg, &block)
163
- end
164
-
165
- def info(msg = nil, &block)
166
- @logger.info(msg, &block)
167
- end
168
-
169
- def warn(msg = nil, &block)
170
- @logger.warn(msg, &block)
171
- end
172
-
173
- def error(msg = nil, &block)
174
- @logger.error(msg, &block)
175
- end
176
-
177
- def fatal(msg = nil, &block)
178
- @logger.error(msg, &block)
179
- end
180
-
181
- def add(severity, msg = nil, &block)
182
- send(Sqreen::Logger::SEVERITY_TO_METHOD[severity], msg, &block)
183
- end
184
-
185
- def formatter=(value)
186
- @logger.formatter = value
187
- end
188
-
189
- def flush_to(logger)
190
- logger.instance_eval { @logdev }.write(read).tap { reset }
191
- end
192
-
193
- private
194
-
195
- def read
196
- @buffer.rewind
197
- @buffer.read
198
- end
199
-
200
- def reset
201
- buffer = StringIO.new
202
- logger = ::Logger.new(buffer)
203
- logger.formatter = @logger.formatter
204
- @buffer, @logger = buffer, logger
205
- end
25
+ @logger || Sqreen::DeferredLogger.instance
206
26
  end
207
27
  end
@@ -0,0 +1,83 @@
1
+ # Copyright (c) 2015 Sqreen. All Rights Reserved.
2
+ # Please refer to our terms for more information: https://www.sqreen.com/terms.html
3
+
4
+ require 'logger'
5
+ require 'sqreen/log'
6
+ require 'sqreen/formatter_with_tid'
7
+ require 'sqreen/null_logger'
8
+
9
+ # TODO: inherit from ::Logger
10
+
11
+ module Sqreen
12
+ # Wrapper class for sqreen logging
13
+ class Logger
14
+ SEVERITY_TO_METHOD = ::Logger::Severity.constants.each_with_object({}) do |s, h|
15
+ h[::Logger::Severity.const_get(s)] = s.downcase
16
+ end
17
+
18
+ def initialize(desired_level, log_location, force_logger = nil)
19
+ if force_logger
20
+ @logger = force_logger
21
+ else
22
+ init_logger_output(log_location)
23
+ end
24
+ init_log_level(desired_level)
25
+ enforce_log_format(@logger)
26
+ create_error_logger
27
+ end
28
+
29
+ def debug(msg = nil, &block)
30
+ @logger.debug(msg, &block)
31
+ end
32
+
33
+ def info(msg = nil, &block)
34
+ @logger.info(msg, &block)
35
+ end
36
+
37
+ def warn(msg = nil, &block)
38
+ @logger.warn(msg, &block)
39
+ end
40
+
41
+ def error(msg = nil, &block)
42
+ @error_logger.error(msg, &block)
43
+ @logger.error(msg, &block)
44
+ end
45
+
46
+ def add(severity, msg = nil, &block)
47
+ send(SEVERITY_TO_METHOD[severity], msg, &block)
48
+ end
49
+
50
+ protected
51
+
52
+ def init_logger_output(path)
53
+ path = File.expand_path(path)
54
+ if File.writable?(path) || File.writable?(File.dirname(path))
55
+ @logger = ::Logger.new(path)
56
+ else
57
+ @logger = ::Logger.new(STDOUT)
58
+ @logger.info("Cannot access #{path} for writing. Defaulting to stdout")
59
+ end
60
+ rescue StandardError => e
61
+ @logger = ::Logger.new(STDOUT)
62
+ @logger.error('Got error while trying to setting logger up, '\
63
+ "falling back to stdout #{e.inspect}")
64
+ end
65
+
66
+ def init_log_level(level)
67
+ log_level = ::Logger.const_get(level)
68
+ @logger.level = log_level
69
+ Sqreen::PerformanceNotifications::Log.enable if level == 'DEBUG'
70
+ return if level != 'DEBUG' && !Sqreen.config_get(:report_perf)
71
+ Sqreen::PerformanceNotifications::LogPerformance.enable
72
+ end
73
+
74
+ def create_error_logger
75
+ @error_logger = Kernel.const_defined?('MiniTest') ? NullLogger.instance : ::Logger.new(STDERR)
76
+ enforce_log_format(@error_logger)
77
+ end
78
+
79
+ def enforce_log_format(logger)
80
+ logger.formatter = Sqreen::FormatterWithTid.new
81
+ end
82
+ end
83
+ end