サービスPing開発ガイドライン

  • GitLab Ultimate 11.2で導入された、より多くの統計情報。
  • GitLab 14.1でUsage PingからService Pingに名称変更。14.0以前のバージョンでは、Usage Pingのドキュメントでバージョンに合ったRailsコマンドを使用してください。

Service PingはGitLabのプロセスで、毎週ペイロードを収集してGitLabに送信します。このペイロードは、製品、サポート、営業チームがGitLabがどのように使われているかを理解するのに役立つ重要なハイレベルデータを提供します。このデータは以下のことに役立ちます:

  • 前月比(または前週比)でカウントを比較し、インスタンスが異なる製品機能をどのように使用しているかを大まかに把握します。
  • GitLab インストールの分類と理解に役立つその他の事実を収集します。
  • ステージの月間アクティブユーザー(SMAU)を計算し、ステージや機能の成功を測定するのに役立ちます。

サービスPing情報は匿名ではありません。インスタンスのホスト名にリンクされていますが、プロジェクト名、ユーザー名、その他の特定のデータは含まれていません。

Service Pingはデフォルトで有効になっています。しかし、自分で管理するインスタンスではこれを無効にすることができます。Service Pingが有効な場合、GitLabは他のインスタンスからデータを収集し、インスタンスの使用統計をユーザーに表示することができます。

Service Pingの用語

Service Pingのコンポーネントを説明するために、以下の用語を使用します:

  • Service Ping:JSONペイロードを収集して生成するプロセス。
  • Service Data(サービス・データ):Service PingのJSONペイロードの内容。メトリクスが含まれます。
  • メトリクス:主にインスタンスのデータベース内のさまざまなテーブルの行数で構成されます。各メトリクスには、YAMLファイルに対応するメトリクス定義があります。
  • MAU: 月間アクティブユーザー。
  • WAU: 週間アクティブユーザー数。

制限事項

  • Service Pingは、ページビュー、リンククリック、ユーザーセッションなどのフロントエンドイベントを追跡しません。
  • Service Pingは、集約されたバックエンドイベントのみに焦点を当てます。

このような制限があるため、以下をお勧めします:

  • GitLab.comでより詳細な分析を行うには、Snowplowで製品をインストゥルメント化することをお勧めします。
  • Service Ping を使って、自己管理インスタンスで集約されたバックエンドイベントを追跡しましょう。

Service Pingリクエストフロー

次の例は、GitLabインスタンス、Versionsアプリケーション、ライセンスアプリケーション、Salesforce、GitLab S3バケット、GitLab Snowflakeデータウェアハウス、Sisense間の基本的なリクエスト/レスポンスフローを示しています:

sequenceDiagram participant GitLab Instance participant Versions Application participant Licenses Application participant Salesforce participant S3 Bucket participant Snowflake DW participant Sisense Dashboards GitLab Instance->>Versions Application: Send Service Ping loop Process usage data Versions Application->>Versions Application: Parse usage data Versions Application->>Versions Application: Write to database Versions Application->>Versions Application: Update license ping time end loop Process data for Salesforce Versions Application-xLicenses Application: Request Zuora subscription id Licenses Application-xVersions Application: Zuora subscription id Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id Salesforce-xVersions Application: Zuora account id Versions Application-xSalesforce: Usage data for the Zuora account end Versions Application->>S3 Bucket: Export Versions database S3 Bucket->>Snowflake DW: Import data Snowflake DW->>Snowflake DW: Transform data using dbt Snowflake DW->>Sisense Dashboards: Data available for querying Versions Application->>GitLab Instance: DevOps Score (Conversational Development Index)

Service Pingの仕組み

  1. Service PingのcronジョブはSidekiqで毎週実行されるように設定されています。
  2. cronジョブが実行されると、Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)
  3. Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values) は他の400以上のカウンターメソッド呼び出しにカスケードダウンします。
  4. すべてのメソッド呼び出しのレスポンスは、単一のJSONペイロードにマージされます。
  5. ファイアウォール例外が必要な場合、必要なURLはいくつかの事柄に依存しますホスト名がversion.gitlab.com、プロトコルがTCP、ポート番号が443の場合、必要な URL はhttps://version.gitlab.com/です。
  6. エラーが発生した場合、以下の情報とともに Version アプリケーションにレポーターされます:

    • uuid - GitLab インスタンス一意識別子
    • hostname - GitLabインスタンスのホスト名
    • version - GitLab インスタンスの現在のバージョン
    • elapsed - サービス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.../*applica...    }    
  1. 最後に、診断目的で使用されるタイミング・メタデータ情報が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 セカンダリサイトで

また、サービスPingで送信するGeoセカンダリサイト固有のメトリクスも収集しています。

  1. Geo secondary service ping cronジョブはSidekiqで毎週実行されるように設定されています。
  2. cron ジョブが実行されると、SecondaryUsageData.update_metrics!を呼び出します。これは Prometheus から関連するメトリクスを収集し、Geoノードのステータス更新時にプライマリサイトに送信するために Geo セカンダリ追跡データベースにデータを保存します。
  3. Geo ノード・ステータス・データは、前述のプロセスで JSON ペイロードと共に送信されます。以下は配列の各オブジェクトが Geo ノードを表すペイロードの例です:

    [
      {
        "repository_verification_enabled"=>true,
        "repositories_replication_enabled"=>true,
        "repositories_synced_count"=>24,
        "repositories_failed_count"=>0,
        "git_fetch_event_count_weekly"=>nil,
        "git_push_event_count_weekly"=>nil,
        ... other geo node status fields
      }
    ]
    

サービス Ping の実装

Service Pingの実装ガイドを参照してください。

サービスPingペイロードの例

以下はサービスPingペイロードの内容例です。

{
  "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"
  },
  "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
          },
          ...
        ],
        ...
      },
      ...
    ]
  }
}

注目すべき変更点

GitLab 14.6 では、flavor が追加され、内部のマネージドデータベースの種類を検出するようになりました。指定できる値は “Amazon Aurora PostgreSQL”、”PostgreSQL on Amazon RDS”、”Cloud SQL for PostgreSQL”、”Azure Database for PostgreSQL - Flexible Server”、または “null” です。

GitLab 13.5 では、PostgreSQL システム識別子を送信するためにpg_system_id が追加されました。

サービスPingデータのエクスポート

Service Pingデータを様々な形式でエクスポートするRakeタスクがあります。

  • Rake タスクはcount,distinct_count,sumの生の SQL クエリをエクスポートします。
  • Rakeタスクは、RedisカウンタークラスまたはRedisブロックの行をエクスポートします(redis_usage_data )。
  • Rakeタスクは、alt_usage_data メトリクスを計算します。

GitLab をインストールしたローカルのホームディレクトリで、YAML 版と JSON 版それぞれについて以下の Rake タスクを実行してください:

# for YAML export of SQL queries
bin/rake gitlab:usage_data:dump_sql_in_yaml

# for JSON export of SQL queries
bin/rake gitlab:usage_data:dump_sql_in_json

# for JSON export of Non SQL data
bin/rake gitlab:usage_data:dump_non_sql_in_json

# You may pipe the output into a file
bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml

サービスPingの生成

Service Pingを生成するには、テレポートまたはリモートサーバーの分離画面セッションを使用します。

トリガー

テレポートによるサービスPingのトリガー

  1. 必要な環境への一時的なアクセスを要求します。
  2. 承認者がイシューされたら、Railsコンソールにアクセスします。
  3. GitlabServicePingWorker.new.perform('triggered_from_cron' => false) を実行してください。

切り離された画面セッションでのサービス Ping のトリガー

  1. エージェント転送でbastionに接続:

    ssh -A lb-bastion.gprd.gitlab.com
    
  2. 名前付きスクリーンの作成

    screen -S <username>_usage_ping_<date>
    
  3. コンソールホストに接続します:

    ssh $USER-rails@console-01-sv-gprd.c.gitlab-production.internal
    
  4. 以下を実行する:

    GitlabServicePingWorker.new.perform('triggered_from_cron' => false)
    
  5. 画面から切り離すには、ctrl + A,ctrl + Dを押します。
  6. 籠城から退出:

    exit
    
  7. ログからメトリクス期間を取得します:

Google Console のログからtime_elapsed を検索します。クエリの例

検証(約30時間後)

テレポートで確認

  1. 以下の手順に従って、必要な環境への新規アクセスをリクエストし、Railsコンソールに接続してください
  2. raw_usage_data テーブルで最後のペイロードを確認します:RawUsageData.last.payload
  3. ペイロードがいつ送信されたかをチェックします:RawUsageData.last.sent_at

分離された画面セッションを使用して確認

  1. bastionに再接続します:

    ssh -A lb-bastion.gprd.gitlab.com
    
  2. 画面セッションを検索します:

    screen -ls
    
  3. 画面セッションに添付します:

    screen -x 14226.mwawrzyniak_usage_ping_2021_01_22
    
  4. raw_usage_data テーブルの最後のペイロードを確認してください:

    RawUsageData.last.payload
    
  5. ペイロードがいつ送信されたかをチェックします:

    RawUsageData.last.sent_at
    

データベースの書き込みオペレーションをスキップ

データベースの書き込みオペレーション、DevOpsレポートの作成、使用データペイロードの保存をスキップするには、オプションの引数を渡します:

skip_db_write:
GitlabServicePingWorker.new.perform('triggered_from_cron' => false, 'skip_db_write' => true)

モニタリング

サービスPing報告プロセスの状態は、内部SiSenseダッシュボードで監視されます。