Add metric initializer spec
An empty file in one of the instrumented directories will cause the app to fail to start when metrics are enabled. Metrics aren't enabled by default in development or test. We could handle the empty file case explicitly, but a file could still not define the constant it is expected to, so instead run the initializer manually in a spec and check that it succeeds.
This commit is contained in:
parent
65bf7e0d92
commit
a96765e627
|
@ -1,3 +1,117 @@
|
|||
# Autoload all classes that we want to instrument, and instrument the methods we
|
||||
# need. This takes the Gitlab::Metrics::Instrumentation module as an argument so
|
||||
# that we can stub it for testing, as it is only called when metrics are
|
||||
# enabled.
|
||||
#
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def instrument_classes(instrumentation)
|
||||
instrumentation.instrument_instance_methods(Gitlab::Shell)
|
||||
|
||||
instrumentation.instrument_methods(Gitlab::Git)
|
||||
|
||||
Gitlab::Git.constants.each do |name|
|
||||
const = Gitlab::Git.const_get(name)
|
||||
|
||||
next unless const.is_a?(Module)
|
||||
|
||||
instrumentation.instrument_methods(const)
|
||||
instrumentation.instrument_instance_methods(const)
|
||||
end
|
||||
|
||||
# Path to search => prefix to strip from constant
|
||||
paths_to_instrument = {
|
||||
['app', 'finders'] => ['app', 'finders'],
|
||||
['app', 'mailers', 'emails'] => ['app', 'mailers'],
|
||||
['app', 'services', '**'] => ['app', 'services'],
|
||||
['lib', 'gitlab', 'conflicts'] => ['lib'],
|
||||
['lib', 'gitlab', 'diff'] => ['lib'],
|
||||
['lib', 'gitlab', 'email', 'message'] => ['lib'],
|
||||
['lib', 'gitlab', 'checks'] => ['lib']
|
||||
}
|
||||
|
||||
paths_to_instrument.each do |(path, prefix)|
|
||||
prefix = Rails.root.join(*prefix)
|
||||
|
||||
Dir[Rails.root.join(*path + ['*.rb'])].each do |file_path|
|
||||
path = Pathname.new(file_path).relative_path_from(prefix)
|
||||
const = path.to_s.sub('.rb', '').camelize.constantize
|
||||
|
||||
instrumentation.instrument_methods(const)
|
||||
instrumentation.instrument_instance_methods(const)
|
||||
end
|
||||
end
|
||||
|
||||
instrumentation.instrument_methods(Premailer::Adapter::Nokogiri)
|
||||
instrumentation.instrument_instance_methods(Premailer::Adapter::Nokogiri)
|
||||
|
||||
[
|
||||
:Blame, :Branch, :BranchCollection, :Blob, :Commit, :Diff, :Repository,
|
||||
:Tag, :TagCollection, :Tree
|
||||
].each do |name|
|
||||
const = Rugged.const_get(name)
|
||||
|
||||
instrumentation.instrument_methods(const)
|
||||
instrumentation.instrument_instance_methods(const)
|
||||
end
|
||||
|
||||
# Instruments all Banzai filters and reference parsers
|
||||
{
|
||||
Filter: Rails.root.join('lib', 'banzai', 'filter', '*.rb'),
|
||||
ReferenceParser: Rails.root.join('lib', 'banzai', 'reference_parser', '*.rb')
|
||||
}.each do |const_name, path|
|
||||
Dir[path].each do |file|
|
||||
klass = File.basename(file, File.extname(file)).camelize
|
||||
const = Banzai.const_get(const_name).const_get(klass)
|
||||
|
||||
instrumentation.instrument_methods(const)
|
||||
instrumentation.instrument_instance_methods(const)
|
||||
end
|
||||
end
|
||||
|
||||
instrumentation.instrument_methods(Banzai::Renderer)
|
||||
instrumentation.instrument_methods(Banzai::Querying)
|
||||
|
||||
instrumentation.instrument_instance_methods(Banzai::ObjectRenderer)
|
||||
instrumentation.instrument_instance_methods(Banzai::Redactor)
|
||||
instrumentation.instrument_methods(Banzai::NoteRenderer)
|
||||
|
||||
[Issuable, Mentionable, Participable].each do |klass|
|
||||
instrumentation.instrument_instance_methods(klass)
|
||||
instrumentation.instrument_instance_methods(klass::ClassMethods)
|
||||
end
|
||||
|
||||
instrumentation.instrument_methods(Gitlab::ReferenceExtractor)
|
||||
instrumentation.instrument_instance_methods(Gitlab::ReferenceExtractor)
|
||||
|
||||
# Instrument the classes used for checking if somebody has push access.
|
||||
instrumentation.instrument_instance_methods(Gitlab::GitAccess)
|
||||
instrumentation.instrument_instance_methods(Gitlab::GitAccessWiki)
|
||||
|
||||
instrumentation.instrument_instance_methods(API::Helpers)
|
||||
|
||||
instrumentation.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker)
|
||||
|
||||
instrumentation.instrument_instance_methods(Rouge::Plugins::Redcarpet)
|
||||
instrumentation.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
|
||||
|
||||
[:XML, :HTML].each do |namespace|
|
||||
namespace_mod = Nokogiri.const_get(namespace)
|
||||
|
||||
instrumentation.instrument_methods(namespace_mod)
|
||||
instrumentation.instrument_methods(namespace_mod::Document)
|
||||
end
|
||||
|
||||
instrumentation.instrument_methods(Rinku)
|
||||
instrumentation.instrument_instance_methods(Repository)
|
||||
|
||||
instrumentation.instrument_methods(Gitlab::Highlight)
|
||||
instrumentation.instrument_instance_methods(Gitlab::Highlight)
|
||||
|
||||
# This is a Rails scope so we have to instrument it manually.
|
||||
instrumentation.instrument_method(Project, :visible_to_user)
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
if Gitlab::Metrics.enabled?
|
||||
require 'pathname'
|
||||
require 'influxdb'
|
||||
|
@ -49,110 +163,7 @@ if Gitlab::Metrics.enabled?
|
|||
end
|
||||
|
||||
Gitlab::Metrics::Instrumentation.configure do |config|
|
||||
config.instrument_instance_methods(Gitlab::Shell)
|
||||
|
||||
config.instrument_methods(Gitlab::Git)
|
||||
|
||||
Gitlab::Git.constants.each do |name|
|
||||
const = Gitlab::Git.const_get(name)
|
||||
|
||||
next unless const.is_a?(Module)
|
||||
|
||||
config.instrument_methods(const)
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
|
||||
# Path to search => prefix to strip from constant
|
||||
paths_to_instrument = {
|
||||
['app', 'finders'] => ['app', 'finders'],
|
||||
['app', 'mailers', 'emails'] => ['app', 'mailers'],
|
||||
['app', 'services', '**'] => ['app', 'services'],
|
||||
['lib', 'gitlab', 'conflicts'] => ['lib'],
|
||||
['lib', 'gitlab', 'diff'] => ['lib'],
|
||||
['lib', 'gitlab', 'email', 'message'] => ['lib'],
|
||||
['lib', 'gitlab', 'checks'] => ['lib']
|
||||
}
|
||||
|
||||
paths_to_instrument.each do |(path, prefix)|
|
||||
prefix = Rails.root.join(*prefix)
|
||||
|
||||
Dir[Rails.root.join(*path + ['*.rb'])].each do |file_path|
|
||||
path = Pathname.new(file_path).relative_path_from(prefix)
|
||||
const = path.to_s.sub('.rb', '').camelize.constantize
|
||||
|
||||
config.instrument_methods(const)
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
end
|
||||
|
||||
config.instrument_methods(Premailer::Adapter::Nokogiri)
|
||||
config.instrument_instance_methods(Premailer::Adapter::Nokogiri)
|
||||
|
||||
[
|
||||
:Blame, :Branch, :BranchCollection, :Blob, :Commit, :Diff, :Repository,
|
||||
:Tag, :TagCollection, :Tree
|
||||
].each do |name|
|
||||
const = Rugged.const_get(name)
|
||||
|
||||
config.instrument_methods(const)
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
|
||||
# Instruments all Banzai filters and reference parsers
|
||||
{
|
||||
Filter: Rails.root.join('lib', 'banzai', 'filter', '*.rb'),
|
||||
ReferenceParser: Rails.root.join('lib', 'banzai', 'reference_parser', '*.rb')
|
||||
}.each do |const_name, path|
|
||||
Dir[path].each do |file|
|
||||
klass = File.basename(file, File.extname(file)).camelize
|
||||
const = Banzai.const_get(const_name).const_get(klass)
|
||||
|
||||
config.instrument_methods(const)
|
||||
config.instrument_instance_methods(const)
|
||||
end
|
||||
end
|
||||
|
||||
config.instrument_methods(Banzai::Renderer)
|
||||
config.instrument_methods(Banzai::Querying)
|
||||
|
||||
config.instrument_instance_methods(Banzai::ObjectRenderer)
|
||||
config.instrument_instance_methods(Banzai::Redactor)
|
||||
config.instrument_methods(Banzai::NoteRenderer)
|
||||
|
||||
[Issuable, Mentionable, Participable].each do |klass|
|
||||
config.instrument_instance_methods(klass)
|
||||
config.instrument_instance_methods(klass::ClassMethods)
|
||||
end
|
||||
|
||||
config.instrument_methods(Gitlab::ReferenceExtractor)
|
||||
config.instrument_instance_methods(Gitlab::ReferenceExtractor)
|
||||
|
||||
# Instrument the classes used for checking if somebody has push access.
|
||||
config.instrument_instance_methods(Gitlab::GitAccess)
|
||||
config.instrument_instance_methods(Gitlab::GitAccessWiki)
|
||||
|
||||
config.instrument_instance_methods(API::Helpers)
|
||||
|
||||
config.instrument_instance_methods(RepositoryCheck::SingleRepositoryWorker)
|
||||
|
||||
config.instrument_instance_methods(Rouge::Plugins::Redcarpet)
|
||||
config.instrument_instance_methods(Rouge::Formatters::HTMLGitlab)
|
||||
|
||||
[:XML, :HTML].each do |namespace|
|
||||
namespace_mod = Nokogiri.const_get(namespace)
|
||||
|
||||
config.instrument_methods(namespace_mod)
|
||||
config.instrument_methods(namespace_mod::Document)
|
||||
end
|
||||
|
||||
config.instrument_methods(Rinku)
|
||||
config.instrument_instance_methods(Repository)
|
||||
|
||||
config.instrument_methods(Gitlab::Highlight)
|
||||
config.instrument_instance_methods(Gitlab::Highlight)
|
||||
|
||||
# This is a Rails scope so we have to instrument it manually.
|
||||
config.instrument_method(Project, :visible_to_user)
|
||||
instrument_classes(config)
|
||||
end
|
||||
|
||||
GC::Profiler.enable
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
require 'spec_helper'
|
||||
require_relative '../../config/initializers/metrics'
|
||||
|
||||
describe 'instrument_classes', lib: true do
|
||||
let(:config) { double(:config) }
|
||||
|
||||
before do
|
||||
allow(config).to receive(:instrument_method)
|
||||
allow(config).to receive(:instrument_methods)
|
||||
allow(config).to receive(:instrument_instance_methods)
|
||||
end
|
||||
|
||||
it 'can autoload and instrument all files' do
|
||||
expect { instrument_classes(config) }.not_to raise_error
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue