Commit ee6f8150 authored by Max Woolf's avatar Max Woolf

Add ability to track unique uses of API endpoints

This MR adds Grape middleware that allows the
tracking of unique users use of any API endpoint.

This MR adds specific support for tracking unique
use of /audit_events.

It also adds the collected data to
the usage ping.
parent c732561d
---
title: Add ability to track unique uses of API endpoints
merge_request: 39616
author:
type: added
......@@ -3,6 +3,7 @@
module API
class AuditEvents < ::Grape::API::Instance
include ::API::PaginationParams
use ::API::UniqueCallTracking, event_name: 'i_compliance_audit_events_api', feature: :track_unique_visits
before do
authenticated_as_admin!
......
# frozen_string_literal: true
module API
class UniqueCallTracking < Grape::Middleware::Base
def visitor_id
return context.session[:visitor_id] if context.session[:visitor_id].present?
return unless context.current_user
uuid = SecureRandom.uuid
context.session[:visitor_id] = uuid
uuid
end
def track_redis_hll_event(event_name, feature)
return unless feature_enabled?(feature)
return unless visitor_id
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, event_name)
end
def after
track_redis_hll_event(@options[:event_name], @options[:feature])
nil
end
private
def feature_enabled?(feature = :track_unique_visits)
Feature.enabled?(feature) && Gitlab::CurrentSettings.usage_ping_enabled?
end
end
end
......@@ -89,6 +89,8 @@ module EE
end
segment ':id/audit_events' do
use ::API::UniqueCallTracking, event_name: 'i_compliance_audit_events_api', feature: :track_unique_visits
before do
authorize! :admin_group, user_group
check_audit_events_available!(user_group)
......
......@@ -22,6 +22,8 @@ module EE
end
end
segment ':id/audit_events' do
use ::API::UniqueCallTracking, event_name: 'i_compliance_audit_events_api', feature: :track_unique_visits
before do
authorize! :admin_project, user_project
check_audit_events_available!(user_project)
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe API::UniqueCallTracking do
describe 'i_compliance_audit_events_api', :clean_gitlab_redis_shared_state do
let_it_be(:current_user) { create(:admin) }
let_it_be(:group) { create(:group, owner_id: current_user) }
let_it_be(:project) { create(:project) }
before do
project.add_user(current_user, :maintainer)
end
context 'after calling all audit_events APIs as a single licensed user' do
before do
stub_feature_flags(track_unique_visits: true)
stub_licensed_features(admin_audit_log: true)
end
subject do
travel_to 8.days.ago do
get api('/audit_events', current_user)
get api("/groups/#{group.id}/audit_events", current_user)
get api("/projects/#{project.id}/audit_events", current_user)
end
end
it 'tracks 3 separate events' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).exactly(3).times
.with(an_instance_of(String), an_instance_of(String))
subject
end
it 'reports one unique event' do
subject
expect(Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'i_compliance_audit_events_api', start_date: 2.months.ago, end_date: Date.current)).to eq(1)
end
end
end
end
......@@ -16,6 +16,11 @@
category: compliance
redis_slot: compliance
aggregation: weekly
- name: i_compliance_audit_events_api
category: compliance
redis_slot: compliance
expiry: 42
aggregation: weekly
# Analytics category
- name: g_analytics_contribution
category: analytics
......
......@@ -1013,6 +1013,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
'g_compliance_audit_events' => 123,
'i_compliance_credential_inventory' => 123,
'i_compliance_audit_events' => 123,
'i_compliance_audit_events_api' => 123,
'compliance_unique_visits_for_any_target' => 543,
'compliance_unique_visits_for_any_target_monthly' => 987
}
......
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