forked from kumahq/kuma
/
tracing.go
133 lines (122 loc) 路 4.34 KB
/
tracing.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package bootstrap
import (
net_url "net/url"
"strconv"
"time"
envoy_api "github.com/envoyproxy/go-control-plane/envoy/api/v2"
envoy_api_v2_core "github.com/envoyproxy/go-control-plane/envoy/api/v2/core"
envoy_api_v2_endpoint "github.com/envoyproxy/go-control-plane/envoy/api/v2/endpoint"
envoy_bootstrap "github.com/envoyproxy/go-control-plane/envoy/config/bootstrap/v2"
envoy_config_trace_v2 "github.com/envoyproxy/go-control-plane/envoy/config/trace/v2"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/duration"
structpb "github.com/golang/protobuf/ptypes/struct"
"github.com/pkg/errors"
mesh_proto "github.com/Kong/kuma/api/mesh/v1alpha1"
"github.com/Kong/kuma/pkg/util/proto"
)
func AddTracingConfig(bootstrap *envoy_bootstrap.Bootstrap, backend *mesh_proto.TracingBackend) error {
if backend.GetType() == mesh_proto.TracingZipkinType {
cluster, tracingCfg, err := zipkinConfig(bootstrap, backend.Conf, backend.Name)
if err != nil {
return err
}
if bootstrap.StaticResources == nil {
bootstrap.StaticResources = &envoy_bootstrap.Bootstrap_StaticResources{}
}
bootstrap.StaticResources.Clusters = append(bootstrap.StaticResources.Clusters, cluster)
bootstrap.Tracing = tracingCfg
}
return nil
}
func zipkinConfig(bootstrap *envoy_bootstrap.Bootstrap, cfgStr *structpb.Struct, backendName string) (*envoy_api.Cluster, *envoy_config_trace_v2.Tracing, error) {
cfg := mesh_proto.ZipkinTracingBackendConfig{}
if err := proto.ToTyped(cfgStr, &cfg); err != nil {
return nil, nil, errors.Wrap(err, "could not convert backend")
}
url, err := net_url.ParseRequestURI(cfg.Url)
if err != nil {
return nil, nil, errors.Wrap(err, "invalid URL of Zipkin")
}
cluster, err := zipkinCluster(backendName, url)
if err != nil {
return nil, nil, err
}
zipkinConfig := envoy_config_trace_v2.ZipkinConfig{
CollectorCluster: cluster.Name,
CollectorEndpoint: url.Path,
TraceId_128Bit: cfg.TraceId128Bit,
CollectorEndpointVersion: apiVersion(&cfg, url),
}
zipkinConfigAny, err := ptypes.MarshalAny(&zipkinConfig)
if err != nil {
return nil, nil, err
}
tracingConfig := &envoy_config_trace_v2.Tracing{
Http: &envoy_config_trace_v2.Tracing_Http{
Name: "envoy.zipkin",
ConfigType: &envoy_config_trace_v2.Tracing_Http_TypedConfig{
TypedConfig: zipkinConfigAny,
},
},
}
return cluster, tracingConfig, nil
}
func apiVersion(zipkin *mesh_proto.ZipkinTracingBackendConfig, url *net_url.URL) envoy_config_trace_v2.ZipkinConfig_CollectorEndpointVersion {
if zipkin.ApiVersion == "" { // try to infer it from the URL
if url.Path == "/api/v1/spans" {
return envoy_config_trace_v2.ZipkinConfig_HTTP_JSON_V1
} else if url.Path == "/api/v2/spans" {
return envoy_config_trace_v2.ZipkinConfig_HTTP_JSON
}
} else {
switch zipkin.ApiVersion {
case "httpJsonV1":
return envoy_config_trace_v2.ZipkinConfig_HTTP_JSON_V1
case "httpJson":
return envoy_config_trace_v2.ZipkinConfig_HTTP_JSON
case "httpProto":
return envoy_config_trace_v2.ZipkinConfig_HTTP_PROTO
}
}
return envoy_config_trace_v2.ZipkinConfig_HTTP_JSON
}
const zipkinClusterTimeout = 10 * time.Second
func zipkinCluster(backendName string, url *net_url.URL) (*envoy_api.Cluster, error) {
port, err := strconv.Atoi(url.Port())
if err != nil {
return nil, err
}
cluster := &envoy_api.Cluster{
Name: backendName,
ConnectTimeout: &duration.Duration{Seconds: int64(zipkinClusterTimeout.Seconds())},
ClusterDiscoveryType: &envoy_api.Cluster_Type{Type: envoy_api.Cluster_STRICT_DNS},
LbPolicy: envoy_api.Cluster_ROUND_ROBIN,
LoadAssignment: &envoy_api.ClusterLoadAssignment{
ClusterName: backendName,
Endpoints: []*envoy_api_v2_endpoint.LocalityLbEndpoints{
{
LbEndpoints: []*envoy_api_v2_endpoint.LbEndpoint{
{
HostIdentifier: &envoy_api_v2_endpoint.LbEndpoint_Endpoint{
Endpoint: &envoy_api_v2_endpoint.Endpoint{
Address: &envoy_api_v2_core.Address{
Address: &envoy_api_v2_core.Address_SocketAddress{
SocketAddress: &envoy_api_v2_core.SocketAddress{
Address: url.Hostname(),
PortSpecifier: &envoy_api_v2_core.SocketAddress_PortValue{
PortValue: uint32(port),
},
},
},
},
},
},
},
},
},
},
},
}
return cluster, nil
}