메트릭 인스트루먼테이션 가이드

이 안내서는 메트릭 인스트루먼테이션을 사용하여 서비스 핑 메트릭을 개발하는 방법에 대해 설명합니다.

비디오 자습서는 인스트루먼테이션 클래스를 통한 서비스 핑 메트릭 추가를 참조하십시오.

용어

  • 인스트루먼테이션 클래스:
    • DatabaseMetric, NumbersMetric 또는 GenericMetric 중 하나의 메트릭 클래스를 상속합니다.
    • 서비스 핑 메트릭의 값을 계산하는 논리를 구현합니다.
  • 메트릭 정의: 서비스 데이터 메트릭 YAML 정의입니다.

  • 하드닝: 메소드의 하드닝은 메소드가 안전하게 실패하고 -1과 같은 대체 값을 반환하도록 하는 프로세스입니다.

작동 방식

메트릭 정의에는 instrumentation_class 필드가 있습니다. 이 필드는 클래스로 설정할 수 있습니다.

정의된 인스트루먼테이션 클래스는 기존의 메트릭 클래스 중 하나를 상속해야 합니다: DatabaseMetric, NumbersMetric 또는 GenericMetric.

인스트루먼테이션 클래스를 사용하면 서비스 핑 생성 전체 과정을 손상시키지 않고 메트릭이 개별적으로 안전하게 실패할 수 있습니다.

데이터베이스 메트릭

note
가능하면 데이터베이스 메트릭 대신 내부 이벤트 추적을 사용하는 것이 좋습니다. 데이터베이스 메트릭은 큰 GitLab 인스턴스의 데이터베이스에 불필요한 부하를 일으킬 수 있으며 잠재적인 최적화가 인스턴스 성능에 영향을 미칠 수 있습니다.

데이터베이스 메트릭은 데이터베이스에 저장된 데이터를 추적하는 데 사용할 수 있습니다. 예를 들어, 특정 인스턴스에 존재하는 이슈의 수를 카운트할 수 있습니다.

  • operation: 지정된 relation에 대한 작업 중 하나인 count, distinct_count, sum, average 중 하나입니다.
  • relation: 우리가 operation을 수행하려는 객체에 대한 ActiveRecord::Relation을 반환하는 람다를 할당합니다. 할당된 람다는 최대 하나의 매개변수를 받을 수 있습니다. 매개변수는 메트릭 정의의 options 키 아래에 해시 처리되어 저장됩니다.
  • start: 일괄 카운팅의 시작 값을 지정합니다. 기본값은 relation.minimum(:id)입니다.
  • finish: 일괄 카운팅의 종료 값을 지정합니다. 기본값은 relation.maximum(:id)입니다.
  • cache_start_and_finish_as: startfinish 값을 캐시하는 데 사용할 캐시 키를 지정하고 그 값을 설정합니다. startfinish가 다양한 메트릭 계산 간에 재사용되어야 하는 비용이 많이 드는 쿼리인 경우에는 이 호출을 사용하세요.
  • available?: 메트릭이 보고되어야 하는지 여부를 지정합니다. 기본값은 true입니다.
  • timestamp_column: 선택적으로 메트릭에 사용되는 타임스탬프 열을 지정합니다. 기본값은 created_at입니다.

데이터베이스 메트릭을 추가하는 Merge Request의 예시.

최적화 권고 및 예시

서비스 핑 메트릭에 대한 단일 쿼리는 콜드 캐시를 사용하여 1초 미만의 실행 시간을 유지해야 합니다.

  • 전문화된 인덱스를 사용하세요. 예시는 다음 Merge Request을 참조하세요:
  • 지정된 startfinish를 사용하세요. 이러한 값은 다음과 같이 메모이즈되어 재사용될 수 있습니다. 예시 Merge Request을 참조하세요.
  • 쿼리에서 조인 및 불필요한 복잡성을 피하세요. 다음과 같은 예시 Merge Request을 참조하세요.
  • distinct_count에 대해 batch_size를 사용자 정의하세요. 다음과 같은 예시 Merge Request을 참조하세요.

데이터베이스 메트릭 예시

카운트 예시

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountIssuesMetric < DatabaseMetric
          operation :count
          
          relation ->(options) { Issue.where(confidential: options[:confidential]) }
        end
      end
    end
  end
end

일괄 카운터 예시

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

서로 다른 일괄 카운터 예시

# 동결된 문자열 리터럴: true

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountUsersAssociatingMilestonesToReleasesMetric < DatabaseMetric
          operation :distinct_count, column: :author_id
          
          relation { Release.with_milestones }
          
          start { Release.minimum(:author_id) }
          finish { Release.maximum(:author_id) }
        end
      end
    end
  end
end

합 예시

# 동결된 문자열 리터럴: true

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class JiraImportsTotalImportedIssuesCountMetric < DatabaseMetric
          operation :sum, column: :imported_issues_count
          
          relation { JiraImportState.finished }
        end
      end
    end
  end
end

평균 예시

# 동결된 문자열 리터럴: true

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class CountIssuesWeightAverageMetric < DatabaseMetric
          operation :average, column: :weight
          
          relation { Issue }
        end
      end
    end
  end
end

예상 일괄 카운터

예상 일괄 카운터 기능은 제공된 estimate_batch_distinct_count 메소드를 통해 ActiveRecord::StatementInvalid 오류를 처리합니다. 오류는 -1의 값으로 반환됩니다.

caution
이 기능은 확률적인 하이퍼로그로그(HyperLogLog) 알고리즘을 사용하는 특정 ActiveRecord_Relation의 고유 카운트를 추정합니다. 하이퍼로그로그 알고리즘은 항상 오류를 포함하며, 가장 높게 발견된 오류율은 4.9%입니다.

올바르게 사용할 때 estimate_batch_distinct_count 메소드는 다른 카운터들로는 보장할 수 없는 중복되지 않는 값을 포함하는 열을 효율적으로 카운트할 수 있게 합니다.

estimate_batch_distinct_count 메서드

메서드:

estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)

메서드에는 다음과 같은 매개변수가 포함되어 있습니다:

  • relation: 카운트를 수행할 ActiveRecord_Relation입니다.
  • column: 고유 카운트를 수행할 열입니다. 기본값은 기본 키입니다.
  • batch_size: Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE에서 가져온 값. 기본값: 10,000.
  • start: 복잡한 최소 계산을 피하기 위해 배치 카운트의 사용자 정의 시작점입니다.
  • finish: 복잡한 최대 계산을 피하기 위해 배치 카운트의 사용자 정의 끝점입니다.

메서드에는 다음과 같은 전제 조건이 포함되어 있습니다:

  • 제공된 relation은 숫자 열로 정의된 기본 키를 포함해야 합니다. 예: id bigint NOT NULL.
  • estimate_batch_distinct_count는 조인된 relation을 처리할 수 있습니다. 고유하지 않은 열을 계산하는 능력을 사용하려면 조인된 relation에 has_many :boards와 같은 일대다 관계가 없어야 합니다.
  • startfinish 매개변수는 항상 다른 열을 참조하는 경우에도 기본 키 관계 값을 나타내어야 합니다. 예를들어:

      estimate_batch_distinct_count(::Note, :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id))
    

예시:

  1. 간단한 예상 배치 카운터 실행, 관계만 제공된 경우, 반환된 값은 Project 관계의 id(기본 키) 열에서 추정된 고유 값의 수를 나타냅니다:

      estimate_batch_distinct_count(::Project)
    
  2. 제공된 관계에 추가 필터(.where(time_period))가 적용된 예상 배치 카운터 실행, 고유 값의 수는 사용자 지정 열(:author_id)에서 추정되고, startfinish 매개변수는 함께 제공된 관계의 범위를 정의하는 경계를 적용합니다:

      estimate_batch_distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id))
    

집계된 메트릭

제품 인텔리전스 오피스 시간 10월 6일에서 집계된 메트릭 사용 방법을 확인하세요.

집계된 메트릭 기능은 이벤트 모음에서 발생한 데이터 속성 수에 대한 통찰을 제공합니다. 예를들어, 새 이슈를 작성하고 새로운 Merge Request을 여는 등 여러 작업을 수행하는 사용자 수를 집계할 수 있습니다.

집계된 메트릭을 정의하는 데 YAML 파일을 사용할 수 있습니다. 다음과 같은 매개변수가 필요합니다:

  • options.events: 메트릭 데이터에 통합할 이벤트 이름 디렉터리입니다. 이 디렉터리의 모든 이벤트는 동일한 데이터 소스를 사용해야 합니다. 추가 데이터 소스 요구 사항에 대해서는 아래 링크들을 참조하세요: 데이터베이스 소스 집계된 메트릭이벤트 소스 집계된 메트릭.
  • options.aggregate.attribute: 이벤트 간에 집계되는 속성을 가리키는 정보입니다.
  • time_frame: 하나 이상의 유효한 시간 범위입니다. 집계된 메트릭에 포함할 데이터를 특정 날짜 범위 내의 이벤트로 제한하는 데 사용합니다. 유효한 시간 범위는 다음과 같습니다:
    • 7일: 최근 7일간의 데이터.
    • 28일: 최근 28일간의 데이터.
    • 전체: 데이터베이스 소스 집계된 메트릭의 경우에만 사용할 수 있는 모든 이력 데이터.
  • data_source: 집계된 메트릭에 포함된 모든 이벤트 데이터를 수집하는 데 사용되는 데이터 소스입니다. 유효한 데이터 소스는 다음과 같습니다:

AggregatedMetric 메트릭을 추가하는 Merge Request에 대한 예시는 98206를 참조하세요.

적어도 하나의 이벤트(incident_management_alert_status_changed, incident_management_alert_assigned, incident_management_alert_todo, incident_management_alert_create_incident)에서 발생한 고유한 user.id를 카운트합니다.

time_frame: 28d
instrumentation_class: AggregatedMetric
data_source: internal_events
options:
    aggregate:
        attribute: user.id
    events:
        - `incident_management_alert_status_changed`
        - `incident_management_alert_assigned`
        - `incident_management_alert_todo`
        - `incident_management_alert_create_incident`

이벤트 소스 집계된 메트릭

내부 이벤트를 수집하여 이벤트의 집합을 선언하려면 time_frameall 값이 포함되지 않도록 하십시오. 이는 Redis 소스 집계된 메트릭에는 사용할 수 없는 값입니다.

EE 전용 이벤트를 모든 GitLab 에디션에서 발생하는 이벤트와 함께 집계하는 것이 가능하지만, 이렇게 할 경우 EE 및 CE GitLab 인스턴스에서 수집된 데이터 간에 높은 분산이 발생할 수 있다는 점을 기억하는 것이 중요합니다.

데이터베이스 소스 집계된 메트릭

데이터베이스에서 수집된 이벤트를 기반으로 메트릭을 집계하려면 다음 단계를 따르세요:

  1. 집계를 위해 메트릭 유지.
  2. 새로운 집계된 메트릭 정의 추가.

집계를 위해 메트릭 유지

집계된 메트릭을 위해 추정된 배치 카운터로 계산된 메트릭만 유지할 수 있습니다. 메트릭을 유지하려면 estimate_batch_distinct_count 메서드에 루비 블록을 삽입하면 됩니다. 이 블록은 Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll.save_aggregated_metrics method 를 호출해야 합니다. 이 메서드는 estimate_batch_distinct_count 결과를 집계된 메트릭에서 사용할 수 있도록 저장합니다.

Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll.save_aggregated_metrics 메서드는 다음과 같은 매개변수를 허용합니다:

  • metric_name: 집계에 사용할 메트릭의 이름. 서비스 핑에 메트릭이 추가된 키와 동일해야 합니다.
  • recorded_at_timestamp: 주어진 서비스 핑 페이로드가 수집된 시점을 나타내는 타임스탬프. recorded_at과 같은 편리한 메서드를 사용하여 recorded_at_timestamp 인수를 채우세요.
  • time_period: estimate_batch_distinct_count에 전달된 relation을 구축하는 데 사용되는 시간 범위입니다. 모든 이용 가능한 이력 데이터로 메트릭을 수집하려면 시간 범위에 nil 값으로 설정하세요.
  • data: relation의 고유한 항목을 나타내는 HyperLogLog 버킷 구조입니다. estimate_batch_distinct_count 메서드는 항상 올바른 인수를 블록으로 전달하므로 data 인수는 항상 블록 인수와 동일한 값을 가져야 합니다. 예를들어 다음과 같이 사용하세요: data: result

메트릭 유지 예시:

class UsageData
  def count_secure_pipelines(time_period)
    ...
    relation = ::Security::Scan.by_scan_types(scan_type).where(time_period)
    
    pipelines_with_secure_jobs['dependency_scanning_pipeline'] = estimate_batch_distinct_count(relation, :pipeline_id, batch_size: 1000, start: start_id, finish: finish_id) do |result|
      ::Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll
        .save_aggregated_metrics(metric_name: 'dependency_scanning_pipeline', recorded_at_timestamp: recorded_at, time_period: time_period, data: result)
    end
  end
end

집계 메트릭 정의 추가

모든 메트릭이 지속될 때 집계 메트릭 정의를 추가할 수 있습니다. 추정 배치 카운터로 수집된 메트릭을 집계하려면 다음 요구 사항을 충족해야 합니다.

  • events: 속성에 나열된 메트릭 이름은 이전 단계에서 메트릭을 지속하는 동안 전달한 metric_name 인수와 동일한 이름을 사용해야 합니다.
  • events: 속성에 나열된 모든 메트릭은 선택한 time_frame: 값에 대해 모든로 지속해야 합니다.

가용성 제한된 집계 메트릭

집계 메트릭을 보고서에서 특정 조건에 따라 사용할 수 있도록 하려면 새로운 클래스에서 AggregatedMetric 클래스의 하위인 클래스에서 이러한 조건을 지정해야 합니다.

# frozen_string_literal: true

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class MergeUsageCountAggregatedMetric < AggregatedMetric
          available? { Feature.enabled?(:merge_usage_data_missing_key_paths) }
        end
      end
    end
  end
end

또한 YAML 설정에서 클래스의 이름을 사용해야 합니다.

time_frame: 28d
instrumentation_class: MergeUsageCountAggregatedMetric
data_source: redis_hll
options:
    aggregate:
        attribute: user.id
    events:
        - `incident_management_alert_status_changed`
        - `incident_management_alert_assigned`
        - `incident_management_alert_todo`
        - `incident_management_alert_create_incident`

숫자 메트릭

  • operation: 주어진 data 블록의 작업입니다. 현재는 add 작업만 지원합니다.
  • data: 숫자 배열을 포함하는 block입니다.
  • available?: 메트릭을 보고해야 하는지 여부를 지정합니다. 기본값은 true입니다.
# frozen_string_literal: true

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
          class IssuesBoardsCountMetric < NumbersMetric
            operation :add
            
            data do |time_frame|
              [
                 CountIssuesMetric.new(time_frame: time_frame).value,
                 CountBoardsMetric.new(time_frame: time_frame).value
              ]
            end
          end
        end
      end
    end
  end
end

또한 YAML 설정에서 집계 클래스의 이름을 포함해야 합니다.

time_frame: 28d
instrumentation_class: IssuesBoardsCountMetric

일반 메트릭

기타 메트릭을 다음과 같이 사용할 수 있습니다. 예를 들어 인스턴스의 데이터베이스 버전입니다.

  • value: 메트릭의 값을 지정합니다.
  • available?: 메트릭을 보고해야 하는지 여부를 지정합니다. 기본값은 true입니다.

일반 메트릭을 추가하는 merge request의 예시.

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class UuidMetric < GenericMetric
          value do
            Gitlab::CurrentSettings.uuid
          end
        end
      end
    end
  end
end

Prometheus 메트릭

이 기기 클래스를 사용하여 value 블록에 프로메테우스 클라이언트 객체를 전달하여 프로메테우스 쿼리를 처리할 수 있습니다. 프로메테우스 오류 처리는 블록 자체에서 수행해야 합니다.

  • value: 메트릭의 값을 지정합니다. 프로메테우스 클라이언트 객체를 첫 번째 인수로 전달합니다.
  • available?: 메트릭을 보고해야 하는지 여부를 지정합니다. 기본값은 true입니다.

프로메테우스 메트릭을 추가하는 merge request의 예시.

module Gitlab
  module Usage
    module Metrics
      module Instrumentations
        class GitalyApdexMetric < PrometheusMetric
          value do |client|
            result = client.query('avg_over_time(gitlab_usage_ping:gitaly_apdex:ratio_avg_over_time_5m[1w])').first
            
            break FALLBACK unless result
            
            result['value'].last.to_f
          end
        end
      end
    end
  end
end

새로운 메트릭 기기 클래스 생성

제너레이터는 클래스 이름과 다음 옵션을 인수로 받습니다.

  • --type=TYPE 필수 항목입니다. 메트릭 유형을 나타냅니다. database, generic, redis, numbers 중 하나여야 합니다.
  • --operation databasenumbers 유형의 경우 필수입니다.
    • database의 경우 count, distinct_count, estimate_batch_distinct_count, sum, average 중 하나여야 합니다.
    • numbers의 경우 add여야 합니다.
  • --ee 메트릭이 EE용인지를 나타냅니다.
rails generate gitlab:usage_metric CountIssues --type database --operation distinct_count
        create lib/gitlab/usage/metrics/instrumentations/count_issues_metric.rb
        create spec/lib/gitlab/usage/metrics/instrumentations/count_issues_metric_spec.rb

서비스 핑 메트릭을 기기 클래스로 마이그레이션

이 안내서에서는 서비스 핑 메트릭을 lib/gitlab/usage_data.rb 또는 ee/lib/ee/gitlab/usage_data.rb에서 기기 클래스로 마이그레이션하는 방법을 설명합니다.

  1. 메트릭 유형 선택:
  1. 기기 클래스 위치 결정: ee 내부 또는 ee 외부.

  2. 기기 클래스 파일 생성.

  3. 기기 클래스 본문 작성:

    • 메트릭에 대한 코드 논리 추가. 이는 usage_data.rb에서 메트릭 구현과 유사할 수 있습니다.
    • 개별 메트릭에 대한 테스트 추가 spec/lib/gitlab/usage/metrics/instrumentations/.
    • Service Ping에 대한 테스트 추가.
  4. 메트릭 정의 파일 생성.

  5. lib/gitlab/usage_data.rb 또는 ee/lib/ee/gitlab/usage_data.rb에서 코드 제거.

  6. spec/lib/gitlab/usage_data.rb 또는 ee/spec/lib/ee/gitlab/usage_data.rb에서 테스트 제거.

메트릭 문제 해결

때로는 메트릭이 즉시 명확하지 않은 이유로 실패할 수 있습니다. 이러한 실패는 성능 문제 또는 다른 문제와 관련될 수 있습니다.

다음 페어링 세션 비디오는 실제로 실패한 메트릭 조사의 예시를 제공합니다.

다음 비디오를 시청하여 메트릭 문제 해결 과정에 대해 더 알아보세요: Product Intelligence Office Hours Oct 27th