Commit 7c02ca71 authored by Piotr Skorupa's avatar Piotr Skorupa Committed by Alper Akgun

Add unified metrics definition YAML file API endpoint

parent 4371aec5
---
title: Add unified metrics definition YAML file API endpoint
merge_request: 57270
author:
type: added
......@@ -1411,6 +1411,37 @@ bin/rake gitlab:usage_data:dump_sql_in_json
bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml
```
## Export metric definitions as a single YAML file
Use this API endpoint to export all metric definitions as a single YAML file, similar to the [Metrics Dictionary](dictionary.md), for easier importing.
```plaintext
GET /usage_data/metric_definitions
```
Response
```yaml
---
- key_path: redis_hll_counters.search.i_search_paid_monthly
description: Calculated unique users to perform a search with a paid license enabled
by month
product_section: enablement
product_stage: enablement
product_group: group::global search
product_category: global_search
value_type: number
status: data_available
time_frame: 28d
data_source: redis_hll
distribution:
- ee
tier:
- premium
- ultimate
...
```
## Generating and troubleshooting usage ping
This activity is to be done via a detached screen session on a remote server.
......
......@@ -2,7 +2,7 @@
module API
class UsageData < ::API::Base
before { authenticate! }
before { authenticate_non_get! }
feature_category :usage_ping
......@@ -15,11 +15,9 @@ module API
desc 'Track usage data events' do
detail 'This feature was introduced in GitLab 13.4.'
end
params do
requires :event, type: String, desc: 'The event name that should be tracked'
end
post 'increment_counter' do
event_name = params[:event]
......@@ -31,7 +29,6 @@ module API
params do
requires :event, type: String, desc: 'The event name that should be tracked'
end
post 'increment_unique_users' do
event_name = params[:event]
......@@ -39,6 +36,16 @@ module API
status :ok
end
desc 'Get a list of all metric definitions' do
detail 'This feature was introduced in GitLab 13.11.'
end
get 'metric_definitions' do
content_type 'application/yaml'
env['api.format'] = :binary
Gitlab::Usage::MetricDefinition.dump_metrics_yaml
end
end
end
end
......@@ -69,6 +69,10 @@ module Gitlab
@schemer ||= ::JSONSchemer.schema(Pathname.new(METRIC_SCHEMA_PATH))
end
def dump_metrics_yaml
@metrics_yaml ||= definitions.values.map(&:to_h).map(&:deep_stringify_keys).to_yaml
end
private
def load_all!
......
......@@ -25,6 +25,13 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
let(:definition) { described_class.new(path, attributes) }
let(:yaml_content) { attributes.deep_stringify_keys.to_yaml }
def write_metric(metric, path, content)
path = File.join(metric, path)
dir = File.dirname(path)
FileUtils.mkdir_p(dir)
File.write(path, content)
end
it 'has all definitons valid' do
expect { described_class.definitions }.not_to raise_error(Gitlab::Usage::Metric::InvalidMetricError)
end
......@@ -145,12 +152,54 @@ RSpec.describe Gitlab::Usage::MetricDefinition do
FileUtils.rm_rf(metric1)
FileUtils.rm_rf(metric2)
end
end
describe 'dump_metrics_yaml' do
let(:other_attributes) do
{
description: 'Test metric definition',
value_type: 'string',
product_category: 'collection',
product_stage: 'growth',
status: 'data_available',
default_generation: 'generation_1',
key_path: 'counter.category.event',
product_group: 'group::product analytics',
time_frame: 'none',
data_source: 'database',
distribution: %w(ee ce),
tier: %w(free starter premium ultimate bronze silver gold)
}
end
let(:other_yaml_content) { other_attributes.deep_stringify_keys.to_yaml }
let(:other_path) { File.join('metrics', 'test_metric.yml') }
let(:metric1) { Dir.mktmpdir('metric1') }
let(:metric2) { Dir.mktmpdir('metric2') }
before do
allow(described_class).to receive(:paths).and_return(
[
File.join(metric1, '**', '*.yml'),
File.join(metric2, '**', '*.yml')
]
)
# Reset memoized `definitions` result
described_class.instance_variable_set(:@definitions, nil)
end
after do
FileUtils.rm_rf(metric1)
FileUtils.rm_rf(metric2)
end
subject { described_class.dump_metrics_yaml }
it 'returns a YAML with both metrics in a sequence' do
write_metric(metric1, path, yaml_content)
write_metric(metric2, other_path, other_yaml_content)
def write_metric(metric, path, content)
path = File.join(metric, path)
dir = File.dirname(path)
FileUtils.mkdir_p(dir)
File.write(path, content)
is_expected.to eq([attributes, other_attributes].map(&:deep_stringify_keys).to_yaml)
end
end
end
......@@ -161,4 +161,23 @@ RSpec.describe API::UsageData do
end
end
end
describe 'GET /usage_data/metric_definitions' do
let(:endpoint) { '/usage_data/metric_definitions' }
let(:metric_yaml) do
{ 'key_path' => 'counter.category.event', 'description' => 'Metric description' }.to_yaml
end
context 'without authentication' do
it 'returns a YAML file', :aggregate_failures do
allow(Gitlab::Usage::MetricDefinition).to receive(:dump_metrics_yaml).and_return(metric_yaml)
get api(endpoint)
expect(response).to have_gitlab_http_status(:ok)
expect(response.media_type).to eq('application/yaml')
expect(response.body).to eq(metric_yaml)
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