Skip to content

Add base framework and tooling for Usage Data metrics instrumentation

What does this MR do?

Add basic tooling for building Usage Ping using instrumentation classes and metrics YAML file definitions

  • Add key processor => to determine the key path for the given metric
  • Add UsageDataMetrics => Usage Data class to generate Usage ping from the instrumentation classes
  • Add uuid metric as example
  • Add RedisHLLMetric instrumentation => class for redis hll metrics
  • Add DatabaseMetric instrumentation => class for database metrics
  • Add GenericMetric instrumentation => class for generic(other) metrics

Resulting Usage Ping:

Added UuidMetric fas example metric

{:uuid=>"7cc411ec-c1c7-46ea-93fd-1563342e6137"}

Usage of this classes

Introduced attribute in metric definition:

instrumentation_class: 'Gitlab::Usage::Metrics::Instrumentations::UuidMetric'

All .yml files having the instrumentation_class set will be used to generate Usage Ping from this classes.

  1. GenericMetric example MR
# hostname_metric.rb
# frozen_string_literal: true

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class HostnameMetric < GenericMetric
          value do
            Gitlab.config.gitlab.host
          end
        end
      end
    end
  end
end
  1. DatabaseMetric example MR

Metric to receive count of issues for time frame set in metric YAML file.

# count_issues_metric.rb

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountIssuesMetric < DatabaseMetric
          operation :count

          start { Issue.minimum(:id) }
          finish { Issue.maximum(:id) }

          relation { Issue }
        end
      end
    end
  end
end

Count of users creating issues for given timeframe

# count_users_creating_issues_Metric.rb

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountUsersCreatingIssuesMetric < DatabaseMetric
          operation :distinct_count, column: :author_id

          relation { Issue }
        end
      end
    end
  end
end

Count of Boards MR example

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountBoardsMetric < DatabaseMetric
          operation :count

          relation { Board }
        end
      end
    end
  end
end
  1. RedisHLLMetric metric example

Metric based on data stored in Redis HLL

Count of users using approve quick action

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountUsersUsingApproveQuickActionMetric < RedisHLLMetric
          event_names :i_quickactions_approve
        end
      end
    end
  end
end

Class Diagram

classDiagram
    BaseMetric <|-- DatabaseMetric
    BaseMetric <|-- RedisHLLMetric
    BaseMetric <|-- GenericMetric
    GenericMetric <|-- UuidMetric
    GenericMetric <|-- HostnameMetric
    DatabaseMetric <|-- CountBoardsMetric
    DatabaseMetric <|-- CountIssuesMetric
    DatabaseMetric <|-- CountUsersCreatingIssuesMetric
    RedisHLLMetric <|-- CountUsersUsingApproveQuickActionMetric
    UsageDataMetrics .. KeyPathProcessor
    UuidMetric --> UsageDataMetrics
    HostnameMetric --> UsageDataMetrics
    CountBoardsMetric --> UsageDataMetrics
    CountIssuesMetric --> UsageDataMetrics
    CountUsersCreatingIssuesMetric --> UsageDataMetrics
    CountUsersUsingApproveQuickActionMetric --> UsageDataMetrics

    class BaseMetric{ 
      +time_frame
      +self.metric_value
      
      +value()
      +self.value(&block)
    }

    class RedisHLLMetric{
      +self.mentric_events
      +self.event_names()
      -time_constraint()
    }

    class DatabaseMetric{
      +self.metric_operation
      +self.metric_relation
      +self.metric_start
      +self.metric_finish
      +self.column

      +self.relation(&block)
      +self.start(&block)
      +self.finish(&block)
      +self.operation(symbol, column: nil)
      -time_constraint()
    }

    class GenericMetric{
      +self.metric_value

      +self.value(&block)
    }
    
    class KeyPathProcessor{
      +process(key_path, value)
    }
    class UsageDataMetrics{
      +uncached_data()
    }
            

Documentation

Issue to add docs

Does this MR meet the acceptance criteria?

Conformity

Availability and Testing

Security

If this MR contains changes to processing or storing of credentials or tokens, authorization and authentication methods and other items described in the security review guidelines:

  • [-] Label as security and @ mention @gitlab-com/gl-security/appsec
  • [-] The MR includes necessary changes to maintain consistency between UI, API, email, or other methods
  • [-] Security reports checked/validated by a reviewer from the AppSec team

Related to #299448 (closed)

Edited by Alina Mihaila

Merge request reports