Commit 3a300898 authored by Sean McGivern's avatar Sean McGivern

Only initialise metrics for the most common feature categories

Most feature categories aren't used at all yet, even on GitLab.com. This
meant we generated a huge amount of series that would never change. As a
compromise between initialising nothing (and having gaps, plus
unpredictable memory usage in Prometheus) and initialising
everything (explosion in number of series), we only initialise for the
top five categories as of today, plus the default category of `unknown`.

The top five categories do include `not_owned`, but that's probably OK.
parent 041d04e3
...@@ -18,6 +18,15 @@ module Gitlab ...@@ -18,6 +18,15 @@ module Gitlab
FEATURE_CATEGORY_HEADER = 'X-Gitlab-Feature-Category' FEATURE_CATEGORY_HEADER = 'X-Gitlab-Feature-Category'
FEATURE_CATEGORY_DEFAULT = 'unknown' FEATURE_CATEGORY_DEFAULT = 'unknown'
# These were the top 5 categories at a point in time, chosen as a
# reasonable default. If we initialize every category we'll end up
# with an explosion in unused metric combinations, but we want the
# most common ones to be always present.
FEATURE_CATEGORIES_TO_INITIALIZE = ['authentication_and_authorization',
'code_review', 'continuous_integration',
'not_owned', 'source_code_management',
FEATURE_CATEGORY_DEFAULT].freeze
def initialize(app) def initialize(app)
@app = app @app = app
end end
...@@ -46,16 +55,10 @@ module Gitlab ...@@ -46,16 +55,10 @@ module Gitlab
# #
# For example `rate(http_requests_total{status="500"}[1m])` would return # For example `rate(http_requests_total{status="500"}[1m])` would return
# no data until the first 500 error would occur. # no data until the first 500 error would occur.
# The list of feature categories is currently not needed by the application
# anywhere else. So no need to keep these in memory forever.
# Doing it here, means we're only reading the file on boot.
feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip).uniq << FEATURE_CATEGORY_DEFAULT
HTTP_METHODS.each do |method, statuses| HTTP_METHODS.each do |method, statuses|
http_request_duration_seconds.get({ method: method }) http_request_duration_seconds.get({ method: method })
statuses.product(feature_categories) do |status, feature_category| statuses.product(FEATURE_CATEGORIES_TO_INITIALIZE) do |status, feature_category|
http_requests_total.get({ method: method, status: status, feature_category: feature_category }) http_requests_total.get({ method: method, status: status, feature_category: feature_category })
end end
end end
......
...@@ -129,12 +129,11 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do ...@@ -129,12 +129,11 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
describe '.initialize_metrics', :prometheus do describe '.initialize_metrics', :prometheus do
it "sets labels for http_requests_total" do it "sets labels for http_requests_total" do
feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip) << described_class::FEATURE_CATEGORY_DEFAULT
expected_labels = [] expected_labels = []
described_class::HTTP_METHODS.each do |method, statuses| described_class::HTTP_METHODS.each do |method, statuses|
statuses.each do |status| statuses.each do |status|
feature_categories.each do |feature_category| described_class::FEATURE_CATEGORIES_TO_INITIALIZE.each do |feature_category|
expected_labels << { method: method.to_s, status: status.to_s, feature_category: feature_category.to_s } expected_labels << { method: method.to_s, status: status.to_s, feature_category: feature_category.to_s }
end end
end end
...@@ -152,6 +151,13 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do ...@@ -152,6 +151,13 @@ RSpec.describe Gitlab::Metrics::RequestsRackMiddleware, :aggregate_failures do
expect(described_class.http_request_duration_seconds.values.keys).to include(*expected_labels) expect(described_class.http_request_duration_seconds.values.keys).to include(*expected_labels)
end end
it 'has every label in config/feature_categories.yml' do
defaults = [described_class::FEATURE_CATEGORY_DEFAULT, 'not_owned']
feature_categories = YAML.load_file(Rails.root.join('config', 'feature_categories.yml')).map(&:strip) + defaults
expect(described_class::FEATURE_CATEGORIES_TO_INITIALIZE).to all(be_in(feature_categories))
end
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment