Service Ping 개발 지침

Service Ping은 GitLab 프로세스로, 매주 GitLab에 payload를 수집하고 전송합니다. 이 payload는 GitLab 사용 방법을 이해하는 데 도움이 되는 중요한 상위 수준의 데이터를 제공합니다. 이 데이터는 다음을 돕습니다.

  • 매달(또는 매주) 카운트를 비교하여 인스턴스가 다른 제품 기능을 어떻게 사용하는지 대략적으로 파악합니다.
  • GitLab 설치를 분류하고 이해하는 데 도움이 되는 다른 사실을 수집합니다.
  • 우리 stage 월간 활성 사용자(MAU)를 계산하여 우리 stage와 기능의 성공을 측정하는 데 도움이 됩니다.

Service Ping 정보는 익명이 아닙니다. 인스턴스의 호스트 이름에 연결되지만 프로젝트 이름, 사용자 이름 또는 기타 특정 데이터를 포함하지 않습니다.

Service Ping은 기본적으로 활성화되어 있습니다. 그러나 Self-Managed 인스턴스에서 특정 지표를 비활성화할 수 있습니다. Service Ping이 활성화되어 있으면, GitLab은 다른 인스턴스에서 데이터를 수집하고 해당 인스턴스의 사용 통계를 사용자에게 표시할 수 있습니다.

Service Ping 용어

다음 용어를 사용하여 Service Ping 구성 요소를 설명합니다.

  • Service Ping: JSON payload를 수집하고 생성하는 프로세스입니다.
  • Service Data: Service Ping JSON payload의 내용입니다. 여기에는 메트릭이 포함됩니다.
  • Metrics: 주로 인스턴스 데이터베이스의 다른 테이블에 대한 행 카운트로 이루어집니다. 각 메트릭에는 해당하는 메트릭 정의(YAML 파일)가 있습니다.
  • MAU: 월간 활성 사용자(Monthly Active Users)
  • WAU: 주간 활성 사용자(Weekly Active Users)

제한

  • Service Ping은 개별 이벤트가 아니라 메트릭만 전달합니다.
  • 버전의 Service Ping에 전달되는 메트릭은 코드베이스에서 해당 메트릭이 존재하고 계측되어야만 합니다.

Service Ping 요청 흐름

다음 예제는 GitLab 인스턴스, Versions 애플리케이션, 라이센스 애플리케이션, Salesforce, GitLab S3 버킷, GitLab Snowflake 데이터 웨어하우스, 그리고 Tableau 간의 기본 요청/응답 흐름을 보여줍니다.

sequenceDiagram participant GitLab Instance participant Versions Application participant Licenses Application participant Salesforce participant S3 Bucket participant Snowflake DW participant Tableau Dashboards GitLab Instance->>Versions Application: Service Ping 전송 loop 사용 데이터 처리 Versions Application->>Versions Application: 사용 데이터 구문 분석 Versions Application->>Versions Application: 데이터베이스에 기록 Versions Application->>Versions Application: 라이센스 ping 시간 업데이트 end loop Salesforce 데이터 처리 Versions Application-xLicenses Application: Zuora 구독 ID 요청 Licenses Application-xVersions Application: Zuora 구독 ID Versions Application-xSalesforce: Zuora 구독 ID로부터 Zuora 계정 ID 요청 Salesforce-xVersions Application: Zuora 계정 ID Versions Application-xSalesforce: Zuora 계정의 사용 데이터 end Versions Application->>S3 Bucket: Versions 데이터베이스 내보내기 S3 Bucket->>Snowflake DW: 데이터 가져오기 Snowflake DW->>Snowflake DW: dbt를 사용하여 데이터 변환 Snowflake DW->>Tableau Dashboards: 쿼리를 위한 데이터 사용 가능 Versions Application->>GitLab Instance: DevOps 점수 (대화형 개발 지수)

Service Ping 작동 방식

  1. Service Ping 크론 작업은 Sidekiq에 매주 실행되도록 설정됩니다.
  2. 크론 작업이 실행되면, Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)을 호출합니다.
  3. Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)는 ~400여개의 다른 카운터 메서드 호출로 cascades down됩니다.
  4. 모든 메서드 호출의 응답은 하나의 JSON payload로 병합됩니다.
  5. 그런 다음, JSON payload는 Version 애플리케이션에 게시됩니다. 방화벽 예외가 필요한 경우 필요한 URL은 여러 가지에 따라 달라집니다. 호스트 이름이 version.gitlab.com이고 프로토콜이 TCP이며 포트 번호가 443인 경우 필요한 URL은 https://version.gitlab.com/입니다.
  6. 오류 발생 시, 다음 정보와 함께 Version 애플리케이션에보고됩니다.

    • uuid - GitLab 인스턴스 고유 식별자
    • hostname - GitLab 인스턴스 호스트 이름
    • version - GitLab 인스턴스 현재 버전
    • elapsed - Service Ping 보고 프로세스 시작부터 오류 발생까지 경과한 시간
    • message - 오류 메시지
    
    {
      "uuid"=>"02333324-1cd7-4c3b-a45b-a4993f05fb1d",
      "hostname"=>"127.0.0.1",
      "version"=>"14.7.0-pre",
      "elapsed"=>0.006946,
      "message"=>'PG::UndefinedColumn: ERROR:  column \"non_existent_attribute\" does not exist\nLINE 1: SELECT COUNT(non_existent_attribute) FROM \"issues\" /*applica...'
    }
    
    
  7. 마지막으로, 진단 목적으로 사용되는 타이밍 메타데이터 정보가 Versions 애플리케이션에 제출됩니다. 이는 메트릭 식별자 목록과 메트릭 계산 시간으로 구성됩니다.

    {
      "metadata"=>
      {
        "uuid"=>"0000000-0000-0000-0000-000000000000",
        "metrics"=>
        [{"name"=>"version", "time_elapsed"=>1.1811964213848114e-05},
         {"name"=>"installation_type", "time_elapsed"=>0.00017242692410945892},
         {"name"=>"license_billable_users", "time_elapsed"=>0.009520471096038818},
         ....
         {"name"=>"counts.clusters_platforms_eks",
          "time_elapsed"=>0.05638605775311589},
         {"name"=>"counts.clusters_platforms_gke",
          "time_elapsed"=>0.40995341585949063},
         {"name"=>"counts.clusters_platforms_user",
          "time_elapsed"=>0.06410990096628666},
         {"name"=>"counts.clusters_management_project",
          "time_elapsed"=>0.24020783510059118}
        ]
      }
    }

Geo 보조 사이트에서

또한 Geo 보조 사이트에 특화된 메트릭스를 수집하여 서비스 핑과 함께 전송합니다.

  1. Geo 보조 서비스 핑 cron 작업은 Sidekiq에 매주 실행되도록 설정되어 있습니다.
  2. cron 작업이 실행되면 SecondaryUsageData.update_metrics!을 호출합니다. 이는 Prometheus에서 관련 메트릭을 수집하고 데이터를 보조 추적 데이터베이스에 저장하여 Geo 노드 상태 업데이트 중에 주 사이트로 전송합니다.
  3. Geo 노드 상태 데이터는 위에서 설명한 프로세스에서 JSON 페이로드와 함께 전송됩니다. 아래는 배열 내 각 객체가 Geo 노드를 나타내는 페이로드의 예시입니다:

    [
      {
        "git_fetch_event_count_weekly"=>nil,
        "git_push_event_count_weekly"=>nil,
        ... 기타 geo 노드 상태 필드
      }
    ]
    

서비스 핑 페이로드 예시

다음은 서비스 핑 페이로드의 예시 내용입니다.

{
  "uuid": "0000000-0000-0000-0000-000000000000",
  "hostname": "example.com",
  "version": "12.10.0-pre",
  "installation_type": "omnibus-gitlab",
  "active_user_count": 999,
  "recorded_at": "2020-04-17T07:43:54.162+00:00",
  "edition": "EEU",
  "license_md5": "00000000000000000000000000000000",
  "license_sha256": "0000000000000000000000000000000000000000000000000000000000000000",
  "license_id": null,
  "historical_max_users": 999,
  "licensee": {
    "Name": "ABC, Inc.",
    "Email": "email@example.com",
    "Company": "ABC, Inc."
  },
  "license_user_count": 999,
  "license_starts_at": "2020-01-01",
  "license_expires_at": "2021-01-01",
  "license_plan": "ultimate",
  "license_add_ons": {
  },
  "license_trial": false,
  "counts": {
    "assignee_lists": 999,
    "boards": 999,
    "ci_builds": 999,
    ...
  },
  "container_registry_enabled": true,
  "dependency_proxy_enabled": false,
  "gitlab_shared_runners_enabled": true,
  "gravatar_enabled": true,
  "influxdb_metrics_enabled": true,
  "ldap_enabled": false,
  "mattermost_enabled": false,
  "omniauth_enabled": true,
  "prometheus_enabled": false,
  "prometheus_metrics_enabled": false,
  "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com",
  "signup_enabled": true,
  "projects_with_expiration_policy_disabled": 999,
  "projects_with_expiration_policy_enabled": 999,
  ...
  "elasticsearch_enabled": true,
  "license_trial_ends_on": null,
  "geo_enabled": false,
  "git": {
    "version": {
      "major": 2,
      "minor": 26,
      "patch": 1
    }
  },
  "gitaly": {
    "version": "12.10.0-rc1-93-g40980d40",
    "servers": 56,
    "clusters": 14,
    "filesystems": [
      "EXT_2_3_4"
    ]
  },
  "gitlab_pages": {
    "enabled": true,
    "version": "1.17.0"
  },
  "container_registry_server": {
    "vendor": "gitlab",
    "version": "2.9.1-gitlab",
    "db_enabled": false
  },
  "database": {
    "adapter": "postgresql",
    "version": "9.6.15",
    "pg_system_id": 6842684531675334351,
    "flavor": "Cloud SQL for PostgreSQL"
  },
  "analytics_unique_visits": {
    "g_analytics_contribution": 999,
    ...
  },
  "usage_activity_by_stage": {
    "configure": {
      "project_clusters_enabled": 999,
      ...
    },
    "create": {
      "merge_requests": 999,
      ...
    },
    "manage": {
      "events": 999,
      ...
    },
    "monitor": {
      "clusters": 999,
      ...
    },
    "package": {
      "projects_with_packages": 999
    },
    "plan": {
      "issues": 999,
      ...
    },
    "release": {
      "deployments": 999,
      ...
    },
    "secure": {
      "user_container_scanning_jobs": 999,
      ...
    },
    "verify": {
      "ci_builds": 999,
      ...
    }
  },
  "usage_activity_by_stage_monthly": {
    "configure": {
      "project_clusters_enabled": 999,
      ...
    },
    "create": {
      "merge_requests": 999,
      ...
    },
    "manage": {
      "events": 999,
      ...
    },
    "monitor": {
      "clusters": 999,
      ...
    },
    "package": {
      "projects_with_packages": 999
    },
    "plan": {
      "issues": 999,
      ...
    },
    "release": {
      "deployments": 999,
      ...
    },
    "secure": {
      "user_container_scanning_jobs": 999,
      ...
    },
    "verify": {
      "ci_builds": 999,
      ...
    }
  },
  "topology": {
    "duration_s": 0.013836685999194742,
    "application_requests_per_hour": 4224,
    "query_apdex_weekly_average": 0.996,
    "failures": [],
    "nodes": [
      {
        "node_memory_total_bytes": 33269903360,
        "node_memory_utilization": 0.35,
        "node_cpus": 16,
        "node_cpu_utilization": 0.2,
        "node_uname_info": {
          "machine": "x86_64",
          "sysname": "Linux",
          "release": "4.19.76-linuxkit"
        },
        "node_services": [
          {
            "name": "web",
            "process_count": 16,
            "process_memory_pss": 233349888,
            "process_memory_rss": 788220927,
            "process_memory_uss": 195295487,
            "server": "puma"
          },
          {
            "name": "sidekiq",
            "process_count": 1,
            "process_memory_pss": 734080000,
            "process_memory_rss": 750051328,
            "process_memory_uss": 731533312
          },
          ...
        ],
        ...
      },
      ...
    ]
  }
}

Service Ping 데이터 내보내기

다양한 형식으로 Service Ping 데이터를 내보내기 위한 Rake 작업이 있습니다.

  • Rake 작업은 count, distinct_count, sum에 대한 원시 SQL 쿼리를 내보냅니다.
  • Rake 작업은 redis_usage_data에 대한 Redis 카운터 클래스 또는 Redis 블록의 라인을 내보냅니다.
  • Rake 작업은 alt_usage_data 메트릭을 계산합니다.

로컬 GitLab 설치 디렉토리에서 다음과 같은 Rake 작업을 실행하여 YAML 또는 JSON 버전 중 하나를 내보냅니다.

# SQL 쿼리의 YAML 내보내기
bin/rake gitlab:usage_data:dump_sql_in_yaml

# SQL 쿼리의 JSON 내보내기
bin/rake gitlab:usage_data:dump_sql_in_json

# SQL이 아닌 데이터의 JSON 내보내기
bin/rake gitlab:usage_data:dump_non_sql_in_json

# 출력을 파일로 보낼 수 있습니다
bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml

Service Ping에 대한 백업 값

다음의 경우에는 백업 값을 반환합니다:

경우
Deprecated Metric (버전 14.3에서 제거) -1000
시간 초과, 일반적인 실패 -1
카운터의 표준 오류 -2
히스토그램 메트릭 실패 { ‘-1’ => -1 }

모니터링

Service Ping 보고 프로세스 상태는 Tableau 대시보드로 모니터링됩니다.

관련 주제