Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance: plugin Zipkin add service name and report local server IP #1386

Merged
24 changes: 22 additions & 2 deletions apisix/plugins/zipkin.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ local new_random_sampler = require("apisix.plugins.zipkin.random_sampler").new
local new_reporter = require("apisix.plugins.zipkin.reporter").new
local ngx = ngx
local pairs = pairs
local tonumber = tonumber

local plugin_name = "zipkin"

Expand All @@ -29,7 +30,17 @@ local schema = {
type = "object",
properties = {
endpoint = {type = "string"},
sample_ratio = {type = "number", minimum = 0.00001, maximum = 1}
sample_ratio = {type = "number", minimum = 0.00001, maximum = 1},
service_name = {
type = "string",
description = "service name for zipkin reporter",
default = "APISIX",
},
server_addr = {
type = "string",
description = "default is $server_addr, you can speific your external ip address",
pattern = "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"
},
},
required = {"endpoint", "sample_ratio"}
}
Expand Down Expand Up @@ -71,7 +82,15 @@ end


function _M.rewrite(conf, ctx)
local tracer = core.lrucache.plugin_ctx(plugin_name, ctx,

-- once the server started, server_addr and server_port won't change, so we can cache it.
conf.server_port = tonumber(ctx.var['server_port'])

if not conf.server_addr or conf.server_addr == '' then
conf.server_addr = ctx.var["server_addr"]
end

local tracer = core.lrucache.plugin_ctx(plugin_name .. '#' .. conf.server_addr, ctx,
create_tracer, conf)

ctx.opentracing_sample = tracer.sampler:sample()
Expand Down Expand Up @@ -109,6 +128,7 @@ function _M.rewrite(conf, ctx)
local request_span = ctx.opentracing.request_span
ctx.opentracing.rewrite_span = request_span:start_child_span(
"apisix.rewrite", start_timestamp)

ctx.REWRITE_END_TIME = tracer:time()
ctx.opentracing.rewrite_span:finish(ctx.REWRITE_END_TIME)
end
Expand Down
25 changes: 12 additions & 13 deletions apisix/plugins/zipkin/reporter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@ local span_kind_map = {

function _M.new(conf)
local endpoint = conf.endpoint
local service_name = conf.service_name
local server_port = conf.server_port
local server_addr = conf.server_addr
assert(type(endpoint) == "string", "invalid http endpoint")
return setmetatable({
endpoint = endpoint,
service_name = service_name,
server_addr = server_addr,
server_port = server_port,
pending_spans = {},
pending_spans_n = 0,
}, mt)
Expand All @@ -55,19 +61,12 @@ function _M.report(self, span)
local span_kind = zipkin_tags["span.kind"]
zipkin_tags["span.kind"] = nil

local localEndpoint do
local serviceName = zipkin_tags["peer.service"]
if serviceName then
zipkin_tags["peer.service"] = nil
localEndpoint = {
serviceName = serviceName,
-- TODO: ip/port from ngx.var.server_name/ngx.var.server_port?
}
else
-- needs to be null, not the empty object
localEndpoint = cjson.null
end
end
local localEndpoint = {
serviceName = self.service_name,
ipv4 = self.server_addr,
port = self.server_port,
-- TODO: ip/port from ngx.var.server_name/ngx.var.server_port?
}

local remoteEndpoint do
local peer_port = span:get_tag "peer.port" -- get as number
Expand Down
49 changes: 47 additions & 2 deletions doc/plugins/zipkin-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@

## 属性

* `endpoint`: Ziplin 的 http 节点,例如`http://127.0.0.1:9411/api/v2/spans`。
* `endpoint`: Zipkin 的 http 节点,例如`http://127.0.0.1:9411/api/v2/spans`。
* `sample_ratio`: 监听的比例,最小为0.00001,最大为1。
* `service_name`: 可选参数,标记当前服务的名称,默认值是`APISIX`。
* `server_addr`: 可选参数,标记当前 APISIX 实例的IP地址,默认值是 nginx 的内置变量`server_addr`。|

## 如何启用

Expand All @@ -49,7 +51,9 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f1
"plugins": {
"zipkin": {
"endpoint": "http://127.0.0.1:9411/api/v2/spans",
"sample_ratio": 1
"sample_ratio": 1,
"service_name": "APISIX-IN-SG",
"server_addr": "192.168.3.50"
}
},
"upstream": {
Expand Down Expand Up @@ -118,3 +122,44 @@ $ curl http://127.0.0.1:2379/v2/keys/apisix/routes/1 -X PUT -d value='
```

现在就已经移除了 Zipkin 插件了。其他插件的开启和移除也是同样的方法。


## 上游服务是Golang的示例代码

```golang
func GetTracer(serviceName string, port int, enpoitUrl string, rate float64) *zipkin.Tracer {
// create a reporter to be used by the tracer
reporter := httpreporter.NewReporter(enpoitUrl)
// set-up the local endpoint for our service host is ip:host

thisip, _ := GetLocalIP()

host := fmt.Sprintf("%s:%d", thisip, port)
endpoint, _ := zipkin.NewEndpoint(serviceName, host)
// set-up our sampling strategy
sampler, _ := zipkin.NewCountingSampler(rate)
// initialize the tracer
tracer, _ := zipkin.NewTracer(
reporter,
zipkin.WithLocalEndpoint(endpoint),
zipkin.WithSampler(sampler),
)
return tracer
}

func main(){
r := gin.Default()

tracer := GetTracer(...)

// use middleware to extract parentID from http header that injected by APISIX
r.Use(func(c *gin.Context) {
span := this.Tracer.Extract(b3.ExtractHTTP(c.Request))
childSpan := this.Tracer.StartSpan(spanName, zipkin.Parent(span))
defer childSpan.Finish()
c.Next()
})

}
```

46 changes: 45 additions & 1 deletion doc/plugins/zipkin.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ It's also works with `Apache SkyWalking`, which is support Zipkin v1/v2 format.
|--------- |--------|-----------|
| endpoint |required|the http endpoint of Ziplin, for example: `http://127.0.0.1:9411/api/v2/spans`.|
| sample_ratio |required|the ratio of sample, the minimum is 0.00001, the maximum is 1.|
| service_name |optional|service name for zipkin reporter, the default values is `APISIX`.|
| server_addr |optional|IPv4 address for zipkin reporter, default is nginx built-in variables $server_addr, here you can speific your external ip address.|

## How To Enable

Expand All @@ -52,7 +54,9 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f1
"plugins": {
"zipkin": {
"endpoint": "http://127.0.0.1:9411/api/v2/spans",
"sample_ratio": 1
"sample_ratio": 1,
"service_name": "APISIX-IN-SG",
"server_addr": "192.168.3.50"
}
},
"upstream": {
Expand Down Expand Up @@ -123,3 +127,43 @@ $ curl http://127.0.0.1:2379/v2/keys/apisix/routes/1 -X PUT -d value='
```

The zipkin plugin has been disabled now. It works for other plugins.

## example code for upstream ( golang with Gin )

```golang
func GetTracer(serviceName string, port int, enpoitUrl string, rate float64) *zipkin.Tracer {
// create a reporter to be used by the tracer
reporter := httpreporter.NewReporter(enpoitUrl)
// set-up the local endpoint for our service host is ip:host

thisip, _ := GetLocalIP()

host := fmt.Sprintf("%s:%d", thisip, port)
endpoint, _ := zipkin.NewEndpoint(serviceName, host)
// set-up our sampling strategy
sampler, _ := zipkin.NewCountingSampler(rate)
// initialize the tracer
tracer, _ := zipkin.NewTracer(
reporter,
zipkin.WithLocalEndpoint(endpoint),
zipkin.WithSampler(sampler),
)
return tracer
}

func main(){
r := gin.Default()

tracer := GetTracer(...)

// use middleware to extract parentID from http header that injected by APISIX
r.Use(func(c *gin.Context) {
span := this.Tracer.Extract(b3.ExtractHTTP(c.Request))
childSpan := this.Tracer.StartSpan(spanName, zipkin.Parent(span))
defer childSpan.Finish()
c.Next()
})

}
```

17 changes: 17 additions & 0 deletions t/lib/server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,23 @@ function _M.mock_zipkin()
if not span.traceId then
ngx.exit(400)
end

if not span.localEndpoint then
ngx.exit(400)
end

if span.localEndpoint.serviceName ~= 'APISIX' and span.localEndpoint.serviceName ~= 'apisix' then
lilien1010 marked this conversation as resolved.
Show resolved Hide resolved
ngx.exit(400)
end

if span.localEndpoint.port ~= 1984 then
ngx.exit(400)
end

if span.localEndpoint.ipv4 ~= ngx.req.get_uri_args()['server_addr'] then
ngx.exit(400)
end

end
end

Expand Down
89 changes: 85 additions & 4 deletions t/plugin/zipkin.t
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,9 @@ done
[[{
"plugins": {
"zipkin": {
"endpoint": "http://127.0.0.1:1982/mock_zipkin",
"sample_ratio": 1
"endpoint": "http://127.0.0.1:1982/mock_zipkin?server_addr=127.0.0.1",
"sample_ratio": 1,
"service_name": "APISIX"
}
},
"upstream": {
Expand All @@ -142,8 +143,9 @@ done
"value": {
"plugins": {
"zipkin": {
"endpoint": "http://127.0.0.1:1982/mock_zipkin",
"sample_ratio": 1
"endpoint": "http://127.0.0.1:1982/mock_zipkin?server_addr=127.0.0.1",
"sample_ratio": 1,
"service_name":"APISIX"
}
},
"upstream": {
Expand Down Expand Up @@ -316,3 +318,82 @@ GET /opentracing
opentracing
--- no_error_log
report2endpoint ok



=== TEST 11: set plugin with external ip address
--- 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:1982/mock_zipkin?server_addr=1.2.3.4",
"sample_ratio": 1,
"service_name": "apisix",
"server_addr": "1.2.3.4"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/opentracing"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
--- no_error_log
[error]



=== TEST 12: tiger zipkin
--- request
GET /opentracing
--- response_body
opentracing
--- grep_error_log eval
qr/\[info\].*/
--- grep_error_log_out eval
qr{report2endpoint ok}



=== TEST 13: sanity server_addr
--- config
location /t {
content_by_lua_block {
local plugin = require("apisix.plugins.zipkin")
local ok, err = plugin.check_schema({
endpoint = 'http://127.0.0.1',
sample_ratio = 0.001,
server_addr = 'badip'
})
if not ok then
ngx.say(err)
else
ngx.say("done")
end
}
}
--- request
GET /t
--- response_body
property "server_addr" validation failed: failed to match pattern "^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$" with "badip"
--- no_error_log
[error]