Commit 03bee06c authored by Alper Akgun's avatar Alper Akgun

Merge branch...

Merge branch '327736-add-extra-arguments-to-metric-yaml-defintion-for-filtering-data-in-instrumentation-class' into 'master'

Add options arguments to Redis HLL Metric YAML definition for filtering data in instrumentation class

See merge request gitlab-org/gitlab!61685
parents cf891458 36593d92
---
title: Add options events to Redis HLL metrics for filtering data
merge_request: 61685
author:
type: other
...@@ -9,7 +9,10 @@ value_type: number ...@@ -9,7 +9,10 @@ value_type: number
status: data_available status: data_available
time_frame: 28d time_frame: 28d
data_source: redis_hll data_source: redis_hll
instrumentation_class: CountUsersUsingApproveQuickActionMetric instrumentation_class: RedisHLLMetric
options:
events:
- i_quickactions_approve
distribution: distribution:
- ce - ce
- ee - ee
......
...@@ -9,7 +9,10 @@ value_type: number ...@@ -9,7 +9,10 @@ value_type: number
status: data_available status: data_available
time_frame: 7d time_frame: 7d
data_source: redis_hll data_source: redis_hll
instrumentation_class: CountUsersUsingApproveQuickActionMetric instrumentation_class: RedisHLLMetric
options:
events:
- i_quickactions_approve
distribution: distribution:
- ce - ce
- ee - ee
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
"introduced_by_url": { "introduced_by_url": {
"type": ["string", "null"] "type": ["string", "null"]
}, },
"extra": { "options": {
"type": "object" "type": "object"
}, },
"time_frame": { "time_frame": {
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
}, },
"instrumentation_class": { "instrumentation_class": {
"type": "string", "type": "string",
"pattern": "^(([A-Z][a-z]+)+::)*(([A-Z][a-z]+)+)$" "pattern": "^(([A-Z][a-z]+)+::)*(([A-Z]+[a-z]+)+)$"
}, },
"distribution": { "distribution": {
"type": "array", "type": "array",
......
...@@ -43,7 +43,7 @@ Each metric is defined in a separate YAML file consisting of a number of fields: ...@@ -43,7 +43,7 @@ Each metric is defined in a separate YAML file consisting of a number of fields:
| `milestone` | no | The milestone when the metric is introduced. | | `milestone` | no | The milestone when the metric is introduced. |
| `milestone_removed` | no | The milestone when the metric is removed. | | `milestone_removed` | no | The milestone when the metric is removed. |
| `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. | | `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. |
| `extra` | no | `object`: extra information needed to calculate the metric value. | | `options` | no | `object`: options information needed to calculate the metric value. |
| `skip_validation` | no | This should **not** be set. [Used for imported metrics until we review, update and make them valid](https://gitlab.com/groups/gitlab-org/-/epics/5425). | | `skip_validation` | no | This should **not** be set. [Used for imported metrics until we review, update and make them valid](https://gitlab.com/groups/gitlab-org/-/epics/5425). |
### Metric statuses ### Metric statuses
......
...@@ -53,20 +53,17 @@ end ...@@ -53,20 +53,17 @@ end
## Redis HyperLogLog metrics ## Redis HyperLogLog metrics
[Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60089/diffs). [Example of a merge request that adds a `RedisHLL` metric](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61685).
```ruby Count unique values for `i_quickactions_approve` event.
module Gitlab
module Usage ```yaml
module Metrics time_frame: 28d
module Instrumentations data_source: redis_hll
class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric instrumentation_class: 'Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric'
event_names :i_quickactions_approve options:
end events:
end - i_quickactions_approve
end
end
end
``` ```
## Generic metrics ## Generic metrics
......
...@@ -8,9 +8,11 @@ module Gitlab ...@@ -8,9 +8,11 @@ module Gitlab
include Gitlab::Utils::UsageData include Gitlab::Utils::UsageData
attr_reader :time_frame attr_reader :time_frame
attr_reader :options
def initialize(time_frame:) def initialize(time_frame:, options: {})
@time_frame = time_frame @time_frame = time_frame
@options = options
end end
end end
end end
......
# frozen_string_literal: true
module Gitlab
module Usage
module Metrics
module Instrumentations
class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric
event_names :i_quickactions_approve
end
end
end
end
end
...@@ -7,20 +7,24 @@ module Gitlab ...@@ -7,20 +7,24 @@ module Gitlab
class RedisHLLMetric < BaseMetric class RedisHLLMetric < BaseMetric
# Usage example # Usage example
# #
# class CountUsersVisitingAnalyticsValuestreamMetric < RedisHLLMetric # In metric YAML defintion
# event_names :g_analytics_valuestream # instrumentation_class: RedisHLLMetric
# events:
# - g_analytics_valuestream
# end # end
class << self def initialize(time_frame:, options: {})
def event_names(events = nil) super
@metric_events = events
raise ArgumentError, "options events are required" unless metric_events.present?
end end
attr_reader :metric_events def metric_events
options[:events]
end end
def value def value
redis_usage_data do redis_usage_data do
event_params = time_constraints.merge(event_names: self.class.metric_events) event_params = time_constraints.merge(event_names: metric_events)
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(**event_params) Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(**event_params)
end end
...@@ -35,7 +39,7 @@ module Gitlab ...@@ -35,7 +39,7 @@ module Gitlab
when '7d' when '7d'
{ start_date: 7.days.ago.to_date, end_date: Date.current } { start_date: 7.days.ago.to_date, end_date: Date.current }
else else
raise "Unknown time frame: #{time_frame} for TimeConstraint" raise "Unknown time frame: #{time_frame} for RedisHLLMetric"
end end
end end
end end
......
...@@ -7,9 +7,12 @@ module Gitlab ...@@ -7,9 +7,12 @@ module Gitlab
def uncached_data def uncached_data
::Gitlab::Usage::MetricDefinition.all.map do |definition| ::Gitlab::Usage::MetricDefinition.all.map do |definition|
instrumentation_class = definition.attributes[:instrumentation_class] instrumentation_class = definition.attributes[:instrumentation_class]
options = definition.attributes[:options]
if instrumentation_class.present? if instrumentation_class.present?
metric_value = "Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}".constantize.new(time_frame: definition.attributes[:time_frame]).value metric_value = "Gitlab::Usage::Metrics::Instrumentations::#{instrumentation_class}".constantize.new(
time_frame: definition.attributes[:time_frame],
options: options).value
metric_payload(definition.key_path, metric_value) metric_payload(definition.key_path, metric_value)
else else
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
require 'spec_helper' require 'spec_helper'
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQuickActionMetric, :clean_gitlab_redis_shared_state do RSpec.describe Gitlab::Usage::Metrics::Instrumentations::RedisHLLMetric, :clean_gitlab_redis_shared_state do
before do before do
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago) Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 1.week.ago)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago) Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 1, time: 2.weeks.ago)
...@@ -10,6 +10,10 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQ ...@@ -10,6 +10,10 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::CountUsersUsingApproveQ
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago) Gitlab::UsageDataCounters::HLLRedisCounter.track_event(:i_quickactions_approve, values: 2, time: 2.months.ago)
end end
it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', data_source: 'redis_hll' }, 2 it_behaves_like 'a correct instrumented metric value', { time_frame: '28d', options: { events: ['i_quickactions_approve'] } }, 2
it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', data_source: 'redis_hll' }, 1 it_behaves_like 'a correct instrumented metric value', { time_frame: '7d', options: { events: ['i_quickactions_approve'] } }, 1
it 'raise exception if vents options is not present' do
expect { described_class.new(time_frame: '28d') }.to raise_error(ArgumentError)
end
end end
# frozen_string_literal: true # frozen_string_literal: true
RSpec.shared_examples 'a correct instrumented metric value' do |options, expected_value| RSpec.shared_examples 'a correct instrumented metric value' do |params, expected_value|
let(:time_frame) { options[:time_frame] } let(:time_frame) { params[:time_frame] }
let(:options) { params[:options] }
before do before do
allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false)
end end
it 'has correct value' do it 'has correct value' do
expect(described_class.new(time_frame: time_frame).value).to eq(expected_value) expect(described_class.new(time_frame: time_frame, options: options).value).to eq(expected_value)
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