
OneUptime Cloud Environments 详解云环境自动识别、环境键设计与 OTLP 接入实战【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime本篇基于 OneUptime 仓库的 cloud-environments.md 文档展开讲解 OneUptime 如何将 AWS ECS、Google Cloud Run、Azure Container Apps 等托管云计算工作负载自动聚合为Cloud Environment云环境环境是如何被三个资源属性唯一标识的、实例身份如何解析、哪些平台受支持以及如何把 OTLP 遥测正确导出到 OneUptime 并验证环境出现。读完后你可以独立完成一个云环境的接入并能从源码层面理解“为什么一个 ECS 任务会被拆成两行”“为什么少了 account id 会多出一个环境”这类问题。一、Cloud Environment 是什么定位与边界OneUptime 把托管云计算managed cloud compute归组为Cloud Environments。文档给出了一个清晰的定位环境既不是服务Service也不是机器Host它是容器运行的“场所”——一个 ECS 集群的账号与区域组合、一个 Cloud Run 的项目与区域、一个 Container Apps 环境——并聚合该场所下的所有工作负载。环境由遥测在带有正确资源属性的数据到达时自动创建无需手工注册。与之配套的层级关系是Services同一批工作负载仍按服务维度保留各自的拆分视图Cloud Environment汇总层roll-up其Instances标签页列出正在运行的 task / instance / replica并在平台能提供数据时展示实时 CPU / 内存。各平台的完整配置导出器设置放在云端控制台的哪个位置、是否需要 sidecar collector、IAM 与网络要求分别位于每平台一页的指南AWS ECS / FargateGoogle Cloud RunAzure Container Apps其他云平台Elastic Beanstalk、App Runner、App Engine、App Service、Container Instances云环境排障二、前置条件接入前需要两样东西OneUptime Telemetry Ingestion Token在Project Settings → Telemetry APM → Ingestion Keys中创建一个Server类型的 key复制其x-oneuptime-token值。它是一个密钥各平台页面会说明在对应云端的 secret storeSecrets Manager、Secret Manager、Container Apps secrets 等中存放它应用内嵌一个OpenTelemetry SDK或与它并行运行的一个OpenTelemetry Collector以 OTLP 协议导出数据。三、OneUptime 如何识别一个环境一个环境对应三个资源属性的唯一组合属性是否必需作用cloud.platform必需必须是下表中受管平台的取值之一——aws_ecs、gcp_cloud_run、azure_container_apps等cloud.account.id否AWS 账号 id、Google Cloud 项目 id 或 Azure 订阅 id参与环境键cloud.region否us-east-1、us-central1、eastus等参与环境键三者用|拼接成environment key环境键即该环境数据库记录中的 Resource Identifieraws_ecs|123456789012|us-east-1 gcp_cloud_run|my-project|us-central1 azure_container_apps|00000000-0000-0000-0000-000000000000|eastus缺失的段保留为空段而不是丢弃——aws_ecs||us-east-1与aws_ecs|123456789012|us-east-1是两个不同的环境。因此一个没上报cloud.account.id的工作负载和上报了它的工作负载会落进不同的环境这正是“预期一个环境却看到两个”的最常见原因。显示名由同样的值构造AWS ECS · us-east-1 · 123456789012。摄入ingest阶段会同时铸造键和名称如果你手工创建一个环境则只按键匹配其 Resource Identifier 必须精确写成platform|account|region。这一规则在源码中有唯一实现点。CloudPlatform.ts 中buildCloudEnvironmentKey约 L320-L328将三段各自trim后用|连接注释明确写道缺失段保留为空段aws_ecs||us-east-1这样日后补上 account id 的环境也不会被静默拆成另一个parseCloudEnvironmentKey约 L336-L351要求键严格是三段且平台段非空否则返回 null。而buildCloudEnvironmentName约 L357-L372负责生成label · region · account形式的显示名——注意名称只拼入非空的段而键则保留空段两者行为是有意区分的。该文件头注释还点明了这个注册表是“单一事实来源”摄入门控OtelIngestBaseService.autoDiscoverCloudResource、环境键/显示名的铸造、Dashboard 的 Cloud Resources 创建表单、应用内 Connect 向导的平台选择器、文档页面与测试全部读取同一份MANAGED_CLOUD_PLATFORMS常量保证四处不会互相矛盾。实例身份Instance identity环境内部每个正在运行的 task / instance / replica 对应一行实例记录取自第一个存在的以下资源属性aws.ecs.task.id→aws.ecs.task.arn截短为 task id→faas.instance→azure.container_app.instance.id→service.instance.id→container.id→host.id→host.name。平台自身的 task / instance 身份故意排在最前sidecar collector 和应用 SDK 都能看到它且它在进程重启后保持不变而 SDK 铸造的service.instance.id通常是每进程一个随机 idNode SDK 默认的serviceinstancedetector 正是如此——若以它为主键一旦awsecscontainermetricsreceiver 按 task id 上报该任务一个 ECS 任务就会立刻裂成两行。只有当平台不提供自身身份时App Runner、App Service、Beanstalk、Container Instances才回落到service.instance.id。源码印证了这一点。CloudInstanceIdentity.ts 中的常量CLOUD_INSTANCE_IDENTITY_ATTRIBUTESL38-L47与文档列表逐项一致shortenEcsTaskArnL54-L64把arn:aws:ecs:us-east-1:123456789012:task/my-cluster/1a2b3c4d5e6f截成 task id即 ECS 控制台显示的、适合放进表格的那段非 ARN 值原样返回resolveCloudInstanceNameL76-L94按序遍历全部缺失时返回 null——此时环境依然有效只是不写实例行。文件头注释还解释了这条链的由来此前只读service.instance.id导致每个 ECS 环境的 Instances 标签页一直为空、CPU/内存磁贴无数据因为 ECS detector 根本不会设置service.instance.id。此外摄入侧OtelIngestBaseService的属性遍历与指标快照侧OtelMetricsIngestService中带resource.前缀的键通过调用方传入的 getter 使用同一条链两条路径对“什么是一个实例”永远一致——这是 sidecar 的 CPU/内存指标点能落到应用 span 同一行实例上的关键。四、受支持的平台平台cloud.platformcloud.*由谁填充实例身份指南AWS ECS / Fargateaws_ecsresource detectoraws.ecs.task.arnAWS ECS / FargateAWS Elastic Beanstalkaws_elastic_beanstalkresource detectorhost.id其他云平台AWS App Runneraws_app_runner手工设置host.name其他云平台Google Cloud Rungcp_cloud_runresource detectorfaas.instanceGoogle Cloud RunGoogle App Enginegcp_app_engineresource detectorfaas.instance其他云平台Azure Container Appsazure_container_appsresource detectorazure.container_app.instance.idAzure Container AppsAzure Container Instancesazure_container_instances手工设置host.name其他云平台Azure App Serviceazure_app_serviceresource detectorhost.id其他云平台两个术语与三条易踩的坑“Resource detector”指 OpenTelemetry 资源检测器——在 SDK 中或 Collector 的resourcedetectionprocessor 中——读取平台元数据并自动填上cloud.*属性“Set by hand”上游没有检测器只能写进OTEL_RESOURCE_ATTRIBUTES各平台页面给出确切的那一行Azure 的两条注释Container Apps 检测器知道平台和副本但不知道区域和订阅App Service 检测器知道平台、区域和实例但不知道订阅——缺的项必须手工补上拼写归一化Node / .NET 的 Azure 检测器把平台写成点号形式azure.container_apps、azure.app_service而 semconv 和 Collector 的 Azure 检测器用下划线。OneUptime 在摄入时把点号形式改写为下划线取值。最后一条在源码中有专门实现CloudPlatform.ts 的CLOUD_PLATFORM_ALIASESL217-L224映射azure.container_apps→azure_container_apps等normalizeCloudPlatformL231-L253负责 trim 查别名表 未知值原样返回。注释解释了不改写的后果同一订阅里一个团队用 Node SDK 检测器的应用与另一个团队的 Collector sidecar 会落进两个不同的环境。别名查找刻意使用Object.prototype.hasOwnProperty而非普通属性访问——因为值来自网络普通查找会把constructor、__proto__这类输入映射成Object.prototype成员函数而非平台。五、哪些不是 Cloud Environment边界同样重要文档用一张表划清了三类“长得像但不是”的场景你运行在出现位置原因EC2、Compute Engine、Azure VMaws_ec2、gcp_compute_engine、azure_vmHosts虚拟机是主机。参见主机 OpenTelemetry Collector 文档EKS、GKE、AKS、自建 KubernetesKubernetes由k8s.*属性路由。参见 Kubernetes Agent 文档Lambda、Cloud Functions、Azure Functionsaws_lambda、gcp_cloud_functions、azure_functionsServerless Functions由faas.name路由。参见 Serverless Functions 文档Cloud Run 与 App Engine 是有意骑线的它们的检测器同时设置受管的cloud.platform和faas.name所以每个服务在Serverless Functions下单独出现而Cloud Environment又把该项目与区域内的所有服务聚合起来。源码结构与此一致MANAGED_CLOUD_PLATFORMS与FAAS_CLOUD_PLATFORM_VALUES在 CloudPlatform.ts 中分开列举两个产品共享一套词表但互不认领同一资源。六、Step 1 — 把属性带上你的遥测两种形态Shape每个平台页面都展示两者Shape A — SDK 直连 OneUptime。在 SDK 中启用平台资源检测器并把 OTLP exporter 指向 OneUptimeNodeOTEL_NODE_RESOURCE_DETECTORSenv,host,os,aws/gcp/azurePythonOTEL_EXPERIMENTAL_RESOURCE_DETECTORSaws_ecs或gcp_resource_detectorJava-Dotel.resource.providers.aws.enabledtrue/gcpGocontrib 检测器.NETOpenTelemetry.Resources.*系列包没有额外容器代价是没有容器级 CPU / 内存。Shape B — sidecar OpenTelemetry Collector。在 task / instance / replica 里加第二个容器应用导出到localhost:4318collector 的resourcedetectionprocessor 给所有经过的数据打上cloud.*它持有 token在 ECS 上它还能顺带提供按 task 的 CPU / 内存processors: resourcedetection: detectors: [env, ecs] # Cloud Run / App Engine 用 [env, gcp]Container Apps 用 [env, azurecontainerapps] timeout: 5s七、Step 2 — 把 OTLP 导出到 OneUptimeCollector 侧完整导出配置exporters: otlphttp/oneuptime: endpoint: https://oneuptime.com/otlp headers: x-oneuptime-token: ${env:ONEUPTIME_TOKEN} service: pipelines: traces: receivers: [otlp] processors: [resourcedetection, batch] exporters: [otlphttp/oneuptime] metrics: receivers: [otlp] processors: [resourcedetection, batch] exporters: [otlphttp/oneuptime] logs: receivers: [otlp] processors: [resourcedetection, batch] exporters: [otlphttp/oneuptime]${env:ONEUPTIME_TOKEN}由 collector 从环境变量展开而该环境变量由平台的 secret store 注入AWS Secrets Manager、GCP Secret Manager、Container Apps secrets。若是 Shape A则直接配在应用本身上OTEL_EXPORTER_OTLP_ENDPOINThttps://oneuptime.com/otlp OTEL_EXPORTER_OTLP_HEADERSx-oneuptime-tokenYOUR_TELEMETRY_INGESTION_TOKEN如果你自建self-host了 OneUptime把 endpoint 换成https://YOUR-ONEUPTIME-HOST/otlp。八、Step 3 — 验证接入curl -i https://oneuptime.com/otlp/v1/validate \ -H x-oneuptime-token: YOUR_TELEMETRY_INGESTION_TOKEN返回200且valid: true说明 token 能解析到某个项目401说明 token 未知、已吊销或拼错。首个 span 之后的一分钟内该环境应出现在Cloud → All Environments。九、环境详情页给你什么环境总览包含Requests、错误率与 p95 延迟带趋势图由你的 traces 派生每个运行中 task / instance 的CPU与Memory外加Top instances by CPU列表——来自携带实例身份的container.cpu.utilization/container.memory.usage指标在 ECS 上则是awsecscontainermetricsreceiver 的ecs.task.cpu.utilized/ecs.task.memory.utilizedInstances——task 的实时数量以及一个每 task 一行的标签页按环境限定范围的完整Logs、Traces、Metrics标签页。遥测停止 15 分钟的环境会显示Disconnected下一次信号到达即恢复。同一批工作负载的按服务拆分在Services下查看。这个 15 分钟阈值在摄入代码中有对应的工程约束OtelIngestBaseService.ts 中updateLastSeen的维护写操作被一个 5 分钟带抖动的 Redis TTL 栅栏节流而注释明确要求所有markDisconnected*阈值必须显著高于该 TTL实际用的 15 分钟约为其 2.4 倍否则健康资源会在 connected / disconnected 之间抖动。十、端到端一条遥测如何变成环境记录把上述机制串起来摄入路径在 OtelIngestBaseService.ts 的autoDiscoverCloudResource约 L2182-L2333中一目了然门控normalizeCloudPlatform归一化cloud.platform且必须命中MANAGED_CLOUD_PLATFORM_VALUES否则直接返回 null这就是 EC2/K8s 永远不会建环境的代码原因补全cloud.provider缺失时由平台推断填充手写OTEL_RESOURCE_ATTRIBUTES常常只带平台一个属性铸键与命名buildCloudEnvironmentKeybuildCloudEnvironmentName键作为CloudResourceService.findOrCreateByResourceIdentifier的查找键——手工创建的环境只要 Resource Identifier 一致就会被“找到”而非重复创建实例记录resolveCloudInstanceName解析实例名后经CloudResourceInstanceService.recordInstance写入实例行同样受维护栅栏节流标签提升promoteOneuptimeLabelsToCloudResource会把遥测属性中的一组 OneUptime 标签挂载到环境记录上。该方法的头注释还强调了一个设计决策环境的身份是cloud.platform cloud.account.id cloud.region而不是service.name——这样单个 CloudResource 聚合该平台/账号/区域上的所有工作负载避免了与 Service 行的service.name重叠镜像。十一、排障入口当环境不出现、出现在 Hosts 下、只出现在 Serverless Functions 下、没有 Instances 或没有 CPU/内存、显示 Disconnected、环境被重复创建、或手工创建的环境始终匹配不上时参见 Cloud Troubleshooting。结合本文的机制多数问题都能快速归因两个环境几乎总是cloud.account.id或cloud.region一段缺失导致空段键aws_ecs||us-east-1Instances 为空检查实例身份链——ECS 上应看到 task id 而非每进程随机 UUID说明 sidecar 与 SDK 的身份不一致Node/.NET Azure 应用没进环境点号拼写的cloud.platform虽会被摄入归一化但若你按归一化前的值手工建了环境Resource Identifier 必须用下划线值platform|account|region才能匹配。【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考