所有 Span 都以 unknown_service 的名义进来了
目标
用真实的 SDK 确认资源(Resource)在默认值、环境变量和代码中按什么优先级确定;用代码遵循 OTLP 中资源的分组结构和稳定的 HTTP 语义约定(semantic conventions);最后安全地合并 schema 不同的资源。
为什么重要
遥测用资源来说明“数据来自哪里”。service.name 以 unknown_service 进入时,仪表板的服务列表会挤成一项;环境变量和代码给出不同的值时,不弄清谁赢了就找不到原因。语义约定是后端和仪表板对属性名称与状态含义的约定,因此把 404 标记为错误,或把路径原文放进 span 名称,都会让错误率和基数(cardinality)同时出错。
已准备的环境
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py init 会在 /root/otca-resource/ 中放入 resource.py、grouping.py、server.py、merge.py 这些起始文件。/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe [env파일](占位符为 env 文件名)会在清除了所有 OTEL_ 环境变量的新进程中,只放入 env 文件的值,然后调用 Resource.create({})。/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show N 会显示第 N 步的实验结果。使用 lab-dev 镜像中的 OpenTelemetry Python SDK 1.44.0(/opt/otel-lab),不使用网络。评分器会用同一个 SDK 重新运行你的文件,对照行为与你填写的值。
步骤
- 用
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py init生成材料后,运行/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe。在清除了所有 OTEL_ 环境变量的新进程中显示Resource.create({})的结果。在/root/otca-resource/01-default.txt中写入service_name=、sdk_language=(telemetry.sdk.language)、has_instance_id=(是否存在 service.instance.id,true/false)。 - 在
/root/otca-resource/02-otel.env中写入OTEL_RESOURCE_ATTRIBUTES=service.name=cart,deployment.environment.name=staging和OTEL_SERVICE_NAME=checkout两行。查看/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe /root/otca-resource/02-otel.env的结果,在/root/otca-resource/02-env.txt中写入service_name=、environment=、winner=(确定 service.name 的环境变量名称)。 - 修改
/root/otca-resource/resource.py中的make_resource(),让它用Resource.create确定 service.name 为checkout-api、service.version 为2.4.1并返回。评分器会在传入OTEL_SERVICE_NAME=checkout、OTEL_RESOURCE_ATTRIBUTES=service.version=0.0.1,deployment.environment.name=prod的进程中调用这个函数。把/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 3的结果,以service_name=、service_version=、environment=的形式写入/root/otca-resource/03-code.txt。 - 在
/root/otca-resource/04-otel.env中写入一行OTEL_RESOURCE_ATTRIBUTES。team.owner的值是payments,risk,同时放入cloud.region=ap-northeast-2。逗号要做百分号编码(%2C)。/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 4会同时显示编码后的值,以及同一个值未编码时的结果。在/root/otca-resource/04-encoding.txt中写入team_owner=与unencoded_team_owner=。 - 修改
/root/otca-resource/grouping.py中的emit(provider_a, provider_b),让它用 provider_a 的 tracer 创建并结束 2 个 span,用 provider_b 创建并结束 1 个 span。/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 5会显示把两个 provider(service.name 分别为 frontend、orders-db)的 span 编码为 OTLP 之后的结果。在/root/otca-resource/05-grouping.txt中写入resource_spans=、spans=、service_name_on_spans=(span 属性中是否有 service.name,true/false)。 - 修改
/root/otca-resource/server.py中的handle(tracer, request),让它按稳定(stable)的 HTTP 语义约定为一个请求创建服务端 span。评分器会用 201、404、503 三个请求来确认:类型为 SERVER,名称为{메서드} {경로 템플릿}(占位符依次为 HTTP 方法与路由模板),属性为http.request.method、url.path、http.route、http.response.status_code(整数),没有旧名称(http.method、http.target、http.status_code),5xx 时状态为 ERROR 并带有error.type(状态码字符串),其余情况状态留空。可以用{RS} show 6查看所创建的 span。 /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 7会显示用merge把配置的资源(schema 1.26.0,service.name checkout)合并到检测到的资源(schema 1.21.0,service.name unknown_service)之后的结果。在/root/otca-resource/07-merge.txt中写入naive_service_name=,然后修改/root/otca-resource/merge.py中的combine(detected, configured),让它返回新资源:以配置的值为准,保留检测到的 host.name,schema_url 沿用配置的资源。不要修改输入的资源。
参考
- 规范要求对 OTEL_RESOURCE_ATTRIBUTES 的值中的逗号和等号做百分号编码,并建议出现错误时丢弃整个值(SHOULD)。第 4 步中看到的部分应用是此 SDK 版本的实际行为,其他语言的 SDK 可能不同。
- 常见错误:用
Resource(...)构造函数创建,导致环境变量被忽略;在服务端 span 中把 4xx 标记为 ERROR;直接使用悄悄失败的 merge 结果。 - Resource SDK、HTTP spans、SDK configuration
什么都没设置的服务的名称
用 /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py init 生成材料后,运行 /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe。在清除了所有 OTEL_ 环境变量的新进程中显示 Resource.create({}) 的结果。在 /root/otca-resource/01-default.txt 中写入 service_name=、sdk_language=(telemetry.sdk.language)、has_instance_id=(是否存在 service.instance.id,true/false)。
service.name 是必需属性,为空时 SDK 会填入默认值。有些属性即使不设置,SDK 也会自己生成。
两个环境变量都在指定名称时
在 /root/otca-resource/02-otel.env 中写入 OTEL_RESOURCE_ATTRIBUTES=service.name=cart,deployment.environment.name=staging 和 OTEL_SERVICE_NAME=checkout 两行。查看 /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py probe /root/otca-resource/02-otel.env 的结果,在 /root/otca-resource/02-env.txt 中写入 service_name=、environment=、winner=(确定 service.name 的环境变量名称)。
两个变量都会生成资源,但优先级是固定的。请根据结果中保留下来的 service.name 来判断。
代码中确定的值与环境变量
修改 /root/otca-resource/resource.py 中的 make_resource(),让它用 Resource.create 确定 service.name 为 checkout-api、service.version 为 2.4.1 并返回。评分器会在传入 OTEL_SERVICE_NAME=checkout、OTEL_RESOURCE_ATTRIBUTES=service.version=0.0.1,deployment.environment.name=prod 的进程中调用这个函数。把 /opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 3 的结果,以 service_name=、service_version=、environment= 的形式写入 /root/otca-resource/03-code.txt。
Resource.create 会在由检测器和环境变量生成的资源之上,覆盖作为参数传入的属性。参数中没有的键,会保留环境变量的值。Resource(...) 构造函数不会读取环境变量。
含有逗号的值
在 /root/otca-resource/04-otel.env 中写入一行 OTEL_RESOURCE_ATTRIBUTES。team.owner 的值是 payments,risk,同时放入 cloud.region=ap-northeast-2。逗号要做百分号编码(%2C)。/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 4 会同时显示编码后的值,以及同一个值未编码时的结果。在 /root/otca-resource/04-encoding.txt 中写入 team_owner= 与 unencoded_team_owner=。
在这个变量中,逗号是属性分隔符。值内部的逗号和等号必须编码。也请阅读未编码一方的 SDK 警告。
在 OTLP 中资源挂在哪里
修改 /root/otca-resource/grouping.py 中的 emit(provider_a, provider_b),让它用 provider_a 的 tracer 创建并结束 2 个 span,用 provider_b 创建并结束 1 个 span。/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 5 会显示把两个 provider(service.name 分别为 frontend、orders-db)的 span 编码为 OTLP 之后的结果。在 /root/otca-resource/05-grouping.txt 中写入 resource_spans=、spans=、service_name_on_spans=(span 属性中是否有 service.name,true/false)。
OTLP 会把拥有相同资源的 span 分为一组,资源只写一次。每个 span 自身并没有资源。
404 不是服务端的错误
修改 /root/otca-resource/server.py 中的 handle(tracer, request),让它按稳定(stable)的 HTTP 语义约定为一个请求创建服务端 span。评分器会用 201、404、503 三个请求来确认:类型为 SERVER,名称为 {메서드} {경로 템플릿}(占位符依次为 HTTP 方法与路由模板),属性为 http.request.method、url.path、http.route、http.response.status_code(整数),没有旧名称(http.method、http.target、http.status_code),5xx 时状态为 ERROR 并带有 error.type(状态码字符串),其余情况状态留空。可以用 {RS} show 6 查看所创建的 span。
对服务端来说,4xx 是请求方的问题,所以不标记为错误状态。在 span 名称里使用路径原文,每个请求的名称都会不同。
schema URL 不同,合并悄悄失败了
/opt/otel-lab/bin/python /opt/fixtures/otca_resource_lab.py show 7 会显示用 merge 把配置的资源(schema 1.26.0,service.name checkout)合并到检测到的资源(schema 1.21.0,service.name unknown_service)之后的结果。在 /root/otca-resource/07-merge.txt 中写入 naive_service_name=,然后修改 /root/otca-resource/merge.py 中的 combine(detected, configured),让它返回新资源:以配置的值为准,保留检测到的 host.name,schema_url 沿用配置的资源。不要修改输入的资源。
按规范,合并 schema URL 互不相同的两个资源属于错误;此 SDK 会记录错误,然后原样返回原来的资源。资源是不可变的,所以请创建新资源再合并。