active_endpoint 0.2.0
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 +7 -0
- data/.gitignore +55 -0
- data/.rspec +2 -0
- data/.rubocop.yml +60 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +25 -0
- data/Gemfile.lock +140 -0
- data/LICENSE +21 -0
- data/README.md +233 -0
- data/Rakefile +6 -0
- data/active_endpoint.gemspec +28 -0
- data/app/assets/config/active_endpoint_manifest.js +2 -0
- data/app/assets/javascripts/active_endpoint/application.js +2 -0
- data/app/assets/stylesheets/active_endpoint/application.css +10 -0
- data/app/controllers/active_endpoint/application_controller.rb +5 -0
- data/app/controllers/active_endpoint/dashboard_controller.rb +7 -0
- data/app/controllers/active_endpoint/probes_controller.rb +22 -0
- data/app/controllers/active_endpoint/unregistred_probes_controller.rb +14 -0
- data/app/helpers/active_endpoint/application_helper.rb +105 -0
- data/app/models/active_endpoint/application_record.rb +5 -0
- data/app/models/active_endpoint/probe.rb +52 -0
- data/app/models/active_endpoint/unregistred_probe.rb +3 -0
- data/app/views/active_endpoint/application/_flashes.html.erb +5 -0
- data/app/views/active_endpoint/application/_header.html.erb +18 -0
- data/app/views/active_endpoint/dashboard/_blacklist.html.erb +57 -0
- data/app/views/active_endpoint/dashboard/_constraints.html.erb +117 -0
- data/app/views/active_endpoint/dashboard/_settings.html.erb +13 -0
- data/app/views/active_endpoint/dashboard/_tags.html.erb +20 -0
- data/app/views/active_endpoint/dashboard/index.html.erb +8 -0
- data/app/views/active_endpoint/probes/index.html.erb +28 -0
- data/app/views/active_endpoint/probes/show.html.erb +43 -0
- data/app/views/active_endpoint/probes/show_response.html.erb +9 -0
- data/app/views/active_endpoint/unregistred_probes/index.html.erb +28 -0
- data/app/views/layouts/active_endpoint/application.html.erb +39 -0
- data/bin/console +14 -0
- data/bin/rails +13 -0
- data/bin/setup +8 -0
- data/config/routes.rb +8 -0
- data/lib/active_endpoint.rb +60 -0
- data/lib/active_endpoint/concerns/configurable.rb +29 -0
- data/lib/active_endpoint/concerns/constraintable.rb +51 -0
- data/lib/active_endpoint/concerns/optionable.rb +41 -0
- data/lib/active_endpoint/concerns/rails_routable.rb +49 -0
- data/lib/active_endpoint/engine.rb +15 -0
- data/lib/active_endpoint/extentions/active_record.rb +30 -0
- data/lib/active_endpoint/logger.rb +28 -0
- data/lib/active_endpoint/proxy.rb +64 -0
- data/lib/active_endpoint/rails/middleware.rb +17 -0
- data/lib/active_endpoint/rails/railtie.rb +13 -0
- data/lib/active_endpoint/request.rb +79 -0
- data/lib/active_endpoint/response.rb +17 -0
- data/lib/active_endpoint/routes/blacklist.rb +67 -0
- data/lib/active_endpoint/routes/cache/proxy.rb +22 -0
- data/lib/active_endpoint/routes/cache/proxy/redis_store_proxy.rb +41 -0
- data/lib/active_endpoint/routes/cache/store.rb +73 -0
- data/lib/active_endpoint/routes/constraint_rule.rb +38 -0
- data/lib/active_endpoint/routes/constraints.rb +81 -0
- data/lib/active_endpoint/routes/matcher.rb +51 -0
- data/lib/active_endpoint/routes/momento.rb +81 -0
- data/lib/active_endpoint/storage.rb +112 -0
- data/lib/active_endpoint/tags.rb +15 -0
- data/lib/active_endpoint/version.rb +3 -0
- data/lib/generators/active_endpoint/install_generator.rb +35 -0
- data/lib/generators/templates/active_endpoint.rb +40 -0
- data/lib/generators/templates/migration.erb +30 -0
- metadata +109 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module ActiveEndpoint
|
|
2
|
+
module Routes
|
|
3
|
+
class ConstraintRule
|
|
4
|
+
include Optionable
|
|
5
|
+
include Constraintable
|
|
6
|
+
|
|
7
|
+
def initialize(request)
|
|
8
|
+
@request = request
|
|
9
|
+
@rules = ActiveEndpoint.constraints
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def rule
|
|
13
|
+
{
|
|
14
|
+
key: "#{prefix}:#{@request[:endpoint]}"
|
|
15
|
+
}.merge(fetch_constraints)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def prefix
|
|
21
|
+
return :endpoints if @rules.present_endpoint?(@request)
|
|
22
|
+
return :resources if @rules.present_resource?(@request)
|
|
23
|
+
return :actions if @rules.present_action?(@request)
|
|
24
|
+
return :scopes if @rules.present_scope?(@request)
|
|
25
|
+
:defaults
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def fetch_constraints
|
|
29
|
+
if prefix == :defaults
|
|
30
|
+
default_constraints
|
|
31
|
+
else
|
|
32
|
+
constraints = @rules.public_send(prefix)[@request[:endpoint]]
|
|
33
|
+
constraints.present? ? constraints : default_constraints
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module ActiveEndpoint
|
|
2
|
+
module Routes
|
|
3
|
+
class Constraints < Momento
|
|
4
|
+
include Constraintable
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
super(Hash)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add(options)
|
|
11
|
+
super(options) do |options|
|
|
12
|
+
if fetch_rule(options).nil?
|
|
13
|
+
message = "Constraints can't have empty limit and period!\n"
|
|
14
|
+
raise ActiveEndpoint::Routes::Constraints::Error.new(message)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def present_endpoint?(request)
|
|
20
|
+
@endpoints.keys.include?(request[:endpoint])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def present_resource?(request)
|
|
24
|
+
reduce_state(@resources.keys, request)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def present_action?(request)
|
|
28
|
+
@actions.keys.include?(request[:endpoint])
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def present_scope?(request)
|
|
32
|
+
reduce_state(@scopes.keys, request)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def add_endpoint(options)
|
|
38
|
+
@endpoints[fetch_endpoint(options)] = constraints(options)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def add_resources(options)
|
|
42
|
+
resources = fetch_resources(options)
|
|
43
|
+
actions = fetch_actions(options)
|
|
44
|
+
scope = fetch_scope(options)
|
|
45
|
+
|
|
46
|
+
if actions.present? && actions.any?
|
|
47
|
+
temp_actions = {}
|
|
48
|
+
if resources.is_a?(Array)
|
|
49
|
+
resources.each do |controller_name|
|
|
50
|
+
actions.each { |action| temp_actions["#{controller_name}##{action}"] = constraints(options) }
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
actions.each { |action| temp_actions["#{resources}##{action}"] = constraints(options) }
|
|
54
|
+
end
|
|
55
|
+
@actions = @actions.merge(apply(scope, temp_actions))
|
|
56
|
+
else
|
|
57
|
+
temp_resources = {}
|
|
58
|
+
if resources.is_a?(Array)
|
|
59
|
+
resources.each { |resource| temp_resources[resource] = constraints(options) }
|
|
60
|
+
else
|
|
61
|
+
temp_resources[resources] = constraints(options)
|
|
62
|
+
end
|
|
63
|
+
@resources = @resources.merge(apply(scope, temp_resources))
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def add_scopes(options)
|
|
68
|
+
@scopes[fetch_scope(options)] = constraints(options)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def apply(scope, collection)
|
|
72
|
+
return collection unless scope.present?
|
|
73
|
+
|
|
74
|
+
collection.inject({}) do |hash, (key, value)|
|
|
75
|
+
hash["#{scope}/#{key}"] = value
|
|
76
|
+
hash
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module ActiveEndpoint
|
|
2
|
+
module Routes
|
|
3
|
+
class Matcher
|
|
4
|
+
include RailsRoutable
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@blacklist = ActiveEndpoint.blacklist
|
|
8
|
+
@cache_store = ActiveEndpoint::Routes::Cache::Store.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def whitelisted?(request)
|
|
12
|
+
trackable?(request) && rails_action?(request)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def blacklisted?(probe)
|
|
16
|
+
@blacklist.include?(probe)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def unregistred?(request)
|
|
20
|
+
trackable?(request) && !rails_action(request)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def assets?(request)
|
|
24
|
+
request.path.start_with?('/assets')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def allow_account?(request)
|
|
28
|
+
@constraint_rule = ActiveEndpoint::Routes::ConstraintRule.new(request).rule
|
|
29
|
+
@cache_store.allow?(@constraint_rule)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def allow_register?(request)
|
|
33
|
+
@cache_store.unregistred?(request.probe)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def favicon?(request)
|
|
39
|
+
request.path == '/favicon.ico'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def engine?(request)
|
|
43
|
+
request.path.include?('active_endpoint')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def trackable?(request)
|
|
47
|
+
!(engine?(request) || assets?(request) || favicon?(request) || blacklisted?(request.probe))
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module ActiveEndpoint
|
|
2
|
+
module Routes
|
|
3
|
+
class Momento
|
|
4
|
+
include Configurable
|
|
5
|
+
include Optionable
|
|
6
|
+
|
|
7
|
+
class Error < ::StandardError; end
|
|
8
|
+
|
|
9
|
+
attr_reader :endpoints, :resources, :actions, :scopes
|
|
10
|
+
|
|
11
|
+
def initialize(structure_class)
|
|
12
|
+
@endpoints = structure_class.new
|
|
13
|
+
@resources = structure_class.new
|
|
14
|
+
@actions = structure_class.new
|
|
15
|
+
@scopes = structure_class.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def include?(request)
|
|
19
|
+
any_presented? [
|
|
20
|
+
present_endpoint?(request),
|
|
21
|
+
present_resource?(request),
|
|
22
|
+
present_action?(request),
|
|
23
|
+
present_scope?(request)
|
|
24
|
+
]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def add(**options, &block)
|
|
28
|
+
|
|
29
|
+
yield(options) if block_given?
|
|
30
|
+
|
|
31
|
+
add_endpoint(options) if fetch_endpoint(options).present?
|
|
32
|
+
add_resources(options) if fetch_resources(options).present?
|
|
33
|
+
add_scopes(options) if fetch_scope(options).present?
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def add_endpoint(_options)
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def add_resource(_options)
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_scopes(_options)
|
|
47
|
+
raise NotImplementedError
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def present_endpoint?(_request)
|
|
51
|
+
raise NotImplementedError
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def present_resource?(_request)
|
|
55
|
+
raise NotImplementedError
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def present_action?(_request)
|
|
59
|
+
raise NotImplementedError
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def present_scope?(_request)
|
|
63
|
+
raise NotImplementedError
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def apply(_scope, _collection)
|
|
67
|
+
raise NotImplementedError
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def any_presented?(chain)
|
|
71
|
+
chain.reduce(false) { |state, responder_state| state || responder_state }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def reduce_state(collection, request)
|
|
75
|
+
collection.reduce(false) do |state, subject|
|
|
76
|
+
state || request[:endpoint].present? && request[:endpoint].start_with?(subject)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module ActiveEndpoint
|
|
2
|
+
class Storage
|
|
3
|
+
STORING_FIELDS = [
|
|
4
|
+
:body,
|
|
5
|
+
:response,
|
|
6
|
+
:started_at,
|
|
7
|
+
:finished_at,
|
|
8
|
+
:duration,
|
|
9
|
+
:endpoint,
|
|
10
|
+
:ip,
|
|
11
|
+
:params,
|
|
12
|
+
:path,
|
|
13
|
+
:request_method,
|
|
14
|
+
:url,
|
|
15
|
+
:xhr
|
|
16
|
+
].freeze
|
|
17
|
+
|
|
18
|
+
LOGGING_FIELDS = [
|
|
19
|
+
:base_url,
|
|
20
|
+
:content_charset,
|
|
21
|
+
:content_length,
|
|
22
|
+
:content_type,
|
|
23
|
+
:fullpath,
|
|
24
|
+
:http_version,
|
|
25
|
+
:http_connection,
|
|
26
|
+
:http_accept_encoding,
|
|
27
|
+
:http_accept_language,
|
|
28
|
+
:media_type,
|
|
29
|
+
:media_type_params,
|
|
30
|
+
:method,
|
|
31
|
+
:path_info,
|
|
32
|
+
:pattern,
|
|
33
|
+
:port,
|
|
34
|
+
:protocol,
|
|
35
|
+
:server_name,
|
|
36
|
+
:ssl
|
|
37
|
+
].freeze
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
def notifier
|
|
41
|
+
ActiveSupport::Notifications
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def probe_params(transaction_id, probe)
|
|
45
|
+
request = probe.delete(:request)
|
|
46
|
+
request_body = request.delete(:body)
|
|
47
|
+
|
|
48
|
+
response = probe.delete(:response)
|
|
49
|
+
response_body = response.present? ? response[:body] : nil
|
|
50
|
+
|
|
51
|
+
params = {
|
|
52
|
+
uuid: transaction_id,
|
|
53
|
+
response: response_body ? Base64.encode64(response_body) : '',
|
|
54
|
+
started_at: probe[:created_at],
|
|
55
|
+
finished_at: probe[:finished_at],
|
|
56
|
+
duration: probe[:finished_at] ? (probe[:finished_at] - probe[:created_at]).second.round(3) : 0,
|
|
57
|
+
body: request_body.is_a?(Puma::NullIO) ? '' : request_body
|
|
58
|
+
}.merge(request)
|
|
59
|
+
|
|
60
|
+
[params.dup.except(*LOGGING_FIELDS), params.dup.except(*STORING_FIELDS)]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def store!(params)
|
|
64
|
+
handle_creation(ActiveEndpoint::Probe.new(params))
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def register!(params)
|
|
68
|
+
handle_creation(ActiveEndpoint::UnregistredProbe.new(params.merge(endpoint: :unregistred)))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def handle_creation(probe)
|
|
72
|
+
probe.save
|
|
73
|
+
rescue => error
|
|
74
|
+
ActiveEndpoint.logger.error('ActiveEndpoint::Probe', error)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def clean!(endpoint, period)
|
|
78
|
+
ActiveEndpoint::Probe.registred.probe(endpoint).taken_before(period).destroy_all
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
notifier.subscribe('active_endpoint.tracked_probe') do |_name, _start, _ending, id, payload|
|
|
83
|
+
store_params, logging_params = probe_params(id, payload[:probe])
|
|
84
|
+
|
|
85
|
+
ActiveEndpoint.logger.info('ActiveEndpoint::Storage', logging_params, ActiveEndpoint.log_probe_info)
|
|
86
|
+
|
|
87
|
+
store!(store_params)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
notifier.subscribe('active_endpoint.unregistred_probe') do |_name, _start, _ending, id, payload|
|
|
91
|
+
store_params, logging_params = probe_params(id, payload[:probe])
|
|
92
|
+
|
|
93
|
+
if ActiveEndpoint.log_debug_info
|
|
94
|
+
ActiveEndpoint.logger.debug('ActiveEndpoint::Storage', store_params.inspect)
|
|
95
|
+
ActiveEndpoint.logger.debug('ActiveEndpoint::Storage', logging_params.inspect)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
register!(store_params)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
notifier.subscribe('active_endpoint.clean_expired') do |_name, _start, _ending, id, payload|
|
|
102
|
+
key = payload[:expired][:key].split(':').last
|
|
103
|
+
period = DateTime.now - (payload[:expired][:period] * ActiveEndpoint.storage_keep_periods).seconds
|
|
104
|
+
|
|
105
|
+
if ActiveEndpoint.log_debug_info
|
|
106
|
+
ActiveEndpoint.logger.info('ActiveEndpoint::Storage', { key: key, period: period, uuid: id }.inspect)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
clean!(key, period)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ActiveEndpoint
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
4
|
+
include ::Rails::Generators::Migration
|
|
5
|
+
|
|
6
|
+
source_root File.expand_path('../templates', __dir__)
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def next_migration_number(_dirname)
|
|
10
|
+
Time.current.strftime('%Y%m%d%H%M%S')
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
puts '=> Creates a ActiveEndpoint initializer, migration and migrate data base for your application.'
|
|
15
|
+
|
|
16
|
+
def copy_initializer_file
|
|
17
|
+
puts '=> Copy initializer file to config/initializers/active_endpoint.rb'
|
|
18
|
+
copy_file 'active_endpoint.rb', 'config/initializers/active_endpoint.rb'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def copy_migration_file
|
|
22
|
+
puts '=> Create migration file in db/migrate/***_create_active_endpoint_probes.rb'
|
|
23
|
+
migration_template 'migration.erb', 'db/migrate/create_active_endpoint_probes.rb',
|
|
24
|
+
migration_version: migration_version
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def migration_version
|
|
30
|
+
last_rails = ::Rails.version.start_with?('5')
|
|
31
|
+
"[#{::Rails::VERSION::MAJOR}.#{::Rails::VERSION::MINOR}]" if last_rails
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
ActiveEndpoint.configure do |endpoint|
|
|
2
|
+
endpoint.blacklist.configure do |list|
|
|
3
|
+
# list.add(endpoint: 'web/welcome#index')
|
|
4
|
+
# list.add(resources: 'web/users', actions: ['show'])
|
|
5
|
+
# list.add(scope: 'web', resources: 'users', actions: ['show'])
|
|
6
|
+
# list.add(scope: 'web')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
endpoint.constraint_limit = 100
|
|
10
|
+
endpoint.constraint_period = 1.minute
|
|
11
|
+
|
|
12
|
+
endpoint.storage_limit = 1000
|
|
13
|
+
endpoint.storage_period = 1.day
|
|
14
|
+
endpoint.storage_keep_periods = 2
|
|
15
|
+
|
|
16
|
+
endpoint.constraints.configure do |constraints|
|
|
17
|
+
# constraints.add(endpoint: 'web/welcome#index',
|
|
18
|
+
# rule: { limit: 100, period: 1.minute },
|
|
19
|
+
# storage: { limit: 1000, period: 1.week }
|
|
20
|
+
# })
|
|
21
|
+
# constraints.add(scope: 'web', resources: 'users', rule: { limit: 100 })
|
|
22
|
+
# constraints.add(scope: 'web', resources: ['users'],
|
|
23
|
+
# actions: [:show, :edit, :update],
|
|
24
|
+
# rule: { limit: 10, period: 1.minute })
|
|
25
|
+
# constraints.add(scope: 'web', rule: { limit: 100, period: 1.minute })
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
endpoint.tags.configure do |tags|
|
|
29
|
+
# tags.add(:fast, { less_than: 250 })
|
|
30
|
+
# tags.add(:normal, { greater_than_or_equal_to: 250, less_than: 500 })
|
|
31
|
+
# tags.add(:slow, { greater_than_or_equal_to: 250, less_than: 500 })
|
|
32
|
+
# tags.add(:acceptable, { greater_than_or_equal_to: 500, less_than: 100 })
|
|
33
|
+
# tags.add(:need_optimization, { greater_than_or_equal_to: 1000 })
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
define_setting :logger, ActiveEndpoint::Logger
|
|
37
|
+
|
|
38
|
+
define_setting :log_probe_info, false
|
|
39
|
+
define_setting :log_debug_info, false
|
|
40
|
+
end
|