Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DEV: Use syntax_tree for formatting #329

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: ['3.1', '3.2', '3.3']
ruby: ["3.1", "3.2", "3.3"]
activerecord: [61, 70, 71]

steps:
Expand All @@ -42,6 +42,9 @@ jobs:
- name: Rubocop
run: bundle exec rubocop

- name: Syntax tree
run: bundle exec stree check Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') $(git ls-files '*.thor')

- name: Run tests
run: bundle exec rake

Expand Down
2 changes: 2 additions & 0 deletions .streerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--print-width=100
--plugins=plugin/trailing_comma,disable_ternary
23 changes: 12 additions & 11 deletions bench/bench.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# frozen_string_literal: true

require_relative '../lib/prometheus_exporter'
require_relative '../lib/prometheus_exporter/client'
require_relative '../lib/prometheus_exporter/server'
require_relative "../lib/prometheus_exporter"
require_relative "../lib/prometheus_exporter/client"
require_relative "../lib/prometheus_exporter/server"

# test how long it takes a custom collector to process 10k messages

Expand All @@ -26,18 +26,19 @@ def prometheus_metrics_text
@client = nil
@runs = 1000

done = lambda do
puts "Elapsed for 10k messages is #{Time.now - @start}"
if (@runs -= 1) > 0
@start = Time.now
10_000.times { @client.send_json(hello: "world") }
done =
lambda do
puts "Elapsed for 10k messages is #{Time.now - @start}"
if (@runs -= 1) > 0
@start = Time.now
10_000.times { @client.send_json(hello: "world") }
end
end
end

collector = Collector.new(done)
server = PrometheusExporter::Server::WebServer.new port: 12349, collector: collector
server = PrometheusExporter::Server::WebServer.new port: 12_349, collector: collector
server.start
@client = PrometheusExporter::Client.new port: 12349, max_queue_size: 100_000
@client = PrometheusExporter::Client.new port: 12_349, max_queue_size: 100_000

@start = Time.now
10_000.times { @client.send_json(hello: "world") }
Expand Down
4 changes: 1 addition & 3 deletions examples/custom_collector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ def process(obj)
end

def prometheus_metrics_text
@mutex.synchronize do
"#{@gauge1.to_prometheus_text}\n#{@gauge2.to_prometheus_text}"
end
@mutex.synchronize { "#{@gauge1.to_prometheus_text}\n#{@gauge2.to_prometheus_text}" }
end
end
34 changes: 6 additions & 28 deletions lib/prometheus_exporter/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ def initialize(name:, help:, type:, client:, opts: nil)
end

def standard_values(value, keys, prometheus_exporter_action = nil)
values = {
type: @type,
help: @help,
name: @name,
keys: keys,
value: value
}
values = { type: @type, help: @help, name: @name, keys: keys, value: value }
values[
:prometheus_exporter_action
] = prometheus_exporter_action if prometheus_exporter_action
Expand Down Expand Up @@ -59,10 +53,7 @@ def self.default=(client)

def initialize(
host: ENV.fetch("PROMETHEUS_EXPORTER_HOST", "localhost"),
port: ENV.fetch(
"PROMETHEUS_EXPORTER_PORT",
PrometheusExporter::DEFAULT_PORT
),
port: ENV.fetch("PROMETHEUS_EXPORTER_PORT", PrometheusExporter::DEFAULT_PORT),
max_queue_size: nil,
thread_sleep: 0.5,
json_serializer: nil,
Expand All @@ -83,9 +74,7 @@ def initialize(
max_queue_size ||= MAX_QUEUE_SIZE
max_queue_size = max_queue_size.to_i

if max_queue_size <= 0
raise ArgumentError, "max_queue_size must be larger than 0"
end
raise ArgumentError, "max_queue_size must be larger than 0" if max_queue_size <= 0

@max_queue_size = max_queue_size
@host = host
Expand All @@ -94,8 +83,7 @@ def initialize(
@mutex = Mutex.new
@thread_sleep = thread_sleep

@json_serializer =
json_serializer == :oj ? PrometheusExporter::OjCompat : JSON
@json_serializer = json_serializer == :oj ? PrometheusExporter::OjCompat : JSON

@custom_labels = custom_labels
end
Expand All @@ -105,14 +93,7 @@ def custom_labels=(custom_labels)
end

def register(type, name, help, opts = nil)
metric =
RemoteMetric.new(
type: type,
name: name,
help: help,
client: self,
opts: opts
)
metric = RemoteMetric.new(type: type, name: name, help: help, client: self, opts: opts)
@metrics << metric
metric
end
Expand Down Expand Up @@ -262,10 +243,7 @@ def ensure_socket!
def wait_for_empty_queue_with_timeout(timeout_seconds)
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
while @queue.length > 0
if start_time + timeout_seconds <
::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
break
end
break if start_time + timeout_seconds < ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
sleep(0.05)
end
end
Expand Down
28 changes: 20 additions & 8 deletions lib/prometheus_exporter/instrumentation/active_record.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
# collects stats from currently running process
module PrometheusExporter::Instrumentation
class ActiveRecord < PeriodicStats
ALLOWED_CONFIG_LABELS = %i(database username host port)
ALLOWED_CONFIG_LABELS = %i[database username host port]

def self.start(client: nil, frequency: 30, custom_labels: {}, config_labels: [])
client ||= PrometheusExporter::Client.default

# Not all rails versions support connection pool stats
unless ::ActiveRecord::Base.connection_pool.respond_to?(:stat)
client.logger.error("ActiveRecord connection pool stats not supported in your rails version")
client.logger.error(
"ActiveRecord connection pool stats not supported in your rails version",
)
return
end

Expand All @@ -29,7 +31,9 @@ def self.start(client: nil, frequency: 30, custom_labels: {}, config_labels: [])

def self.validate_config_labels(config_labels)
return if config_labels.size == 0
raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}" if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
if (config_labels - ALLOWED_CONFIG_LABELS).size > 0
raise "Invalid Config Labels, available options #{ALLOWED_CONFIG_LABELS}"
end
end

def initialize(metric_labels, config_labels)
Expand All @@ -55,7 +59,7 @@ def collect_active_record_pool_stats(metrics)
pid: pid,
type: "active_record",
hostname: ::PrometheusExporter.hostname,
metric_labels: labels(pool)
metric_labels: labels(pool),
}
metric.merge!(pool.stat)
metrics << metric
Expand All @@ -66,12 +70,20 @@ def collect_active_record_pool_stats(metrics)

def labels(pool)
if ::ActiveRecord.version < Gem::Version.new("6.1.0.rc1")
@metric_labels.merge(pool_name: pool.spec.name).merge(pool.spec.config
.select { |k, v| @config_labels.include? k }
.map { |k, v| [k.to_s.dup.prepend("dbconfig_"), v] }.to_h)
@metric_labels.merge(pool_name: pool.spec.name).merge(
pool
.spec
.config
.select { |k, v| @config_labels.include? k }
.map { |k, v| [k.to_s.dup.prepend("dbconfig_"), v] }
.to_h,
)
else
@metric_labels.merge(pool_name: pool.db_config.name).merge(
@config_labels.each_with_object({}) { |l, acc| acc["dbconfig_#{l}"] = pool.db_config.public_send(l) })
@config_labels.each_with_object({}) do |l, acc|
acc["dbconfig_#{l}"] = pool.db_config.public_send(l)
end,
)
end
end
end
Expand Down
31 changes: 20 additions & 11 deletions lib/prometheus_exporter/instrumentation/delayed_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,33 @@

module PrometheusExporter::Instrumentation
class DelayedJob
JOB_CLASS_REGEXP = %r{job_class: ((\w+:{0,2})+)}.freeze
JOB_CLASS_REGEXP = /job_class: ((\w+:{0,2})+)/.freeze

class << self
def register_plugin(client: nil, include_module_name: false)
instrumenter = self.new(client: client)
return unless defined?(Delayed::Plugin)

plugin = Class.new(Delayed::Plugin) do
callbacks do |lifecycle|
lifecycle.around(:invoke_job) do |job, *args, &block|
max_attempts = Delayed::Worker.max_attempts
enqueued_count = Delayed::Job.where(queue: job.queue).count
pending_count = Delayed::Job.where(attempts: 0, locked_at: nil, queue: job.queue).count
instrumenter.call(job, max_attempts, enqueued_count, pending_count, include_module_name,
*args, &block)
plugin =
Class.new(Delayed::Plugin) do
callbacks do |lifecycle|
lifecycle.around(:invoke_job) do |job, *args, &block|
max_attempts = Delayed::Worker.max_attempts
enqueued_count = Delayed::Job.where(queue: job.queue).count
pending_count =
Delayed::Job.where(attempts: 0, locked_at: nil, queue: job.queue).count
instrumenter.call(
job,
max_attempts,
enqueued_count,
pending_count,
include_module_name,
*args,
&block
)
end
end
end
end

Delayed::Worker.plugins << plugin
end
Expand Down Expand Up @@ -50,7 +59,7 @@ def call(job, max_attempts, enqueued_count, pending_count, include_module_name,
attempts: attempts,
max_attempts: max_attempts,
enqueued: enqueued_count,
pending: pending_count
pending: pending_count,
)
end
end
Expand Down
6 changes: 2 additions & 4 deletions lib/prometheus_exporter/instrumentation/good_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ def self.start(client: nil, frequency: 30)
good_job_collector = new
client ||= PrometheusExporter::Client.default

worker_loop do
client.send_json(good_job_collector.collect)
end
worker_loop { client.send_json(good_job_collector.collect) }

super
end
Expand All @@ -23,7 +21,7 @@ def collect
running: ::GoodJob::Job.running.size,
finished: ::GoodJob::Job.finished.size,
succeeded: ::GoodJob::Job.succeeded.size,
discarded: ::GoodJob::Job.discarded.size
discarded: ::GoodJob::Job.discarded.size,
}
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/prometheus_exporter/instrumentation/hutch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def handle(message)
type: "hutch",
name: @klass.class.to_s,
success: success,
duration: duration
duration: duration,
)
end
end
Expand Down
24 changes: 12 additions & 12 deletions lib/prometheus_exporter/instrumentation/method_profiler.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# frozen_string_literal: true

# see https://samsaffron.com/archive/2017/10/18/fastest-way-to-profile-a-method-in-ruby
module PrometheusExporter::Instrumentation; end
module PrometheusExporter::Instrumentation
end

class PrometheusExporter::Instrumentation::MethodProfiler
def self.patch(klass, methods, name, instrument:)
Expand All @@ -21,9 +22,8 @@ def self.transfer
end

def self.start(transfer = nil)
Thread.current[:_method_profiler] = transfer || {
__start: Process.clock_gettime(Process::CLOCK_MONOTONIC)
}
Thread.current[:_method_profiler] = transfer ||
{ __start: Process.clock_gettime(Process::CLOCK_MONOTONIC) }
end

def self.clear
Expand All @@ -42,8 +42,8 @@ def self.stop

def self.define_methods_on_module(klass, methods, name)
patch_source_line = __LINE__ + 3
patches = methods.map do |method_name|
<<~RUBY

patches = methods.map { |method_name| <<~RUBY }.join("\n")
def #{method_name}(...)
unless prof = Thread.current[:_method_profiler]
return super
Expand All @@ -58,9 +58,8 @@ def #{method_name}(...)
end
end
RUBY
end.join("\n")

klass.module_eval patches, __FILE__, patch_source_line
klass.module_eval(patches, __FILE__, patch_source_line)
end

def self.patch_using_prepend(klass, methods, name)
Expand All @@ -71,14 +70,16 @@ def self.patch_using_prepend(klass, methods, name)

def self.patch_using_alias_method(klass, methods, name)
patch_source_line = __LINE__ + 3
patches = methods.map do |method_name|
<<~RUBY

patches = methods.map { |method_name| <<~RUBY }.join("\n")
unless defined?(#{method_name}__mp_unpatched)
alias_method :#{method_name}__mp_unpatched, :#{method_name}

def #{method_name}(...)
unless prof = Thread.current[:_method_profiler]
return #{method_name}__mp_unpatched(...)
end

begin
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
#{method_name}__mp_unpatched(...)
Expand All @@ -90,8 +91,7 @@ def #{method_name}(...)
end
end
RUBY
end.join("\n")

klass.class_eval patches, __FILE__, patch_source_line
klass.class_eval(patches, __FILE__, patch_source_line)
end
end
Loading
Loading