全链路数据确实能够很好的帮助相关人员及时、准确的发现业务问题。但企业业务发生问题的概率一般都很低,全链路采样有着自身的优缺点。

优点

  • 链路数据健全

缺点

  • 资源浪费。由于数据健全导致数据存储资源成本大大提高,对于异常链路数据检索成本提高

基于全链路数据采集的采样,OpenTelemetry 支持两种类型的采样器

1、概率采样器(probabilisticsamplerprocessor) 2、尾部采样器(tailsamplingprocessor)

概率采样处理器

顾名思义,概率采样器,是按照某种概率进行采样。同样OpenTelemetry 支持两种概率采样

1、sampling.priority OpenTracing 定义的语义约定 2、TraceId hash

sampling.priority语义约定优先于 TraceId hash。顾名思义,TraceId hash 采样基于由TraceId 确定的 hash 值。为了使 TraceId hash 起作用,给定层的所有收集器(例如,在同一负载均衡器后面)必须具有相同的hash_seed. 也可以利用hash_seed不同收集器层的不同来支持额外的采样要求。有关配置规范,请参阅 config.go

可以修改以下配置选项:

  • hash_seed(无默认值):用于计算哈希算法的整数。请注意,给定层的所有收集器(例如,在同一个负载均衡器后面)应该具有相同的 hash_seed。
    在使用多层采集器实现所需采样率的情况下,这一点很重要,例如:第一层为10%,第二层为10%,总体采样率为1%(10%x 10%)。
    如果所有层使用相同的种子,则通过一层的所有数据也将通过下一层,与配置的采样率无关。在不同的层中有不同的种子可以确保每层中的采样率按预期工作。
  • sampling_percentage(默认值 = 0):对 trace 进行采样的百分比;>= 100 表示采集所有的 trace。

配置概率采样器

  1. processors:
  2. # 概率采样器
  3. probabilistic_sampler:
  4. hash_seed: 22
  5. sampling_percentage: 15.3

启用概率采样器

  1. service:
  2. extensions: [pprof, zpages, health_check]
  3. pipelines:
  4. traces:
  5. receivers: [otlp]
  6. processors: [batch,probabilistic_sampler]
  7. exporters: [otlp]
  8. metrics:
  9. receivers: [otlp]
  10. processors: [batch]
  11. exporters: [otlp]

尾部采样器

尾部采样处理器根据一组定义的策略对 trace 进行采样。目前,该处理器仅适用于 collector 的单个实例。从技术上讲,traceId 感知负载平衡可用于支持多个 collector 实例,但此配置尚未经过测试。有关配置规范,请参阅 config.go

需要以下配置选项:

  • policies(无默认值):用于做出抽样决策的策略

目前支持多种策略。这些包括:

  • always_sample:采样所有的 traces
  • latency:基于 trace 持续时间的采样。持续时间是通过查看最早的开始时间和最晚的结束时间来确定的,而不考虑两者之间发生的事情。
  • numeric_attribute: 基于数字属性的采样
  • probabilistic:采样一定百分比的 trace 。
  • status_code: 基于状态码的示例 ( OK,ERRORUNSET)。很多人当做是response body json的 code(现在很多项目都这么定义),其实是不对的。
  • string_attribute:基于字符串属性值匹配的采样,支持精确匹配和正则表达式值匹配
  • rate_limiting: 基于速率的采样
  • and:基于多个策略的采样,创建一个 AND 策略
  • composite:基于上述采样器组合的采样,每个采样器具有排序和速率分配。费率分配为每个保单订单分配一定百分比的跨度。例如,如果我们将 max_total_spans_per_second 设置为 100,那么我们可以将 rate_allocation 设置如下
    1. test-composite-policy-1 = max_total_spans_per_second 的 50 % = 50 spans_per_second
    2. test-composite-policy-2 = max_total_spans_per_second 的 25 % = 25 spans_per_second
    3. 为确保剩余容量被填满,请使用 always_sample 作为策略之一

还可以修改以下配置选项:

  • decision_wait(默认 = 30 秒):在做出采样决定之前,从 trace 的第一个跨度开始的等待时间
  • num_traces(默认值 = 50000):内存中保存的 trace 数
  • expected_new_traces_per_sec(默认 = 0):预期的新 trace 数(有助于分配数据结构)

例子:

  1. processors:
  2. tail_sampling:
  3. decision_wait: 10s
  4. num_traces: 100
  5. expected_new_traces_per_sec: 10
  6. policies: [
  7. {
  8. name: test-policy-1,
  9. type: always_sample
  10. },
  11. {
  12. name: test-policy-2,
  13. type: latency,
  14. latency: {threshold_ms: 5000}
  15. },
  16. {
  17. name: test-policy-3,
  18. type: numeric_attribute,
  19. numeric_attribute: {key: key1, min_value: 50, max_value: 100}
  20. },
  21. {
  22. name: test-policy-4,
  23. type: probabilistic,
  24. probabilistic: {sampling_percentage: 10}
  25. },
  26. {
  27. name: test-policy-5,
  28. type: status_code,
  29. status_code: {status_codes: [ERROR, UNSET]}
  30. },
  31. {
  32. name: test-policy-6,
  33. type: string_attribute,
  34. string_attribute: {key: key2, values: [value1, value2]}
  35. },
  36. {
  37. name: test-policy-7,
  38. type: string_attribute,
  39. string_attribute: {key: key2, values: [value1, val*], enabled_regex_matching: true, cache_max_size: 10}
  40. },
  41. {
  42. name: test-policy-8,
  43. type: rate_limiting,
  44. rate_limiting: {spans_per_second: 35}
  45. },
  46. {
  47. name: test-policy-9,
  48. type: string_attribute,
  49. string_attribute: {key: http.url, values: [\/health, \/metrics], enabled_regex_matching: true, invert_match: true}
  50. },
  51. {
  52. name: and-policy-1,
  53. type: and,
  54. and: {
  55. and_sub_policy: [
  56. {
  57. name: test-and-policy-1,
  58. type: numeric_attribute,
  59. numeric_attribute: { key: key1, min_value: 50, max_value: 100 }
  60. },
  61. {
  62. name: test-and-policy-2,
  63. type: string_attribute,
  64. string_attribute: { key: key2, values: [ value1, value2 ] }
  65. },
  66. ]
  67. }
  68. },
  69. {
  70. name: composite-policy-1,
  71. type: composite,
  72. composite: {
  73. max_total_spans_per_second: 1000,
  74. policy_order: [test-composite-policy-1, test-composite-policy-2, test-composite-policy-3],
  75. composite_sub_policy: [
  76. {
  77. name: test-composite-policy-1,
  78. type: numeric_attribute,
  79. numeric_attribute: {key: key1, min_value: 50, max_value: 100}
  80. },
  81. {
  82. name: test-composite-policy-2,
  83. type: string_attribute,
  84. string_attribute: {key: key2, values: [value1, value2]}
  85. },
  86. {
  87. name: test-composite-policy-3,
  88. type: always_sample
  89. }
  90. ],
  91. rate_allocation: [
  92. {
  93. policy: test-composite-policy-1,
  94. percent: 50
  95. },
  96. {
  97. policy: test-composite-policy-2,
  98. percent: 25
  99. }
  100. ]
  101. }
  102. },
  103. ]

有关使用处理器的详细示例,请参阅tail_sampling_config.yaml

演示 demo

本 demo 主要是将 OpenTelemetry 数据推送至 观测云

准备工作

1、下载源码:https://github.com/lrwh/observable-demo/tree/main/opentelemetry-collector-sampling
2、确保已经安装了 DataKit

服务名称 端口 描述
otel-collector otel/opentelemetry-collector-contrib:0.51.0
springboot_server 8080:8080 opentelemetry-agent 版本 1.13.1, 源码地址:https://github.com/lrwh/observable-demo/tree/main/springboot-server

3、Datakit 开启 OpenTelemetry 采集,参照最佳实践OpenTelemetry 链路数据接入最佳实践

启动服务

  1. docker-compose up -d

以下示例主要以尾部采样策略为测试场景。
配置尾部采样器

  1. processors:
  2. # 尾部采样器
  3. tail_sampling:
  4. decision_wait: 10s
  5. num_traces: 100
  6. expected_new_traces_per_sec: 100
  7. policies:
  8. [
  9. {
  10. name: policy-1,
  11. type: status_code,
  12. status_code: {status_codes: [ERROR]}
  13. },
  14. {
  15. name: policy-2,
  16. type: probabilistic,
  17. probabilistic: {sampling_percentage: 20}
  18. }
  19. ]

以上规则是的关系,表示policy-1policy-2 任意一个成立则进行采样。

启用尾部采样器

  1. service:
  2. extensions: [pprof, zpages, health_check]
  3. pipelines:
  4. traces:
  5. receivers: [otlp]
  6. processors: [batch,tail_sampling]
  7. exporters: [otlp]
  8. metrics:
  9. receivers: [otlp]
  10. processors: [batch]
  11. exporters: [otlp]

场景一

1、访问服务API gateway 5 次,每次均为正常返回

curl http://localhost:8080/gateway

2、前往观测云查看trace信息,按照采样规则,最多采样一次trace数据。

场景二

1、设置启动客户端

curl http://localhost:8080/setClient?c=true

当前演示demo并没有启动客户端服务,所以后续调用 gateway 接口会有异常产生。

2、访问 5 次gateway服务,返回 {"msg":"client 调用失败","code":500}
3、前往观测云查看trace信息,按照采样规则,如果发生异常,则异常全采。

概率采样处理器与采用概率策略的尾部采样处理器相比

概率采样处理器和概率尾采样处理器策略的工作方式非常相似:基于可配置的采样百分比,它们将对接收到的 trace 进行固定比率的采样。但根据整体处理管道,您应该更喜欢使用其中一个。

根据经验,如果您想添加概率采样和…
…您还没有使用尾部采样处理器:使用概率采样处理器。运行概率采样处理器比尾部采样处理器更有效。概率抽样策略根据 traceId 做出决定,因此等待更多跨度到达不会影响其决定。
…您已经在使用尾部采样处理器:添加概率采样策略。您已经承担了运行尾部采样处理器的成本,添加概率策略将可以忽略不计。此外,在尾部采样处理器中使用该策略将确保不会丢弃由其他策略采样的 trace 。