68b946e3c8
`current_application_settings` used by `influx_metrics_enabled` executed a markdown parsing code that was measured using `Gitlab::Metrics.measure` But since the Gitlab::Metrics::InfluxDb was not yet build so Gitlab::Metrics did not yet have `measure` method. Causing the NoMethodError. However If run was successful at least once then result was cached in a file and this code never executed again. Which caused this issue to only show up in CI preparation step.
170 lines
4.8 KiB
Ruby
170 lines
4.8 KiB
Ruby
module Gitlab
|
|
module Metrics
|
|
module InfluxDb
|
|
extend Gitlab::CurrentSettings
|
|
extend self
|
|
|
|
MUTEX = Mutex.new
|
|
private_constant :MUTEX
|
|
|
|
def influx_metrics_enabled?
|
|
settings[:enabled] || false
|
|
end
|
|
|
|
RAILS_ROOT = Rails.root.to_s
|
|
METRICS_ROOT = Rails.root.join('lib', 'gitlab', 'metrics').to_s
|
|
PATH_REGEX = /^#{RAILS_ROOT}\/?/
|
|
|
|
def settings
|
|
@settings ||= {
|
|
enabled: current_application_settings[:metrics_enabled],
|
|
pool_size: current_application_settings[:metrics_pool_size],
|
|
timeout: current_application_settings[:metrics_timeout],
|
|
method_call_threshold: current_application_settings[:metrics_method_call_threshold],
|
|
host: current_application_settings[:metrics_host],
|
|
port: current_application_settings[:metrics_port],
|
|
sample_interval: current_application_settings[:metrics_sample_interval] || 15,
|
|
packet_size: current_application_settings[:metrics_packet_size] || 1
|
|
}
|
|
end
|
|
|
|
def mri?
|
|
RUBY_ENGINE == 'ruby'
|
|
end
|
|
|
|
def method_call_threshold
|
|
# This is memoized since this method is called for every instrumented
|
|
# method. Loading data from an external cache on every method call slows
|
|
# things down too much.
|
|
@method_call_threshold ||= settings[:method_call_threshold]
|
|
end
|
|
|
|
def submit_metrics(metrics)
|
|
prepared = prepare_metrics(metrics)
|
|
|
|
pool&.with do |connection|
|
|
prepared.each_slice(settings[:packet_size]) do |slice|
|
|
begin
|
|
connection.write_points(slice)
|
|
rescue StandardError
|
|
end
|
|
end
|
|
end
|
|
rescue Errno::EADDRNOTAVAIL, SocketError => ex
|
|
Gitlab::EnvironmentLogger.error('Cannot resolve InfluxDB address. GitLab Performance Monitoring will not work.')
|
|
Gitlab::EnvironmentLogger.error(ex)
|
|
end
|
|
|
|
def prepare_metrics(metrics)
|
|
metrics.map do |hash|
|
|
new_hash = hash.symbolize_keys
|
|
|
|
new_hash[:tags].each do |key, value|
|
|
if value.blank?
|
|
new_hash[:tags].delete(key)
|
|
else
|
|
new_hash[:tags][key] = escape_value(value)
|
|
end
|
|
end
|
|
|
|
new_hash
|
|
end
|
|
end
|
|
|
|
def escape_value(value)
|
|
value.to_s.gsub('=', '\\=')
|
|
end
|
|
|
|
# Measures the execution time of a block.
|
|
#
|
|
# Example:
|
|
#
|
|
# Gitlab::Metrics.measure(:find_by_username_duration) do
|
|
# User.find_by_username(some_username)
|
|
# end
|
|
#
|
|
# name - The name of the field to store the execution time in.
|
|
#
|
|
# Returns the value yielded by the supplied block.
|
|
def measure(name)
|
|
trans = current_transaction
|
|
|
|
return yield unless trans
|
|
|
|
real_start = Time.now.to_f
|
|
cpu_start = System.cpu_time
|
|
|
|
retval = yield
|
|
|
|
cpu_stop = System.cpu_time
|
|
real_stop = Time.now.to_f
|
|
|
|
real_time = (real_stop - real_start) * 1000.0
|
|
cpu_time = cpu_stop - cpu_start
|
|
|
|
trans.increment("#{name}_real_time", real_time)
|
|
trans.increment("#{name}_cpu_time", cpu_time)
|
|
trans.increment("#{name}_call_count", 1)
|
|
|
|
retval
|
|
end
|
|
|
|
# Adds a tag to the current transaction (if any)
|
|
#
|
|
# name - The name of the tag to add.
|
|
# value - The value of the tag.
|
|
def tag_transaction(name, value)
|
|
trans = current_transaction
|
|
|
|
trans&.add_tag(name, value)
|
|
end
|
|
|
|
# Sets the action of the current transaction (if any)
|
|
#
|
|
# action - The name of the action.
|
|
def action=(action)
|
|
trans = current_transaction
|
|
|
|
trans&.action = action
|
|
end
|
|
|
|
# Tracks an event.
|
|
#
|
|
# See `Gitlab::Metrics::Transaction#add_event` for more details.
|
|
def add_event(*args)
|
|
trans = current_transaction
|
|
|
|
trans&.add_event(*args)
|
|
end
|
|
|
|
# Returns the prefix to use for the name of a series.
|
|
def series_prefix
|
|
@series_prefix ||= Sidekiq.server? ? 'sidekiq_' : 'rails_'
|
|
end
|
|
|
|
# Allow access from other metrics related middlewares
|
|
def current_transaction
|
|
Transaction.current
|
|
end
|
|
|
|
# When enabled this should be set before being used as the usual pattern
|
|
# "@foo ||= bar" is _not_ thread-safe.
|
|
def pool
|
|
if influx_metrics_enabled?
|
|
if @pool.nil?
|
|
MUTEX.synchronize do
|
|
@pool ||= ConnectionPool.new(size: settings[:pool_size], timeout: settings[:timeout]) do
|
|
host = settings[:host]
|
|
port = settings[:port]
|
|
|
|
InfluxDB::Client.
|
|
new(udp: { host: host, port: port })
|
|
end
|
|
end
|
|
end
|
|
@pool
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|