LabHub
学习 学习路径 课程

OTCA — OpenTelemetry 认证助理

另一订单的标签跟来了

在 LabHub 中继续学习

目标

修正七个真实 Python 函数,传递执行时上下文,并在正常完成、异常和取消后 恢复原始上下文。随后将外部 baggage 的提取与按目的地划分的传播策略分开。

为什么重要

如果请求值附着到错误的任务上,即使收集到了数据,也会错误解读根因。 本实验在安装了 Python 3.12 和 OpenTelemetry SDK 1.44.0 的专用环境中,实际运行 asyncio、ThreadPoolExecutor 和 W3C baggage propagator。依赖项已经预装在镜像中, 无需从互联网下载,也不需要 API key。

不会运行外部 HTTP、DNS、Collector 或认证服务器。warehouse.internal 是传给函数的 逻辑目的地字符串。通过任务并不代表完成了真实网络目的地验证、身份认证与授权、 外部存储写入或全面的隐私保护验证。 第 8 步中 baggage 是否自动记录为 span attribute,根据前一理论课的 SDK 实验和 官方说明作出判断。其余代码检查均来自对 Context 函数执行过程的观察。

准备与运行

工作目录是 /root/otca-context。starters 中只准备了 8 个语法正确但行为错误的起始文件。 请将相应文件复制到工作目录后进行修改。

cd /root/otca-context
cp starters/scope.py scope.py
/opt/otel-lab/bin/python /opt/app/otca_sdk/runner.py --track context run 1

更改 run 后面的数字,即可查看相应步骤的 observations 和 checks。 请比较当前观察值与期望值。任务并不是修改 SDK 或评分器;只要实际行为正确, 语义相同的其他代码也可以通过。系统会在受限的子进程中运行答案副本,不修改原始文件。 单个代码最多运行 8 秒,综合执行总预算为 50 秒;无限循环和输出泛滥会判定失败。 不要把这一执行限制理解为针对恶意代码的独立安全隔离,隔离由实验 Pod 负责。

步骤

  1. /root/otca-context/scope.py——修正 scope.py 的 with_context(value, callback)。在回调执行一次期间,baggage request 必须为 value。原样传递返回值和原始异常,并在正常和异常两条路径中都恢复调用者此前的上下文。
  2. /root/otca-context/tasks.py——tasks.py 的 start_task(coro) 使用当前请求上下文调度协程,并返回供调用者 await 的对象。即使调用者后来更改上下文,任务也必须读取调度时的值,同时保留调用者的新值。
  3. /root/otca-context/threads.py——threads.py 的 start_thread(function) 调度同步函数在线程中执行,并返回可 await 的对象。让 worker 读取调用该函数时的请求值,而不是后来 await 时的值。
  4. /root/otca-context/executor.py——executor.py 的 submit(executor, function) 将函数提交给给定的 ThreadPoolExecutor,并返回 Future。必须传递提交时的请求值,且不得残留到同一 worker 的下一个普通任务中。调用者上下文也必须保留。
  5. /root/otca-context/requests.py——requests.py 的 async handle(value, callback) 将 baggage request 设置为 value,并 await 一次异步回调。即使两个请求重叠,也要隔离各自的值;正常返回、异常和 Task.cancel 时都恢复此前的上下文。返回值、异常和取消要原样传给调用者。
  6. /root/otca-context/incoming.py——incoming.py 的 inbound(carrier) 以空 OTel Context 为基准,从 W3C baggage header dict 中提取并返回 OTel Context。不要混入已有的本地 baggage,同时保留原始 dict 和调用者上下文。本步骤也提取 role=admin,但不要将其解释为认证成功。
  7. /root/otca-context/outgoing.py——outgoing.py 的 outbound(source, destination) 仅当 destination 与 warehouse.internal 完全相同时,才允许 region 的 test-east/test-west 和 channel 的 web/batch 字符串。将选中的值写入新 Context,返回 W3C baggage header dict。排除其他键、值和目的地,并保留原始对象。没有剩余值时返回空 dict。
  8. /root/otca-context/report.json——使用 JSON boolean 判断 report.json 中的八个假设。前七份代码也必须全部正常工作。请区分 Task 创建时机、延迟的 to_thread、普通 executor、取消后的恢复、baggage 与 span attribute、空 inbound、授权以及目的地的影响。

参考

回调后恢复原始请求

/root/otca-context/scope.py:修正 scope.py 的 with_context(value, callback)。在回调执行一次期间,baggage request 必须为 value。原样传递返回值和原始异常,并在正常和异常两条路径中都恢复调用者此前的上下文。

set_baggage 的返回值与附加当前上下文的操作并不相同。请确认回调后的恢复在异常路径中也会执行。

保留 Task 调度时的请求

/root/otca-context/tasks.py:tasks.py 的 start_task(coro) 使用当前请求上下文调度协程,并返回供调用者 await 的对象。即使调用者后来更改上下文,任务也必须读取调度时的值,同时保留调用者的新值。

请确认返回协程对象与创建带有当前 Context 的 Task 之间有何区别。

修正延迟线程任务捕获上下文的时机

/root/otca-context/threads.py:threads.py 的 start_thread(function) 调度同步函数在线程中执行,并返回可 await 的对象。让 worker 读取调用该函数时的请求值,而不是后来 await 时的值。

to_thread 返回的协程何时执行?请思考在当前上下文中调度执行的步骤。

不在复用的 worker 中残留上下文

/root/otca-context/executor.py:executor.py 的 submit(executor, function) 将函数提交给给定的 ThreadPoolExecutor,并返回 Future。必须传递提交时的请求值,且不得残留到同一 worker 的下一个普通任务中。调用者上下文也必须保留。

如果在 worker 内部才复制,已经太晚了。请寻找为每次提交创建独立副本并在其中执行的方法。

清理重叠请求与真实取消

/root/otca-context/requests.py:requests.py 的 async handle(value, callback) 将 baggage request 设置为 value,并 await 一次异步回调。即使两个请求重叠,也要隔离各自的值;正常返回、异常和 Task.cancel 时都恢复此前的上下文。返回值、异常和取消要原样传给调用者。

如果 detach 只放在正常返回之后,取消会跳过该行。请区分恢复上下文与吞掉取消。

隔离外部请求头与本地请求

/root/otca-context/incoming.py:incoming.py 的 inbound(carrier) 以空 OTel Context 为基准,从 W3C baggage header dict 中提取并返回 OTel Context。不要混入已有的本地 baggage,同时保留原始 dict 和调用者上下文。本步骤也提取 role=admin,但不要将其解释为认证成功。

请比较默认 extract 与显式指定空 Context 的 extract。还要区分 contextvars.Context 与 OTel Context。

同时限制目的地、键和值

/root/otca-context/outgoing.py:outgoing.py 的 outbound(source, destination) 仅当 destination 与 warehouse.internal 完全相同时,才允许 region 的 test-east/test-west 和 channel 的 web/batch 字符串。将选中的值写入新 Context,返回 W3C baggage header dict。排除其他键、值和目的地,并保留原始对象。没有剩余值时返回空 dict。

如果只允许键,值中仍可能携带其他信息。还要确认按目的地前缀比较时不会放行相似主机。

同时验证行为与假设

/root/otca-context/report.json:使用 JSON boolean 判断 report.json 中的八个假设。前七份代码也必须全部正常工作。请区分 Task 创建时机、延迟的 to_thread、普通 executor、取消后的恢复、baggage 与 span attribute、空 inbound、授权以及目的地的影响。

仅仅报告正确还不够。请区分实际观察与官方契约,并修正每个函数的失败原因。