sqreen 1.20.1 → 1.21.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sqreen/attack_detected.html +1 -2
- data/lib/sqreen/deliveries/batch.rb +8 -1
- data/lib/sqreen/ecosystem.rb +80 -0
- data/lib/sqreen/ecosystem/dispatch_table.rb +43 -0
- data/lib/sqreen/ecosystem/http/net_http.rb +51 -0
- data/lib/sqreen/ecosystem/http/rack_request.rb +38 -0
- data/lib/sqreen/ecosystem/loggable.rb +13 -0
- data/lib/sqreen/ecosystem/module_api.rb +30 -0
- data/lib/sqreen/ecosystem/module_api/event_listener.rb +18 -0
- data/lib/sqreen/ecosystem/module_api/instrumentation.rb +23 -0
- data/lib/sqreen/ecosystem/module_api/signal_producer.rb +26 -0
- data/lib/sqreen/ecosystem/module_api/tracing_push_down.rb +34 -0
- data/lib/sqreen/ecosystem/module_api/transaction_storage.rb +71 -0
- data/lib/sqreen/ecosystem/module_registry.rb +39 -0
- data/lib/sqreen/ecosystem/redis/redis_connection.rb +35 -0
- data/lib/sqreen/ecosystem/tracing/sampler.rb +160 -0
- data/lib/sqreen/ecosystem/tracing/sampling_configuration.rb +150 -0
- data/lib/sqreen/ecosystem/tracing/signals/tracing_client.rb +53 -0
- data/lib/sqreen/ecosystem/tracing/signals/tracing_server.rb +53 -0
- data/lib/sqreen/ecosystem/tracing_id_setup.rb +34 -0
- data/lib/sqreen/ecosystem/transaction_storage.rb +64 -0
- data/lib/sqreen/ecosystem_integration.rb +70 -0
- data/lib/sqreen/ecosystem_integration/around_callbacks.rb +89 -0
- data/lib/sqreen/ecosystem_integration/instrumentation_service.rb +38 -0
- data/lib/sqreen/ecosystem_integration/request_lifecycle_tracking.rb +56 -0
- data/lib/sqreen/ecosystem_integration/signal_consumption.rb +35 -0
- data/lib/sqreen/frameworks/generic.rb +15 -1
- data/lib/sqreen/graft/call.rb +9 -0
- data/lib/sqreen/legacy/old_event_submission_strategy.rb +7 -1
- data/lib/sqreen/remote_command.rb +3 -0
- data/lib/sqreen/runner.rb +19 -5
- data/lib/sqreen/session.rb +2 -0
- data/lib/sqreen/signals/conversions.rb +6 -1
- data/lib/sqreen/version.rb +1 -1
- metadata +32 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49a6c95ab34d19ae0f769e475ae67c2c3e4d19b17582ee09d8a6d231ac3d9150
|
4
|
+
data.tar.gz: ad1ea7a80f3582ba90ffc6aa1cef7040459c56f65ea4712a023923b8bc7801e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0da6438f20a00a84914db2bb06c24feab53e164feae1cb7d2af0b53afe24c5d5ea54a0cb68a8872a49aadedae4450de57e63da6a4f4a2ec21ac85eaa84c13acf
|
7
|
+
data.tar.gz: 3e75918e810529674e10d693fd2a62c0eeeeecb18bac06a25fdd686d29c45d55333abb0feea790ec1d89e29ce71097bd1de16c2d31d98a6219e985d806793008
|
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
<!-- Sorry, you’ve been blocked --><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>You've been blocked</title><style>a,body,div,h1,html,span{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}body{background:-webkit-radial-gradient(26% 19%,circle,#fff,#f4f7f9);background:radial-gradient(circle at 26% 19%,#fff,#f4f7f9);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;width:100%;min-height:100vh;line-height:1;flex-direction:column}h1,p,svg{display:block}svg{margin:0 auto 4vh}main{text-align:center;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;flex-direction:column}h1{font-family:sans-serif;font-weight:600;font-size:34px;color:#1e0936;line-height:1.2}p{font-size:18px;line-height:normal;color:#646464;font-family:sans-serif;font-weight:400}a{color:#4842b7}footer{width:100%;text-align:center}footer p{font-size:16px}</style></head><body><main><svg width="170px" height="193px" viewBox="0 0 170 193" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true"><g id="exports" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Artboard" transform="translate(-186.000000, -189.000000)"><g id="logo-cmyk-indigo" transform="translate(186.000000, 189.000000)"><g id="nest-cmyk-indigo"><ellipse id="sqreen" fill="#B0ACFF" cx="85" cy="96.5" rx="45.7692308" ry="45.7966102"></ellipse><path d="M78.4615385,175.749389 L78.4615385,102.2092 L13.1398162,64.4731256 L13.1398162,129.181112 L36.352167,115.771438 C37.9764468,119.873152 40.1038639,123.720553 42.6582364,127.237412 L18.5723996,141.151695 L78.4615385,175.749389 Z M91.5384615,175.749389 L151.4276,141.151695 L127.341764,127.237412 C129.896136,123.720553 132.023553,119.873152 133.647833,115.771438 L156.860184,129.181112 L156.860184,64.4731256 L91.5384615,102.2092 L91.5384615,175.749389 Z M18.0061522,52.1754237 L85,90.8774777 L151.993848,52.1754237 L91.5384615,17.2506105 L91.5384615,44.565949 C89.3964992,44.2986903 87.2143177,44.1610169 85,44.1610169 C82.7856823,44.1610169 80.6035008,44.2986903 78.4615385,44.565949 L78.4615385,17.2506105 L18.0061522,52.1754237 Z M90.8846156,1.76392358 L164.052491,44.0326866 C167.693904,46.1363149 169.937107,50.0239804 169.937107,54.231237 L169.937107,138.768763 C169.937107,142.97602 167.693904,146.863685 164.052491,148.967313 L90.8846156,191.236076 C87.2432028,193.339705 82.7567972,193.339705 79.1153844,191.236076 L5.94750871,148.967313 C2.30609589,146.863685 0.0628930904,142.97602 0.0628930904,138.768763 L0.0628930904,54.231237 C0.0628930904,50.0239804 2.30609589,46.1363149 5.94750871,44.0326866 L79.1153844,1.76392358 C82.7567972,-0.339704735 87.2432028,-0.339704735 90.8846156,1.76392358 Z" id="app" fill="#4842B7"></path></g></g></g></g></svg><h1>Sorry, you've been blocked</h1><p>Contact the website owner</p></main><footer><p>Security provided by <a href="https://www.sqreen.com/?utm_medium=block_page" target="_blank">Sqreen</a></p></footer></body></html>
|
@@ -13,6 +13,8 @@ require 'sqreen/events/attack'
|
|
13
13
|
require 'sqreen/events/remote_exception'
|
14
14
|
require 'sqreen/mono_time'
|
15
15
|
require 'sqreen/deliveries/simple'
|
16
|
+
require 'sqreen/kit/signals/signal'
|
17
|
+
require 'sqreen/kit/signals/trace'
|
16
18
|
|
17
19
|
module Sqreen
|
18
20
|
module Deliveries
|
@@ -58,7 +60,7 @@ module Sqreen
|
|
58
60
|
def post_batch_needed?(event)
|
59
61
|
now = Sqreen.time
|
60
62
|
# do not use any? {} due to side effects inside block
|
61
|
-
event_keys(event).map do |key|
|
63
|
+
event_keys(event).uniq.map do |key|
|
62
64
|
was = @first_seen[key]
|
63
65
|
@first_seen[key] ||= now
|
64
66
|
was.nil? || current_batch.size > max_batch || now > (was + max_staleness)
|
@@ -86,6 +88,7 @@ module Sqreen
|
|
86
88
|
res += event.observed.fetch(:sdk, []).select { |e|
|
87
89
|
e[0] == :track
|
88
90
|
}.map { |e| "sdk-track".freeze }
|
91
|
+
res += event.observed.fetch(:signals, []).map { "signal".freeze }
|
89
92
|
return res
|
90
93
|
end
|
91
94
|
|
@@ -97,6 +100,10 @@ module Sqreen
|
|
97
100
|
"rex-#{event.klass}"
|
98
101
|
when Sqreen::AggregatedMetric
|
99
102
|
"agg-metric"
|
103
|
+
when Sqreen::Kit::Signals::Signal
|
104
|
+
"signal"
|
105
|
+
when Sqreen::Kit::Signals::Trace
|
106
|
+
"signal"
|
100
107
|
end
|
101
108
|
end
|
102
109
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'sqreen/ecosystem/module_registry'
|
3
|
+
require 'sqreen/ecosystem/tracing/sampling_configuration'
|
4
|
+
require 'sqreen/ecosystem/transaction_storage'
|
5
|
+
require 'sqreen/ecosystem/tracing_id_setup'
|
6
|
+
require 'sqreen/ecosystem/module_api/tracing_push_down'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
# The API for the ecosystem client (together with the dispatch table)
|
10
|
+
module Ecosystem
|
11
|
+
class << self
|
12
|
+
def init(opts = {})
|
13
|
+
@registry = ModuleRegistry.new
|
14
|
+
register_modules(opts[:modules])
|
15
|
+
@registry.init_all
|
16
|
+
|
17
|
+
@tracing_id_setup = TracingIdSetup.new(@registry)
|
18
|
+
@tracing_id_setup.setup_modules
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset
|
22
|
+
instance_variables.each do |ia|
|
23
|
+
instance_variable_set(ia, nil)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# To be called by the Ecosystem client when a new transaction
|
28
|
+
# (generally: request) is started
|
29
|
+
# In the future, it's intended that request end/start detection be handled
|
30
|
+
# by the Ecosystem itself, so control will flow in the other direction,
|
31
|
+
# from the ecosystem to its client
|
32
|
+
def start_transaction
|
33
|
+
TransactionStorage.create_thread_local
|
34
|
+
end
|
35
|
+
|
36
|
+
def end_transaction
|
37
|
+
TransactionStorage.destroy_thread_local
|
38
|
+
end
|
39
|
+
|
40
|
+
# @param [String] tracing_id_prefix
|
41
|
+
# @param [Array<Hash{String=>Object}>] sampling_config
|
42
|
+
def configure_sampling(tracing_id_prefix, sampling_config)
|
43
|
+
@tracing_id_setup.tracing_id_prefix = tracing_id_prefix
|
44
|
+
built_samp_cfg = Tracing::SamplingConfiguration.new(sampling_config)
|
45
|
+
inject_sampling_config(built_samp_cfg)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def register_modules(modules)
|
51
|
+
return register_all_modules unless modules
|
52
|
+
|
53
|
+
modules.each { |mod| register mod }
|
54
|
+
end
|
55
|
+
|
56
|
+
def register_all_modules
|
57
|
+
# replace with something more magical?
|
58
|
+
require_relative 'ecosystem/http/rack_request'
|
59
|
+
register Http::RackRequest.new
|
60
|
+
|
61
|
+
require_relative 'ecosystem/http/net_http'
|
62
|
+
register Http::NetHttp.new
|
63
|
+
|
64
|
+
require_relative 'ecosystem/redis/redis_connection'
|
65
|
+
register Redis::RedisConnection.new
|
66
|
+
end
|
67
|
+
|
68
|
+
def register(mod)
|
69
|
+
@registry.register mod
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param [Sqreen::Ecosystem::SamplingConfiguration] config
|
73
|
+
def inject_sampling_config(config)
|
74
|
+
@registry.each_module(Sqreen::Ecosystem::ModuleApi::TracingPushDown) do |mod|
|
75
|
+
mod.sampling_config = config
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Sqreen
|
4
|
+
module Ecosystem
|
5
|
+
# Configured by the ecosystem client
|
6
|
+
module DispatchTable
|
7
|
+
class << self
|
8
|
+
# data consumption
|
9
|
+
# argument: +Sqreen::Kit::Signals::Signal+
|
10
|
+
# see +Sqreen::EcosystemIntegration::SignalConsumption#consume_signal+
|
11
|
+
attr_accessor :consume_signal
|
12
|
+
|
13
|
+
# argument: block taking a Rack::Request
|
14
|
+
# see +Sqreen::EcosystemIntegration::RequestLifecycleTracking#add_start_observer+
|
15
|
+
attr_accessor :add_request_start_listener
|
16
|
+
|
17
|
+
attr_accessor :fetch_logger
|
18
|
+
|
19
|
+
# argument: callback taking:
|
20
|
+
# * the method to instrument
|
21
|
+
# * A Hash{Symbol=>Proc} with the advice. The proc takes the
|
22
|
+
# arguments and the ball, so these details of the instrumentation
|
23
|
+
# implementation leak through the abstraction
|
24
|
+
# see +Sqreen::EcosystemIntegration::InstrumentationService+
|
25
|
+
attr_accessor :instrument
|
26
|
+
|
27
|
+
def reset
|
28
|
+
instance_variables.each do |ia|
|
29
|
+
instance_variable_set(ia, nil)
|
30
|
+
end
|
31
|
+
|
32
|
+
# set default logger
|
33
|
+
logger = ::Logger.new(STDERR)
|
34
|
+
logger.level = ::Logger::WARN
|
35
|
+
logger.progname = 'sqreen-ecosystem'
|
36
|
+
self.fetch_logger = proc { logger }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
reset
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'sqreen/ecosystem/module_api'
|
2
|
+
require 'sqreen/ecosystem/module_api/instrumentation'
|
3
|
+
require 'sqreen/ecosystem/module_api/tracing_push_down'
|
4
|
+
require 'sqreen/ecosystem/module_api/signal_producer'
|
5
|
+
require 'sqreen/ecosystem/module_api/transaction_storage'
|
6
|
+
require 'sqreen/ecosystem/tracing/signals/tracing_client'
|
7
|
+
|
8
|
+
module Sqreen
|
9
|
+
module Ecosystem
|
10
|
+
module Http
|
11
|
+
class NetHttp
|
12
|
+
include ModuleApi::Instrumentation
|
13
|
+
include ModuleApi::SignalProducer
|
14
|
+
include ModuleApi::TracingPushDown
|
15
|
+
|
16
|
+
def setup
|
17
|
+
instrument 'Net::HTTP#request', before: method(:before_advice)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# instr. def request(req, body = nil, &block) # :yield: +response+
|
23
|
+
# req is of type +Net::HTTPGenericRequest+
|
24
|
+
def before_advice(call, _ball)
|
25
|
+
return unless should_sample?('client')
|
26
|
+
|
27
|
+
tracing_id = create_tracing_id
|
28
|
+
|
29
|
+
# build & submit signal
|
30
|
+
host = call.instance.address
|
31
|
+
port = call.instance.port
|
32
|
+
|
33
|
+
host += ':' + port.to_s if port != 80 && port != 443
|
34
|
+
|
35
|
+
signal = Tracing::Signals::TracingClient.new
|
36
|
+
signal.payload = Tracing::Signals::TracingClient::Payload.new(
|
37
|
+
transport: 'http',
|
38
|
+
host: host,
|
39
|
+
tracing_identifier: tracing_id
|
40
|
+
)
|
41
|
+
|
42
|
+
submit_signal signal
|
43
|
+
|
44
|
+
# add tracing header, if available
|
45
|
+
req = call.args[0]
|
46
|
+
req[ModuleApi::TRACE_ID_HEADER] = tracing_id
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sqreen/ecosystem/module_api'
|
2
|
+
require 'sqreen/ecosystem/module_api/event_listener'
|
3
|
+
require 'sqreen/ecosystem/module_api/signal_producer'
|
4
|
+
require 'sqreen/ecosystem/module_api/tracing_push_down'
|
5
|
+
require 'sqreen/ecosystem/tracing/signals/tracing_server'
|
6
|
+
|
7
|
+
module Sqreen
|
8
|
+
module Ecosystem
|
9
|
+
module Http
|
10
|
+
class RackRequest
|
11
|
+
include ModuleApi::EventListener
|
12
|
+
include ModuleApi::TracingPushDown
|
13
|
+
include ModuleApi::SignalProducer
|
14
|
+
|
15
|
+
def setup
|
16
|
+
on_request_start(&method(:handle_request))
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def handle_request(rack_request)
|
22
|
+
return unless should_sample?('server')
|
23
|
+
|
24
|
+
trace_id = rack_request.env[ModuleApi::TRACE_ID_ENV_KEY]
|
25
|
+
|
26
|
+
signal = Tracing::Signals::TracingServer.new
|
27
|
+
signal.payload = Tracing::Signals::TracingServer::Payload.new(
|
28
|
+
transport: 'http',
|
29
|
+
client_ip: rack_request.ip,
|
30
|
+
tracing_identifier: trace_id
|
31
|
+
)
|
32
|
+
|
33
|
+
submit_signal signal
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'sqreen/ecosystem/loggable'
|
2
|
+
|
3
|
+
module Sqreen
|
4
|
+
module Ecosystem
|
5
|
+
# The API that the transport/tracing modules are written against
|
6
|
+
module ModuleApi
|
7
|
+
TRACE_ID_HEADER = 'X-Sqreen-Trace-Identifier'.freeze
|
8
|
+
TRACE_ID_ENV_KEY = 'HTTP_X_SQREEN_TRACE_IDENTIFIER'.freeze
|
9
|
+
|
10
|
+
Loggable = Sqreen::Ecosystem::Loggable
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
attr_writer :module_name
|
14
|
+
|
15
|
+
def module_name
|
16
|
+
if instance_variable_defined?(:@module_name)
|
17
|
+
@module_name
|
18
|
+
else
|
19
|
+
# to snake case
|
20
|
+
@module_name = to_s.sub(/.*::/, '').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.included(mod)
|
26
|
+
mod.extend(ClassMethods)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'sqreen/ecosystem/dispatch_table'
|
2
|
+
|
3
|
+
module Sqreen
|
4
|
+
module Ecosystem
|
5
|
+
module ModuleApi
|
6
|
+
module EventListener
|
7
|
+
private
|
8
|
+
|
9
|
+
# XXX: callbacks need to be wrapped in order ot handle
|
10
|
+
# perfcap, exceptions, and maybe other concerns applying
|
11
|
+
# across the board
|
12
|
+
def on_request_start(&cb)
|
13
|
+
DispatchTable.add_request_start_listener.call(cb)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sqreen/ecosystem/module_api'
|
2
|
+
|
3
|
+
module Sqreen
|
4
|
+
module Ecosystem
|
5
|
+
module ModuleApi
|
6
|
+
module Instrumentation
|
7
|
+
def self.included(mod)
|
8
|
+
mod.send :include, ModuleApi unless mod.ancestors.include?(ModuleApi)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Just forwards the call to the instrumentation service
|
14
|
+
# @param [String] method
|
15
|
+
# @param [Hash{Symbol=>Proc}] advice keys are one of: :before, :after,
|
16
|
+
# :raised,
|
17
|
+
def instrument(method, advice)
|
18
|
+
DispatchTable.instrument.call(self.class.module_name, method, advice)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'sqreen/ecosystem/dispatch_table'
|
2
|
+
require 'sqreen/ecosystem/module_api/transaction_storage'
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Ecosystem
|
6
|
+
module ModuleApi
|
7
|
+
module SignalProducer
|
8
|
+
include TransactionStorage
|
9
|
+
|
10
|
+
# for injection
|
11
|
+
attr_writer :tracing_id_producer
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def create_tracing_id
|
16
|
+
@tracing_id_producer.call
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Sqreen::Kit::Signals::Signal] signal
|
20
|
+
def submit_signal(signal)
|
21
|
+
DispatchTable.consume_signal.call(signal)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'sqreen/ecosystem/loggable'
|
2
|
+
require 'sqreen/ecosystem/tracing/sampling_configuration'
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Ecosystem
|
6
|
+
module ModuleApi
|
7
|
+
module TracingPushDown
|
8
|
+
include Loggable
|
9
|
+
|
10
|
+
# method for ecosystem to inject the config
|
11
|
+
# @param [Sqreen::Ecosystem::SamplingConfiguration]
|
12
|
+
attr_writer :sampling_config
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def should_sample?(scope)
|
17
|
+
unless @sampling_config
|
18
|
+
logger.debug { "Scope #{scope} is disabled because tracing hasn't been enabled yet" }
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
result = @sampling_config.should_sample?(scope)
|
23
|
+
if result
|
24
|
+
logger.debug { "Will sample scope #{scope}. Sampling line: #{result}" }
|
25
|
+
else
|
26
|
+
logger.debug { "Will NOT sample scope #{scope}" }
|
27
|
+
end
|
28
|
+
|
29
|
+
result
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'sqreen/ecosystem/transaction_storage'
|
2
|
+
require 'sqreen/ecosystem/loggable'
|
3
|
+
|
4
|
+
module Sqreen
|
5
|
+
module Ecosystem
|
6
|
+
module ModuleApi
|
7
|
+
module TransactionStorage
|
8
|
+
class TxLocalVariables
|
9
|
+
class << self
|
10
|
+
class << self
|
11
|
+
include Sqreen::Ecosystem::Loggable
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def attr_reader(attr, _opts = {})
|
16
|
+
define_method attr do
|
17
|
+
tx_storage = Ecosystem::TransactionStorage.fetch_thread_local
|
18
|
+
return unless tx_storage
|
19
|
+
tx_storage[attr]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def attr_accessor(attr, opts = {})
|
24
|
+
# reader
|
25
|
+
attr_reader attr, opts
|
26
|
+
|
27
|
+
# writer (2 variants)
|
28
|
+
do_assign = proc do |value|
|
29
|
+
tx_storage = Ecosystem::TransactionStorage.fetch_thread_local
|
30
|
+
unless tx_storage
|
31
|
+
logger.debug do
|
32
|
+
"Assignment of tx local attribute #{attr} to #{value} has no effect"
|
33
|
+
end
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
tx_storage[attr] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
if opts.fetch(:allow_overwrite, false)
|
41
|
+
define "#{attr}=", &do_assign
|
42
|
+
else
|
43
|
+
define_method "#{attr}=" do |value|
|
44
|
+
cur = public_send(attr)
|
45
|
+
unless cur.nil?
|
46
|
+
raise "Cannot override value of #{attr} from #{cur} with #{value}"
|
47
|
+
end
|
48
|
+
|
49
|
+
do_assign.call(value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end # TxLocalVariables.singleton_class.singleton_class
|
54
|
+
|
55
|
+
# usage:
|
56
|
+
# attr_reader :xxx
|
57
|
+
|
58
|
+
# in the future, we'll possibly need to expose the full
|
59
|
+
# TransactionStorage to the modules, at least if we don't
|
60
|
+
# opt for a more structured fashion of data exchange between
|
61
|
+
# the modules.
|
62
|
+
end # TxLocalVariables.singleton_class
|
63
|
+
end # TxLocalVariables
|
64
|
+
|
65
|
+
def tx_local_vars
|
66
|
+
TxLocalVariables
|
67
|
+
end
|
68
|
+
end # TransactionStorage module
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|