influxdb-rails 1.0.0 → 1.0.1.beta1
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/.github/dependabot.yml +11 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/.travis.yml +4 -7
- data/CHANGELOG.md +17 -0
- data/README.md +47 -5
- data/Rakefile +0 -6
- data/gemfiles/Gemfile.rails-5.0.x +2 -0
- data/gemfiles/Gemfile.rails-6.0.x +10 -0
- data/influxdb-rails.gemspec +5 -3
- data/lib/influxdb-rails.rb +11 -0
- data/lib/influxdb/rails/configuration.rb +8 -12
- data/lib/influxdb/rails/context.rb +6 -40
- data/lib/influxdb/rails/helpers/rspec_matchers.rb +48 -0
- data/lib/influxdb/rails/metric.rb +39 -0
- data/lib/influxdb/rails/middleware/active_job_subscriber.rb +67 -0
- data/lib/influxdb/rails/middleware/active_record_subscriber.rb +26 -0
- data/lib/influxdb/rails/middleware/block_instrumentation_subscriber.rb +24 -0
- data/lib/influxdb/rails/middleware/render_subscriber.rb +15 -16
- data/lib/influxdb/rails/middleware/request_subscriber.rb +16 -21
- data/lib/influxdb/rails/middleware/sql_subscriber.rb +18 -18
- data/lib/influxdb/rails/middleware/subscriber.rb +40 -27
- data/lib/influxdb/rails/railtie.rb +15 -18
- data/lib/influxdb/rails/tags.rb +33 -0
- data/lib/influxdb/rails/test_client.rb +13 -0
- data/lib/influxdb/rails/values.rb +24 -0
- data/lib/influxdb/rails/version.rb +1 -1
- data/sample-dashboard/README.md +1 -1
- data/spec/requests/action_controller_metrics_spec.rb +83 -0
- data/spec/requests/action_view_collection_metrics_spec.rb +66 -0
- data/spec/requests/action_view_partial_metrics_spec.rb +62 -0
- data/spec/requests/action_view_template_metrics_spec.rb +62 -0
- data/spec/requests/active_job_enqueue_metrics_spec.rb +65 -0
- data/spec/requests/active_job_perform_metrics_spec.rb +68 -0
- data/spec/requests/active_job_perform_start_metrics_spec.rb +68 -0
- data/spec/requests/active_record_instantiation_metrics_spec.rb +65 -0
- data/spec/requests/active_record_sql_metrics_spec.rb +103 -0
- data/spec/requests/block_inistrumentation_spec.rb +64 -0
- data/spec/requests/context_spec.rb +27 -0
- data/spec/requests/logger_spec.rb +10 -0
- data/spec/spec_helper.rb +10 -4
- data/spec/support/broken_client.rb +11 -0
- data/spec/support/rails5/app.rb +32 -10
- data/spec/support/rails6/app.rb +70 -0
- data/spec/support/views/{widgets → metrics}/_item.html.erb +0 -0
- data/spec/support/views/{widgets → metrics}/index.html.erb +0 -0
- data/spec/support/views/metrics/show.html.erb +4 -0
- data/spec/unit/block_instrumentation_spec.rb +18 -0
- metadata +87 -37
- data/gemfiles/Gemfile.rails-4.2.x +0 -7
- data/lib/influxdb/rails/instrumentation.rb +0 -34
- data/lib/influxdb/rails/middleware/simple_subscriber.rb +0 -33
- data/spec/controllers/widgets_controller_spec.rb +0 -15
- data/spec/integration/integration_helper.rb +0 -1
- data/spec/integration/metrics_spec.rb +0 -27
- data/spec/shared_examples/data.rb +0 -61
- data/spec/support/rails4/app.rb +0 -48
- data/spec/unit/context_spec.rb +0 -40
- data/spec/unit/middleware/render_subscriber_spec.rb +0 -96
- data/spec/unit/middleware/request_subscriber_spec.rb +0 -103
- data/spec/unit/middleware/sql_subscriber_spec.rb +0 -108
@@ -0,0 +1,67 @@
|
|
1
|
+
require "influxdb/rails/middleware/subscriber"
|
2
|
+
|
3
|
+
module InfluxDB
|
4
|
+
module Rails
|
5
|
+
module Middleware
|
6
|
+
class ActiveJobSubscriber < Subscriber # :nodoc:
|
7
|
+
private
|
8
|
+
|
9
|
+
def values
|
10
|
+
{
|
11
|
+
value: value,
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def tags
|
16
|
+
{
|
17
|
+
hook: short_hook_name,
|
18
|
+
state: job_state,
|
19
|
+
job: job.class.name,
|
20
|
+
queue: job.queue_name,
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def job_state
|
25
|
+
return "failed" if failed?
|
26
|
+
|
27
|
+
case short_hook_name
|
28
|
+
when "enqueue"
|
29
|
+
"queued"
|
30
|
+
when "perform_start"
|
31
|
+
"running"
|
32
|
+
when "perform"
|
33
|
+
"succeeded"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def measure_performance?
|
38
|
+
short_hook_name == "perform"
|
39
|
+
end
|
40
|
+
|
41
|
+
def short_hook_name
|
42
|
+
@short_hook_name ||= fetch_short_hook_name
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_short_hook_name
|
46
|
+
return "enqueue" if hook_name.include?("enqueue")
|
47
|
+
return "perform_start" if hook_name.include?("perform_start")
|
48
|
+
return "perform" if hook_name.include?("perform")
|
49
|
+
end
|
50
|
+
|
51
|
+
def job
|
52
|
+
@job ||= payload[:job]
|
53
|
+
end
|
54
|
+
|
55
|
+
def value
|
56
|
+
return duration if measure_performance?
|
57
|
+
|
58
|
+
1
|
59
|
+
end
|
60
|
+
|
61
|
+
def failed?
|
62
|
+
payload[:exception_object]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "influxdb/rails/middleware/subscriber"
|
2
|
+
require "influxdb/rails/sql/query"
|
3
|
+
|
4
|
+
module InfluxDB
|
5
|
+
module Rails
|
6
|
+
module Middleware
|
7
|
+
class ActiveRecordSubscriber < Subscriber # :nodoc:
|
8
|
+
private
|
9
|
+
|
10
|
+
def values
|
11
|
+
{
|
12
|
+
value: duration,
|
13
|
+
record_count: payload[:record_count],
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def tags
|
18
|
+
{
|
19
|
+
hook: "instantiation",
|
20
|
+
class_name: payload[:class_name],
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "influxdb/rails/middleware/subscriber"
|
2
|
+
|
3
|
+
module InfluxDB
|
4
|
+
module Rails
|
5
|
+
module Middleware
|
6
|
+
class BlockInstrumentationSubscriber < Subscriber
|
7
|
+
private
|
8
|
+
|
9
|
+
def values
|
10
|
+
{
|
11
|
+
value: duration,
|
12
|
+
}.merge(payload[:values].to_h)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tags
|
16
|
+
{
|
17
|
+
hook: "block_instrumentation",
|
18
|
+
name: payload[:name],
|
19
|
+
}.merge(payload[:tags].to_h)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,31 +1,30 @@
|
|
1
|
-
require "influxdb/rails/middleware/
|
1
|
+
require "influxdb/rails/middleware/subscriber"
|
2
2
|
|
3
3
|
module InfluxDB
|
4
4
|
module Rails
|
5
5
|
module Middleware
|
6
|
-
class RenderSubscriber <
|
7
|
-
def short_hook_name
|
8
|
-
return "render_template" if hook_name.include?("render_template")
|
9
|
-
return "render_partial" if hook_name.include?("render_partial")
|
10
|
-
return "render_collection" if hook_name.include?("render_collection")
|
11
|
-
end
|
12
|
-
|
6
|
+
class RenderSubscriber < Subscriber # :nodoc:
|
13
7
|
private
|
14
8
|
|
15
|
-
def values
|
16
|
-
|
9
|
+
def values
|
10
|
+
{
|
11
|
+
value: duration,
|
17
12
|
count: payload[:count],
|
18
|
-
cache_hits: payload[:cache_hits]
|
19
|
-
|
13
|
+
cache_hits: payload[:cache_hits],
|
14
|
+
}
|
20
15
|
end
|
21
16
|
|
22
|
-
def tags
|
23
|
-
|
24
|
-
location: location,
|
17
|
+
def tags
|
18
|
+
{
|
25
19
|
hook: short_hook_name,
|
26
20
|
filename: payload[:identifier],
|
27
21
|
}
|
28
|
-
|
22
|
+
end
|
23
|
+
|
24
|
+
def short_hook_name
|
25
|
+
return "render_template" if hook_name.include?("render_template")
|
26
|
+
return "render_partial" if hook_name.include?("render_partial")
|
27
|
+
return "render_collection" if hook_name.include?("render_collection")
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|
@@ -4,44 +4,39 @@ module InfluxDB
|
|
4
4
|
module Rails
|
5
5
|
module Middleware
|
6
6
|
class RequestSubscriber < Subscriber # :nodoc:
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
InfluxDB::Rails.client.write_point \
|
11
|
-
configuration.measurement_name,
|
12
|
-
values: values(start, finish, payload),
|
13
|
-
tags: tags(payload),
|
14
|
-
timestamp: timestamp(finish)
|
15
|
-
rescue StandardError => e
|
16
|
-
::Rails.logger.error("[InfluxDB::Rails] Unable to write points: #{e.message}")
|
7
|
+
def write
|
8
|
+
super
|
17
9
|
ensure
|
18
10
|
InfluxDB::Rails.current.reset
|
19
11
|
end
|
20
12
|
|
21
13
|
private
|
22
14
|
|
23
|
-
def tags
|
24
|
-
|
15
|
+
def tags
|
16
|
+
{
|
25
17
|
method: "#{payload[:controller]}##{payload[:action]}",
|
26
18
|
hook: "process_action",
|
27
19
|
status: payload[:status],
|
28
20
|
format: payload[:format],
|
29
21
|
http_method: payload[:method],
|
30
|
-
|
31
|
-
app_name: configuration.application_name,
|
22
|
+
exception: payload[:exception]&.first,
|
32
23
|
}
|
33
|
-
super(tags)
|
34
24
|
end
|
35
25
|
|
36
|
-
def values
|
26
|
+
def values
|
37
27
|
{
|
38
|
-
controller:
|
28
|
+
controller: duration,
|
39
29
|
view: (payload[:view_runtime] || 0).ceil,
|
40
30
|
db: (payload[:db_runtime] || 0).ceil,
|
41
|
-
started:
|
42
|
-
}
|
43
|
-
|
44
|
-
|
31
|
+
started: started,
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def started
|
36
|
+
InfluxDB.convert_timestamp(
|
37
|
+
start.utc,
|
38
|
+
configuration.client.time_precision
|
39
|
+
)
|
45
40
|
end
|
46
41
|
end
|
47
42
|
end
|
@@ -1,35 +1,35 @@
|
|
1
|
-
require "influxdb/rails/middleware/
|
1
|
+
require "influxdb/rails/middleware/subscriber"
|
2
2
|
require "influxdb/rails/sql/query"
|
3
3
|
|
4
4
|
module InfluxDB
|
5
5
|
module Rails
|
6
6
|
module Middleware
|
7
|
-
class SqlSubscriber <
|
8
|
-
def call(_name, started, finished, _unique_id, payload)
|
9
|
-
super if InfluxDB::Rails::Sql::Query.new(payload).track?
|
10
|
-
end
|
11
|
-
|
7
|
+
class SqlSubscriber < Subscriber # :nodoc:
|
12
8
|
private
|
13
9
|
|
14
|
-
def values
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
result = super
|
20
|
-
result.empty? ? :raw : result
|
10
|
+
def values
|
11
|
+
{
|
12
|
+
value: duration,
|
13
|
+
sql: InfluxDB::Rails::Sql::Normalizer.new(payload[:sql]).perform,
|
14
|
+
}
|
21
15
|
end
|
22
16
|
|
23
|
-
def tags
|
24
|
-
|
25
|
-
tags = {
|
26
|
-
location: location,
|
17
|
+
def tags
|
18
|
+
{
|
27
19
|
hook: "sql",
|
28
20
|
operation: query.operation,
|
29
21
|
class_name: query.class_name,
|
30
22
|
name: query.name,
|
23
|
+
location: :raw,
|
31
24
|
}
|
32
|
-
|
25
|
+
end
|
26
|
+
|
27
|
+
def disabled?
|
28
|
+
super || !query.track?
|
29
|
+
end
|
30
|
+
|
31
|
+
def query
|
32
|
+
@query ||= InfluxDB::Rails::Sql::Query.new(payload)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "influxdb/rails/metric"
|
2
|
+
|
1
3
|
module InfluxDB
|
2
4
|
module Rails
|
3
5
|
module Middleware
|
@@ -5,49 +7,60 @@ module InfluxDB
|
|
5
7
|
# which are intended as ActiveSupport::Notifications.subscribe
|
6
8
|
# consumers.
|
7
9
|
class Subscriber
|
8
|
-
|
9
|
-
attr_reader :hook_name
|
10
|
-
|
11
|
-
def initialize(configuration, hook_name)
|
10
|
+
def initialize(configuration:, hook_name:, start:, finish:, payload:)
|
12
11
|
@configuration = configuration
|
13
12
|
@hook_name = hook_name
|
13
|
+
@start = start
|
14
|
+
@finish = finish
|
15
|
+
@payload = payload
|
14
16
|
end
|
15
17
|
|
16
|
-
def call(
|
17
|
-
|
18
|
+
def self.call(name, start, finish, _id, payload)
|
19
|
+
new(
|
20
|
+
configuration: InfluxDB::Rails.configuration,
|
21
|
+
start: start,
|
22
|
+
finish: finish,
|
23
|
+
payload: payload,
|
24
|
+
hook_name: name
|
25
|
+
).write
|
26
|
+
end
|
27
|
+
|
28
|
+
def write
|
29
|
+
return if disabled?
|
30
|
+
|
31
|
+
metric.write
|
32
|
+
rescue StandardError => e
|
33
|
+
::Rails.logger.error("[InfluxDB::Rails] Unable to write points: #{e.message}")
|
18
34
|
end
|
19
35
|
|
20
36
|
private
|
21
37
|
|
22
|
-
|
23
|
-
|
38
|
+
attr_reader :configuration, :hook_name, :start, :finish, :payload
|
39
|
+
|
40
|
+
def metric
|
41
|
+
InfluxDB::Rails::Metric.new(
|
42
|
+
values: values,
|
43
|
+
tags: tags,
|
44
|
+
configuration: configuration,
|
45
|
+
timestamp: finish
|
46
|
+
)
|
24
47
|
end
|
25
48
|
|
26
|
-
def
|
27
|
-
|
49
|
+
def tags
|
50
|
+
raise NotImplementedError, "must be implemented in subclass"
|
28
51
|
end
|
29
52
|
|
30
|
-
def
|
31
|
-
|
32
|
-
result = configuration.tags_middleware.call(result)
|
33
|
-
result.reject! do |_, value|
|
34
|
-
value.nil? || value == ""
|
35
|
-
end
|
36
|
-
result
|
53
|
+
def values
|
54
|
+
raise NotImplementedError, "must be implemented in subclass"
|
37
55
|
end
|
38
56
|
|
39
|
-
def
|
40
|
-
|
41
|
-
!configuration.ignore_current_environment? &&
|
42
|
-
!configuration.ignored_hooks.include?(hook_name)
|
57
|
+
def duration
|
58
|
+
((finish - start) * 1000).ceil
|
43
59
|
end
|
44
60
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
current.controller,
|
49
|
-
current.action,
|
50
|
-
].reject(&:blank?).join("#")
|
61
|
+
def disabled?
|
62
|
+
configuration.ignore_current_environment? ||
|
63
|
+
configuration.ignored_hooks.include?(hook_name)
|
51
64
|
end
|
52
65
|
end
|
53
66
|
end
|
@@ -11,38 +11,35 @@ module InfluxDB
|
|
11
11
|
end
|
12
12
|
|
13
13
|
ActiveSupport.on_load(:action_controller) do
|
14
|
-
require "influxdb/rails/instrumentation"
|
15
|
-
include InfluxDB::Rails::Instrumentation
|
16
|
-
|
17
14
|
before_action do
|
18
15
|
current = InfluxDB::Rails.current
|
19
|
-
current.
|
16
|
+
current.values = { request_id: request.request_id } if request.respond_to?(:request_id)
|
20
17
|
end
|
21
18
|
end
|
22
19
|
|
23
20
|
cache = lambda do |_, _, _, _, payload|
|
24
21
|
current = InfluxDB::Rails.current
|
25
|
-
|
26
|
-
current.
|
22
|
+
location = [payload[:controller], payload[:action]].join("#")
|
23
|
+
current.tags = { location: location }
|
27
24
|
end
|
28
25
|
ActiveSupport::Notifications.subscribe "start_processing.action_controller", &cache
|
29
26
|
|
30
27
|
{
|
31
|
-
"process_action.action_controller"
|
32
|
-
"render_template.action_view"
|
33
|
-
"render_partial.action_view"
|
34
|
-
"render_collection.action_view"
|
35
|
-
"sql.active_record"
|
36
|
-
|
37
|
-
|
28
|
+
"process_action.action_controller" => Middleware::RequestSubscriber,
|
29
|
+
"render_template.action_view" => Middleware::RenderSubscriber,
|
30
|
+
"render_partial.action_view" => Middleware::RenderSubscriber,
|
31
|
+
"render_collection.action_view" => Middleware::RenderSubscriber,
|
32
|
+
"sql.active_record" => Middleware::SqlSubscriber,
|
33
|
+
"instantiation.active_record" => Middleware::ActiveRecordSubscriber,
|
34
|
+
"enqueue.active_job" => Middleware::ActiveJobSubscriber,
|
35
|
+
"perform_start.active_job" => Middleware::ActiveJobSubscriber,
|
36
|
+
"perform.active_job" => Middleware::ActiveJobSubscriber,
|
37
|
+
"block_instrumentation.influxdb_rails" => Middleware::BlockInstrumentationSubscriber,
|
38
|
+
}.each do |hook_name, subscriber|
|
39
|
+
ActiveSupport::Notifications.subscribe(hook_name, subscriber)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
# rubocop:enable Metrics/BlockLength
|
41
|
-
|
42
|
-
def subscribe_to(hook_name, subscriber_class)
|
43
|
-
subscriber = subscriber_class.new(InfluxDB::Rails.configuration, hook_name)
|
44
|
-
ActiveSupport::Notifications.subscribe hook_name, subscriber
|
45
|
-
end
|
46
43
|
end
|
47
44
|
end
|
48
45
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module InfluxDB
|
2
|
+
module Rails
|
3
|
+
class Tags
|
4
|
+
def initialize(tags: {}, config:, additional_tags: InfluxDB::Rails.current.tags)
|
5
|
+
@tags = tags
|
6
|
+
@config = config
|
7
|
+
@additional_tags = additional_tags
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_h
|
11
|
+
expanded_tags.reject do |_, value|
|
12
|
+
value.nil? || value == ""
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :additional_tags, :tags, :config
|
19
|
+
|
20
|
+
def expanded_tags
|
21
|
+
config.tags_middleware.call(tags.merge(default_tags))
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_tags
|
25
|
+
{
|
26
|
+
server: Socket.gethostname,
|
27
|
+
app_name: config.application_name,
|
28
|
+
location: :raw,
|
29
|
+
}.merge(additional_tags)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|