Skip to content

Commit 6bf6ab9

Browse files
authored
feat(opentelemetry): add opentelemetry variables (#8871)
1 parent 9078352 commit 6bf6ab9

File tree

8 files changed

+295
-0
lines changed

8 files changed

+295
-0
lines changed

apisix/cli/ngx_tpl.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,14 @@ http {
635635
proxy_ssl_trusted_certificate {* ssl.ssl_trusted_certificate *};
636636
{% end %}
637637
638+
# opentelemetry_set_ngx_var starts
639+
{% if opentelemetry_set_ngx_var then %}
640+
set $opentelemetry_context_traceparent '';
641+
set $opentelemetry_trace_id '';
642+
set $opentelemetry_span_id '';
643+
{% end %}
644+
# opentelemetry_set_ngx_var ends
645+
638646
# http server configuration snippet starts
639647
{% if http_server_configuration_snippet then %}
640648
{* http_server_configuration_snippet *}

apisix/cli/ops.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,10 @@ Please modify "admin_key" in conf/config.yaml .
542542
end
543543
end
544544

545+
local opentelemetry_set_ngx_var
546+
if enabled_plugins["opentelemetry"] and yaml_conf.plugin_attr["opentelemetry"] then
547+
opentelemetry_set_ngx_var = yaml_conf.plugin_attr["opentelemetry"].set_ngx_var
548+
end
545549
-- Using template.render
546550
local sys_conf = {
547551
lua_path = env.pkg_path_org,
@@ -562,6 +566,7 @@ Please modify "admin_key" in conf/config.yaml .
562566
control_server_addr = control_server_addr,
563567
prometheus_server_addr = prometheus_server_addr,
564568
proxy_mirror_timeouts = proxy_mirror_timeouts,
569+
opentelemetry_set_ngx_var = opentelemetry_set_ngx_var
565570
}
566571

567572
if not yaml_conf.apisix then

apisix/plugins/opentelemetry.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ local type = type
4747
local pairs = pairs
4848
local ipairs = ipairs
4949
local unpack = unpack
50+
local string_format = string.format
5051

5152
local lrucache = core.lrucache.new({
5253
type = 'plugin', count = 128, ttl = 24 * 60 * 60,
@@ -112,6 +113,11 @@ local attr_schema = {
112113
},
113114
default = {},
114115
},
116+
set_ngx_var = {
117+
type = "boolean",
118+
description = "set nginx variables",
119+
default = false,
120+
},
115121
},
116122
}
117123

@@ -332,6 +338,17 @@ function _M.rewrite(conf, api_ctx)
332338
kind = span_kind.server,
333339
attributes = attributes,
334340
})
341+
342+
if plugin_info.set_ngx_var then
343+
local span_context = ctx:span():context()
344+
ngx_var.opentelemetry_context_traceparent = string_format("00-%s-%s-%02x",
345+
span_context.trace_id,
346+
span_context.span_id,
347+
span_context.trace_flags)
348+
ngx_var.opentelemetry_trace_id = span_context.trace_id
349+
ngx_var.opentelemetry_span_id = span_context.span_id
350+
end
351+
335352
api_ctx.otel_context_token = ctx:attach()
336353

337354
-- inject trace context into the headers of upstream HTTP request

conf/config-default.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ plugin_attr: # Plugin attributes
570570
inactive_timeout: 1 # Set the timeout for spans to wait in the export queue before being sent,
571571
# if the queue is not full.
572572
max_export_batch_size: 16 # Set the maximum number of spans to include in each batch sent to the
573+
set_ngx_var: false # export opentelemetry variables to nginx variables
573574
# OpenTelemetry collector.
574575
prometheus: # Plugin: prometheus
575576
export_uri: /apisix/prometheus/metrics # Set the URI for the Prometheus metrics endpoint.

docs/en/latest/plugins/opentelemetry.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,29 @@ plugin_attr:
8989
max_export_batch_size: 2
9090
```
9191
92+
## Variables
93+
94+
The following nginx variables are set by OpenTelemetry:
95+
96+
- `opentelemetry_context_traceparent` - [W3C trace context](https://www.w3.org/TR/trace-context/#trace-context-http-headers-format), e.g.: `00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01`
97+
- `opentelemetry_trace_id` - Trace Id of the current span
98+
- `opentelemetry_span_id` - Span Id of the current span
99+
100+
How to use variables? you have to add it to your configuration file (`conf/config.yaml`):
101+
102+
```yaml title="./conf/config.yaml"
103+
http:
104+
enable_access_log: true
105+
access_log: "/dev/stdout"
106+
access_log_format: '{"time": "$time_iso8601","opentelemetry_context_traceparent": "$opentelemetry_context_traceparent","opentelemetry_trace_id": "$opentelemetry_trace_id","opentelemetry_span_id": "$opentelemetry_span_id","remote_addr": "$remote_addr","uri": "$uri"}'
107+
access_log_format_escape: json
108+
plugins:
109+
- opentelemetry
110+
plugin_attr:
111+
opentelemetry:
112+
set_ngx_var: true
113+
```
114+
92115
## Enable Plugin
93116

94117
To enable the Plugin, you have to add it to your configuration file (`conf/config.yaml`):

docs/zh/latest/plugins/opentelemetry.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,29 @@ plugin_attr:
8888
max_export_batch_size: 2
8989
```
9090
91+
## 如何使用变量
92+
93+
以下`nginx`变量是由`opentelemetry` 设置的。
94+
95+
- `opentelemetry_context_traceparent` - [W3C trace context](https://www.w3.org/TR/trace-context/#trace-context-http-headers-format), 例如:`00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01`
96+
- `opentelemetry_trace_id` - 当前 span 的 trace_id
97+
- `opentelemetry_span_id` - 当前 span 的 span_id
98+
99+
如何使用?你需要在配置文件(`./conf/config.yaml`)设置如下:
100+
101+
```yaml title="./conf/config.yaml"
102+
http:
103+
enable_access_log: true
104+
access_log: "/dev/stdout"
105+
access_log_format: '{"time": "$time_iso8601","opentelemetry_context_traceparent": "$opentelemetry_context_traceparent","opentelemetry_trace_id": "$opentelemetry_trace_id","opentelemetry_span_id": "$opentelemetry_span_id","remote_addr": "$remote_addr","uri": "$uri"}'
106+
access_log_format_escape: json
107+
plugins:
108+
- opentelemetry
109+
plugin_attr:
110+
opentelemetry:
111+
set_ngx_var: true
112+
```
113+
91114
## 如何启用
92115

93116
`opentelemetry` 插件默认为禁用状态,你需要在配置文件(`./conf/config.yaml`)中开启该插件:
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env bash
2+
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership.
7+
# The ASF licenses this file to You under the Apache License, Version 2.0
8+
# (the "License"); you may not use this file except in compliance with
9+
# the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS,
15+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
# See the License for the specific language governing permissions and
17+
# limitations under the License.
18+
#
19+
20+
. ./t/cli/common.sh
21+
22+
echo '
23+
plugins:
24+
- opentelemetry
25+
plugin_attr:
26+
opentelemetry:
27+
set_ngx_var: true
28+
' > conf/config.yaml
29+
30+
make init
31+
32+
if ! grep "set \$opentelemetry_context_traceparent '';" conf/nginx.conf > /dev/null; then
33+
echo "failed: opentelemetry_context_traceparent not found in nginx.conf"
34+
exit 1
35+
fi
36+
37+
if ! grep "set \$opentelemetry_trace_id '';" conf/nginx.conf > /dev/null; then
38+
echo "failed: opentelemetry_trace_id not found in nginx.conf"
39+
exit 1
40+
fi
41+
42+
if ! grep "set \$opentelemetry_span_id '';" conf/nginx.conf > /dev/null; then
43+
echo "failed: opentelemetry_span_id not found in nginx.conf"
44+
exit 1
45+
fi
46+
47+
48+
echo "passed: opentelemetry_set_ngx_var configuration is validated"

t/plugin/opentelemetry3.t

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
use t::APISIX 'no_plan';
19+
20+
repeat_each(1);
21+
no_long_string();
22+
no_root_location();
23+
log_level("info");
24+
25+
add_block_preprocessor(sub {
26+
my ($block) = @_;
27+
28+
if (!$block->extra_yaml_config) {
29+
my $extra_yaml_config = <<_EOC_;
30+
plugins:
31+
- http-logger
32+
- opentelemetry
33+
plugin_attr:
34+
opentelemetry:
35+
set_ngx_var: true
36+
batch_span_processor:
37+
max_export_batch_size: 1
38+
inactive_timeout: 0.5
39+
_EOC_
40+
$block->set_value("extra_yaml_config", $extra_yaml_config);
41+
}
42+
43+
my $upstream_server_config = $block->upstream_server_config // <<_EOC_;
44+
set \$opentelemetry_context_traceparent "";
45+
set \$opentelemetry_trace_id "";
46+
set \$opentelemetry_span_id "";
47+
access_log logs/error.log opentelemetry_log;
48+
_EOC_
49+
50+
$block->set_value("upstream_server_config", $upstream_server_config);
51+
52+
my $http_config = $block->http_config // <<_EOC_;
53+
log_format opentelemetry_log '{"time": "\$time_iso8601","opentelemetry_context_traceparent": "\$opentelemetry_context_traceparent","opentelemetry_trace_id": "\$opentelemetry_trace_id","opentelemetry_span_id": "\$opentelemetry_span_id","remote_addr": "\$remote_addr","uri": "\$uri"}';
54+
_EOC_
55+
56+
$block->set_value("http_config", $http_config);
57+
58+
if (!$block->extra_init_by_lua) {
59+
my $extra_init_by_lua = <<_EOC_;
60+
-- mock exporter http client
61+
local client = require("opentelemetry.trace.exporter.http_client")
62+
client.do_request = function()
63+
ngx.log(ngx.INFO, "opentelemetry export span")
64+
return "ok"
65+
end
66+
_EOC_
67+
68+
$block->set_value("extra_init_by_lua", $extra_init_by_lua);
69+
}
70+
71+
72+
if (!$block->request) {
73+
$block->set_value("request", "GET /t");
74+
}
75+
76+
$block;
77+
});
78+
79+
run_tests;
80+
81+
__DATA__
82+
83+
=== TEST 1: add plugin metadata
84+
--- config
85+
location /t {
86+
content_by_lua_block {
87+
local t = require("lib.test_admin").test
88+
local code, body = t('/apisix/admin/plugin_metadata/http-logger',
89+
ngx.HTTP_PUT,
90+
[[{
91+
"log_format": {
92+
"opentelemetry_context_traceparent": "$opentelemetry_context_traceparent",
93+
"opentelemetry_trace_id": "$opentelemetry_trace_id",
94+
"opentelemetry_span_id": "$opentelemetry_span_id"
95+
}
96+
}]]
97+
)
98+
if code >= 300 then
99+
ngx.status = code
100+
return body
101+
end
102+
103+
local code, body = t('/apisix/admin/routes/1',
104+
ngx.HTTP_PUT,
105+
[[{
106+
"plugins": {
107+
"http-logger": {
108+
"uri": "http://127.0.0.1:1980/log",
109+
"batch_max_size": 1,
110+
"max_retry_count": 1,
111+
"retry_delay": 2,
112+
"buffer_duration": 2,
113+
"inactive_timeout": 2,
114+
"concat_method": "new_line"
115+
},
116+
"opentelemetry": {
117+
"sampler": {
118+
"name": "always_on"
119+
}
120+
}
121+
},
122+
"upstream": {
123+
"nodes": {
124+
"127.0.0.1:1982": 1
125+
},
126+
"type": "roundrobin"
127+
},
128+
"uri": "/hello"
129+
}]]
130+
)
131+
132+
if code >=300 then
133+
ngx.status = code
134+
end
135+
ngx.say(body)
136+
}
137+
}
138+
--- request
139+
GET /t
140+
--- response_body
141+
passed
142+
143+
144+
145+
=== TEST 2: trigger opentelemetry with open set variables
146+
--- request
147+
GET /hello
148+
--- response_body
149+
hello world
150+
--- wait: 1
151+
--- grep_error_log eval
152+
qr/opentelemetry export span/
153+
--- grep_error_log_out
154+
opentelemetry export span
155+
--- error_log eval
156+
qr/request log: \{.*"opentelemetry_context_traceparent":"00-\w{32}-\w{16}-01".*\}/
157+
158+
159+
160+
=== TEST 3: trigger opentelemetry with disable set variables
161+
--- yaml_config
162+
plugin_attr:
163+
opentelemetry:
164+
set_ngx_var: false
165+
--- request
166+
GET /hello
167+
--- response_body
168+
hello world
169+
--- error_log eval
170+
qr/request log: \{.*"opentelemetry_context_traceparent":"".*\}/

0 commit comments

Comments
 (0)