Skip to content

Commit

Permalink
feat(zipkin): add variable (#10361)
Browse files Browse the repository at this point in the history
  • Loading branch information
wizhuo committed Oct 27, 2023
1 parent f1d4168 commit 595672c
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 2 deletions.
8 changes: 8 additions & 0 deletions apisix/cli/ngx_tpl.lua
Expand Up @@ -643,6 +643,14 @@ http {
{% end %}
# opentelemetry_set_ngx_var ends
# zipkin_set_ngx_var starts
{% if zipkin_set_ngx_var then %}
set $zipkin_context_traceparent '';
set $zipkin_trace_id '';
set $zipkin_span_id '';
{% end %}
# zipkin_set_ngx_var ends
# http server configuration snippet starts
{% if http_server_configuration_snippet then %}
{* http_server_configuration_snippet *}
Expand Down
9 changes: 8 additions & 1 deletion apisix/cli/ops.lua
Expand Up @@ -546,6 +546,12 @@ Please modify "admin_key" in conf/config.yaml .
if enabled_plugins["opentelemetry"] and yaml_conf.plugin_attr["opentelemetry"] then
opentelemetry_set_ngx_var = yaml_conf.plugin_attr["opentelemetry"].set_ngx_var
end

local zipkin_set_ngx_var
if enabled_plugins["zipkin"] and yaml_conf.plugin_attr["zipkin"] then
zipkin_set_ngx_var = yaml_conf.plugin_attr["zipkin"].set_ngx_var
end

-- Using template.render
local sys_conf = {
lua_path = env.pkg_path_org,
Expand All @@ -566,7 +572,8 @@ Please modify "admin_key" in conf/config.yaml .
control_server_addr = control_server_addr,
prometheus_server_addr = prometheus_server_addr,
proxy_mirror_timeouts = proxy_mirror_timeouts,
opentelemetry_set_ngx_var = opentelemetry_set_ngx_var
opentelemetry_set_ngx_var = opentelemetry_set_ngx_var,
zipkin_set_ngx_var = zipkin_set_ngx_var
}

if not yaml_conf.apisix then
Expand Down
22 changes: 21 additions & 1 deletion apisix/plugins/zipkin.lua
Expand Up @@ -20,13 +20,17 @@ local zipkin_codec = require("apisix.plugins.zipkin.codec")
local new_random_sampler = require("apisix.plugins.zipkin.random_sampler").new
local new_reporter = require("apisix.plugins.zipkin.reporter").new
local ngx = ngx
local ngx_var = ngx.var
local ngx_re = require("ngx.re")
local pairs = pairs
local tonumber = tonumber
local to_hex = require "resty.string".to_hex

local plugin_name = "zipkin"
local ZIPKIN_SPAN_VER_1 = 1
local ZIPKIN_SPAN_VER_2 = 2
local plugin = require("apisix.plugin")
local string_format = string.format


local lrucache = core.lrucache.new({
Expand Down Expand Up @@ -69,6 +73,8 @@ function _M.check_schema(conf)
return core.schema.check(schema, conf)
end

local plugin_info = plugin.plugin_attr(plugin_name) or {}


local function create_tracer(conf,ctx)
conf.route_id = ctx.route_id
Expand Down Expand Up @@ -205,9 +211,23 @@ function _M.rewrite(plugin_conf, ctx)
ctx.opentracing_sample = tracer.sampler:sample(per_req_sample_ratio or conf.sample_ratio)
if not ctx.opentracing_sample then
request_span:set_baggage_item("x-b3-sampled","0")
else
request_span:set_baggage_item("x-b3-sampled","1")
end

if plugin_info.set_ngx_var then
local span_context = request_span:context()
ngx_var.zipkin_context_traceparent = string_format("00-%s-%s-%02x",
to_hex(span_context.trace_id),
to_hex(span_context.span_id),
span_context:get_baggage_item("x-b3-sampled"))
ngx_var.zipkin_trace_id = span_context.trace_id
ngx_var.zipkin_span_id = span_context.span_id
end

if not ctx.opentracing_sample then
return
end
request_span:set_baggage_item("x-b3-sampled","1")

local request_span = ctx.opentracing.request_span
if conf.span_version == ZIPKIN_SPAN_VER_1 then
Expand Down
2 changes: 2 additions & 0 deletions conf/config-default.yaml
Expand Up @@ -615,6 +615,8 @@ plugin_attr: # Plugin attributes
hooks_file: "/usr/local/apisix/plugin_inspect_hooks.lua" # Set the path to the Lua file that defines
# hooks. Only administrators should have
# write access to this file for security.
zipkin: # Plugin: zipkin
set_ngx_var: false # export zipkin variables to nginx variables

deployment: # Deployment configurations
role: traditional # Set deployment mode: traditional, control_plane, or data_plane.
Expand Down
29 changes: 29 additions & 0 deletions docs/en/latest/plugins/zipkin.md
Expand Up @@ -235,3 +235,32 @@ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13
}
}'
```

## Variables

The following nginx variables are set by zipkin:

- `zipkin_context_traceparent` - [W3C trace context](https://www.w3.org/TR/trace-context/#trace-context-http-headers-format), e.g.: `00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01`
- `zipkin_trace_id` - Trace Id of the current span
- `zipkin_span_id` - Span Id of the current span

How to use variables? you have to add it to your configuration file (`conf/config.yaml`):

```yaml title="./conf/config.yaml"
http:
enable_access_log: true
access_log: "/dev/stdout"
access_log_format: '{"time": "$time_iso8601","zipkin_context_traceparent": "$zipkin_context_traceparent","zipkin_trace_id": "$zipkin_trace_id","zipkin_span_id": "$zipkin_span_id","remote_addr": "$remote_addr","uri": "$uri"}'
access_log_format_escape: json
plugins:
- zipkin
plugin_attr:
zipkin:
set_ngx_var: true
```

You can also include a trace_id when printing logs

```print error log
log.error(ngx.ERR,ngx_var.zipkin_trace_id,"error message")
```
29 changes: 29 additions & 0 deletions docs/zh/latest/plugins/zipkin.md
Expand Up @@ -235,3 +235,32 @@ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13
}
}'
```

## 如何使用变量

以下`nginx`变量是由`zipkin` 设置的。

- `zipkin_context_traceparent` - [W3C trace context](https://www.w3.org/TR/trace-context/#trace-context-http-headers-format), 例如:`00-0af7651916cd43dd8448eb211c80319c-b9c7c989f97918e1-01`
- `zipkin_trace_id` - 当前 span 的 trace_id
- `zipkin_span_id` - 当前 span 的 span_id

如何使用?你需要在配置文件(`./conf/config.yaml`)设置如下:

```yaml title="./conf/config.yaml"
http:
enable_access_log: true
access_log: "/dev/stdout"
access_log_format: '{"time": "$time_iso8601","zipkin_context_traceparent": "$zipkin_context_traceparent","zipkin_trace_id": "$zipkin_trace_id","zipkin_span_id": "$zipkin_span_id","remote_addr": "$remote_addr","uri": "$uri"}'
access_log_format_escape: json
plugins:
- zipkin
plugin_attr:
zipkin:
set_ngx_var: true
```

你也可以在打印日志的时候带上 `trace_id`

```print error log
log.error(ngx.ERR,ngx_var.zipkin_trace_id,"error message")
```
48 changes: 48 additions & 0 deletions t/cli/test_zipkin_set_ngx_var.sh
@@ -0,0 +1,48 @@
#!/usr/bin/env bash

#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

. ./t/cli/common.sh

echo '
plugins:
- zipkin
plugin_attr:
zipkin:
set_ngx_var: true
' > conf/config.yaml

make init

if ! grep "set \$zipkin_context_traceparent '';" conf/nginx.conf > /dev/null; then
echo "failed: zipkin_context_traceparent not found in nginx.conf"
exit 1
fi

if ! grep "set \$zipkin_trace_id '';" conf/nginx.conf > /dev/null; then
echo "failed: zipkin_trace_id not found in nginx.conf"
exit 1
fi

if ! grep "set \$zipkin_span_id '';" conf/nginx.conf > /dev/null; then
echo "failed: zipkin_span_id not found in nginx.conf"
exit 1
fi


echo "passed: zipkin_set_ngx_var configuration is validated"
129 changes: 129 additions & 0 deletions t/plugin/zipkin3.t
@@ -0,0 +1,129 @@
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

use t::APISIX 'no_plan';

repeat_each(1);
no_long_string();
no_root_location();
log_level("info");

add_block_preprocessor(sub {
my ($block) = @_;

if (!$block->extra_yaml_config) {
my $extra_yaml_config = <<_EOC_;
plugins:
- zipkin
plugin_attr:
zipkin:
set_ngx_var: true
_EOC_
$block->set_value("extra_yaml_config", $extra_yaml_config);
}

my $upstream_server_config = $block->upstream_server_config // <<_EOC_;
set \$zipkin_context_traceparent "";
set \$zipkin_trace_id "";
set \$zipkin_span_id "";
_EOC_

$block->set_value("upstream_server_config", $upstream_server_config);

my $extra_init_by_lua = <<_EOC_;
local zipkin = require("apisix.plugins.zipkin")
local orig_func = zipkin.access
zipkin.access = function (...)
local traceparent = ngx.var.zipkin_context_traceparent
if traceparent == nil or traceparent == '' then
ngx.log(ngx.ERR,"ngx_var.zipkin_context_traceparent is empty")
else
ngx.log(ngx.ERR,"ngx_var.zipkin_context_traceparent:",ngx.var.zipkin_context_traceparent)
end
local orig = orig_func(...)
return orig
end
_EOC_

$block->set_value("extra_init_by_lua", $extra_init_by_lua);

if (!$block->request) {
$block->set_value("request", "GET /t");
}

$block;
});

run_tests;

__DATA__
=== TEST 1: add plugin metadata
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"zipkin": {
"endpoint": "http://127.0.0.1:9999/mock_zipkin",
"sample_ratio": 1
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/echo"
}]]
)
if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
=== TEST 2: trigger zipkin with open set variables
--- request
GET /echo
--- error_log eval
qr/ngx_var.zipkin_context_traceparent:00-\w{32}-\w{16}-01*/
=== TEST 3: trigger zipkin with disable set variables
--- yaml_config
plugin_attr:
zipkin:
set_ngx_var: false
--- request
GET /echo
--- error_log
ngx_var.zipkin_context_traceparent is empty

0 comments on commit 595672c

Please sign in to comment.