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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE +3 -0
- data/lib/sqreen/actions.rb +11 -337
- data/lib/sqreen/actions/base.rb +110 -0
- data/lib/sqreen/actions/block_ip.rb +32 -0
- data/lib/sqreen/actions/block_user.rb +44 -0
- data/lib/sqreen/actions/ip_range_indexed_action_class.rb +36 -0
- data/lib/sqreen/actions/ip_ranges_index.rb +36 -0
- data/lib/sqreen/actions/redirect_ip.rb +40 -0
- data/lib/sqreen/actions/redirect_user.rb +45 -0
- data/lib/sqreen/actions/repository.rb +24 -0
- data/lib/sqreen/actions/unknown_action_type.rb +16 -0
- data/lib/sqreen/actions/user_action_class.rb +41 -0
- data/lib/sqreen/agent.rb +4 -1
- data/lib/sqreen/attack_blocked.rb +17 -0
- data/lib/sqreen/binding_accessor.rb +9 -102
- data/lib/sqreen/binding_accessor/path_elem.rb +8 -0
- data/lib/sqreen/binding_accessor/transforms.rb +107 -0
- data/lib/sqreen/capped_queue.rb +2 -0
- data/lib/sqreen/{callbacks.rb → cb.rb} +1 -53
- data/lib/sqreen/{callback_tree.rb → cb_tree.rb} +2 -2
- data/lib/sqreen/condition_evaluator.rb +22 -5
- data/lib/sqreen/configuration.rb +5 -0
- data/lib/sqreen/default_cb.rb +20 -0
- data/lib/sqreen/deferred_logger.rb +63 -0
- data/lib/sqreen/deliveries.rb +10 -0
- data/lib/sqreen/deliveries/batch.rb +7 -1
- data/lib/sqreen/deliveries/simple.rb +5 -0
- data/lib/sqreen/dependency/detector.rb +1 -1
- data/lib/sqreen/dependency/libsqreen.rb +28 -0
- data/lib/sqreen/dependency/rails.rb +4 -0
- data/lib/sqreen/dependency/sinatra.rb +47 -14
- data/lib/sqreen/error_handling_middleware.rb +30 -0
- data/lib/sqreen/event.rb +2 -0
- data/lib/sqreen/events/attack.rb +2 -0
- data/lib/sqreen/events/request_record.rb +11 -56
- data/lib/sqreen/exception.rb +9 -40
- data/lib/sqreen/formatter_with_tid.rb +45 -0
- data/lib/sqreen/framework_cb.rb +28 -0
- data/lib/sqreen/frameworks.rb +7 -0
- data/lib/sqreen/frameworks/generic.rb +20 -2
- data/lib/sqreen/frameworks/rails.rb +2 -0
- data/lib/sqreen/frameworks/request_recorder.rb +3 -0
- data/lib/sqreen/frameworks/sinatra.rb +2 -0
- data/lib/sqreen/frameworks/sqreen_test.rb +2 -0
- data/lib/sqreen/instrumentation.rb +5 -5
- data/lib/sqreen/invalid_signature_exception.rb +8 -0
- data/lib/{sqreen-alt.rb → sqreen/js.rb} +6 -1
- data/lib/sqreen/js/call_context.rb +10 -0
- data/lib/sqreen/js/context_pool.rb +60 -0
- data/lib/sqreen/js/exec_js_runnable.rb +20 -0
- data/lib/sqreen/js/execjs_adapter.rb +6 -47
- data/lib/sqreen/js/executable_js.rb +12 -0
- data/lib/sqreen/js/js_service.rb +2 -22
- data/lib/sqreen/js/js_service_adapter.rb +18 -0
- data/lib/sqreen/js/mini_racer_adapter.rb +6 -180
- data/lib/sqreen/js/mini_racer_executable_js.rb +142 -0
- data/lib/sqreen/js/thread_local_exec_js_runnable.rb +47 -0
- data/lib/sqreen/log.rb +8 -188
- data/lib/sqreen/logger.rb +83 -0
- data/lib/sqreen/metrics_store.rb +3 -11
- data/lib/sqreen/metrics_store/already_registered_metric.rb +11 -0
- data/lib/sqreen/metrics_store/unknown_metric.rb +11 -0
- data/lib/sqreen/metrics_store/unregistered_metric.rb +11 -0
- data/lib/sqreen/middleware.rb +0 -34
- data/lib/sqreen/mono_time.rb +2 -0
- data/lib/sqreen/node.rb +44 -0
- data/lib/sqreen/not_implemented_yet.rb +8 -0
- data/lib/sqreen/null_logger.rb +24 -0
- data/lib/sqreen/payload_creator.rb +2 -19
- data/lib/sqreen/payload_creator/header_section.rb +28 -0
- data/lib/sqreen/prefix.rb +33 -0
- data/lib/sqreen/rails_middleware.rb +14 -0
- data/lib/sqreen/remote_command.rb +1 -8
- data/lib/sqreen/remote_command/failure_output.rb +11 -0
- data/lib/sqreen/rules.rb +32 -2
- data/lib/sqreen/{rule_attributes.rb → rules/attrs.rb} +0 -0
- data/lib/sqreen/{rules_callbacks/sdk_auth_track.rb → rules/auth_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/binding_accessor_matcher.rb → rules/binding_accessor_matcher_cb.rb} +4 -8
- data/lib/sqreen/{rules_callbacks → rules}/binding_accessor_metrics.rb +1 -1
- data/lib/sqreen/{rules_callbacks/blacklist_ips.rb → rules/blacklist_ips_cb.rb} +3 -2
- data/lib/sqreen/{rules_callbacks → rules}/count_http_codes.rb +2 -2
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches.rb → rules/crawler_user_agent_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/crawler_user_agent_matches_metrics.rb → rules/crawler_user_agent_matches_metrics_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/custom_error.rb → rules/custom_error_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/devise_auth_track.rb → rules/devise_auth_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/devise_signup_track.rb → rules/devise_signup_track_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/execjs.rb → rules/execjs_cb.rb} +49 -50
- data/lib/sqreen/{rules_callbacks/headers_insert.rb → rules/headers_insert_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks → rules}/matcher_rule.rb +2 -2
- data/lib/sqreen/{rules_callbacks/not_found.rb → rules/not_found_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks/rails_parameters.rb → rules/rails_parameters_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks → rules}/record_request_context.rb +1 -1
- data/lib/sqreen/{rules_callbacks/regexp_rule.rb → rules/regexp_rule_cb.rb} +1 -1
- data/lib/sqreen/{rule_callback.rb → rules/rule_cb.rb} +2 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_req_start_actions.rb +4 -2
- data/lib/sqreen/{rules_callbacks → rules}/run_user_actions.rb +1 -1
- data/lib/sqreen/{rules_callbacks/shell_env.rb → rules/shell_env_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/sdk_signup_track.rb → rules/signup_track_cb.rb} +2 -2
- data/lib/sqreen/rules/update_request_context.rb +20 -0
- data/lib/sqreen/{rules_callbacks/url_matches.rb → rules/url_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/user_agent_matches.rb → rules/user_agent_matches_cb.rb} +1 -1
- data/lib/sqreen/{rules_callbacks/waf.rb → rules/waf_cb.rb} +10 -14
- data/lib/sqreen/{rules_callbacks/reflected_xss.rb → rules/xss_cb.rb} +10 -7
- data/lib/sqreen/run_when_called_cb.rb +21 -0
- data/lib/sqreen/runtime_infos.rb +2 -9
- data/lib/sqreen/sensitive_data_redactor.rb +111 -0
- data/lib/sqreen/signature_verifier.rb +20 -0
- data/lib/sqreen/sinatra_middleware.rb +14 -0
- data/lib/sqreen/{rules_signature.rb → sqreen_signed_verifier.rb} +5 -17
- data/lib/sqreen/token_invalid_exception.rb +8 -0
- data/lib/sqreen/token_not_found_exception.rb +9 -0
- data/lib/sqreen/trie.rb +3 -64
- data/lib/sqreen/unauthorized.rb +8 -0
- data/lib/sqreen/util.rb +2 -0
- data/lib/sqreen/util/capped_array.rb +33 -0
- data/lib/sqreen/util/capped_hash.rb +39 -0
- data/lib/sqreen/util/capped_string.rb +24 -0
- data/lib/sqreen/util/capper.rb +65 -0
- data/lib/sqreen/version.rb +1 -1
- data/lib/sqreen/waf_error.rb +18 -0
- metadata +87 -35
- data/lib/sqreen/rules_callbacks.rb +0 -35
- 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
|
data/lib/sqreen/log.rb
CHANGED
|
@@ -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
|