Service Ping 开发指南
Service Ping 是一个 GitLab 进程,用于收集并发送每周的数据包给 GitLab。 该数据包提供了重要的高层级数据,帮助我们的产品、支持和销售团队了解 GitLab 的使用情况。这些数据有助于:
- 按月(或周)对比计数,大致了解实例如何使用不同的产品功能。
- 收集其他事实,帮助我们分类和理解 GitLab 安装。
- 计算我们各阶段的月活跃用户数(SMAU),这有助于衡量我们各阶段和功能的成功度。
Service Ping 信息不是匿名的。它与实例的主机名相关联,但不包含项目名称、用户名或任何其他特定数据。
Service Ping 默认启用。但是,您可以在任何 GitLab 自托管实例上禁用某些指标。当 Service Ping 启用时,GitLab 会收集来自其他实例的数据,并向您的用户显示您实例的使用统计信息。
Service Ping 术语
我们使用以下术语来描述 Service Ping 组件:
- Service Ping:收集并生成 JSON 数据包的进程。
- Service Data:Service Ping JSON 数据包的内容。这包括指标。
- Metrics:主要由实例数据库中不同表的行数组成。每个指标在 YAML 文件中都有相应的指标定义。
- MAU:月活跃用户。
- WAU:周活跃用户。
已知问题
- Service Ping 只传递指标,不传递单个事件。
- 指标必须在代码库中存在并已实现,才能在相应版本的 Service Pings 中传递该版本的 GitLab。
Service Ping 请求流程
以下示例展示了 GitLab 实例、版本应用、许可应用、Salesforce、GitLab GCP 存储桶、GitLab Snowflake 数据仓库和 Tableau 之间的基本请求/响应流程:
sequenceDiagram
participant GitLab Instance
participant Versions Application
participant Licenses Application
participant Salesforce
participant GCP Bucket
participant Snowflake DW
participant Tableau 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->>GCP Bucket: Export Versions database
GCP Bucket->>Snowflake DW: Import data
Snowflake DW->>Snowflake DW: Transform data using dbt
Snowflake DW->>Tableau Dashboards: Data available for querying
Versions Application->>GitLab Instance: DevOps Score (Conversational Development Index)
Service Ping 工作原理
-
Service Ping 的 cron job 在 Sidekiq 中设置为每周运行。
-
当 cron job 运行时,它会调用
Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)。 -
Gitlab::Usage::ServicePingReport.for(output: :all_metrics_values)向下级联到约 400+ 个其他计数器方法调用。 -
所有方法调用的响应被合并在一起成一个 JSON 数据包。
-
然后 JSON 数据包被发布到版本应用 如果需要防火墙例外,所需的 URL 取决于几个因素。如果主机名是
version.gitlab.com,协议是TCP,端口号是443,则所需的 URL 是 https://version.gitlab.com/。 -
如果发生错误,它将与以下信息一起报告给版本应用:
-
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...' }
-
-
最后,用于诊断目的的时序元数据信息被提交到版本应用。它由指标标识符列表和计算这些指标所需的时间组成:
{
"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 从站点相关的特定指标,通过 Service Ping 发送。
-
Geo 从站点 service ping cron job 在 Sidekiq 中设置为每周运行。
-
当 cron job 运行时,它会调用
SecondaryUsageData.update_metrics!。这会从 Prometheus 收集相关指标,并将数据存储在 Geo 从站点跟踪数据库中,以便在 Geo 节点状态更新期间传输到主站点。 -
Geo 节点状态数据与上述过程中的 JSON 数据包一起发送。以下是数据包示例,其中数组中的每个对象代表一个 Geo 节点:
[ { "git_fetch_event_count_weekly"=>nil, "git_push_event_count_weekly"=>nil, ... other geo node status fields } ]
Service Ping 数据包示例
以下是 Service 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 protected]",
"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 数据
存在 Rake 任务以不同格式导出 Service Ping 数据。
- Rake 任务导出
count、distinct_count、sum的原始 SQL 查询。 - Rake 任务导出
redis_usage_data的 Redis 计数器类或 Redis 块的行。 - Rake 任务计算
alt_usage_data指标。
在本地 GitLab 安装的主目录中,运行以下 Rake 任务以获取 YAML 或 JSON 版本:
# 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.yamlService Ping 的回退值
在这些情况下,我们返回回退值:
| Case | Value |
|---|---|
| 已弃用的指标 (在版本 14.3 中移除) | -1000 |
| 超时、一般性错误 | -1 |
| 计数器中的标准错误 | -2 |
| 直方图指标失败 | { ‘-1’ => -1 } |
监控
Service Ping 报告进程状态通过 Tableau 仪表板 进行监控。