未验证 提交 e0c2e750 编写于 作者: G Gao Hongtao 提交者: GitHub

Adding HTTP client/server plugin (#9)

* Adding more unit test cases including

 * noop test
 * gRPC reporter test
 * tracer parameter test
 * and so on

* Add http plugin

* Add essentail tags

* Add component

* Add log reporter for examples

* Polish codes
上级 4b1487b6
......@@ -24,7 +24,8 @@ import (
)
func ExampleNewTracer() {
r, err := reporter.NewGRPCReporter("hello.com:11800")
// Use gRPC reporter for production
r, err := reporter.NewLogReporter()
if err != nil {
log.Fatalf("new reporter error %v \n", err)
}
......@@ -33,24 +34,25 @@ func ExampleNewTracer() {
if err != nil {
log.Fatalf("create tracer error %v \n", err)
}
// This for test
tracer.WaitUntilRegister()
span, ctx, err := tracer.CreateLocalSpan(context.Background())
if err != nil {
log.Fatalf("create new local span error %v \n", err)
}
span.SetOperationName("invoke data")
span.Tag("kind", "outer")
time.Sleep(2 * time.Second)
time.Sleep(time.Second)
subSpan, _, err := tracer.CreateLocalSpan(ctx)
if err != nil {
log.Fatalf("create new sub local span error %v \n", err)
}
subSpan.SetOperationName("invoke inner")
subSpan.Log(time.Now(), "inner", "this is right")
time.Sleep(2 * time.Second)
time.Sleep(time.Second)
subSpan.End()
time.Sleep(1 * time.Second)
time.Sleep(500 * time.Millisecond)
span.End()
time.Sleep(time.Minute)
//fmt.Print("aa")
// Output: aa
time.Sleep(time.Second)
// Output:
}
......@@ -32,7 +32,10 @@ func (*NoopSpan) SetPeer(string) {
func (*NoopSpan) SetSpanLayer(common.SpanLayer) {
}
func (*NoopSpan) Tag(string, string) {
func (*NoopSpan) SetComponent(int32) {
}
func (*NoopSpan) Tag(Tag, string) {
}
func (*NoopSpan) Log(time.Time, ...string) {
......
......@@ -110,6 +110,7 @@ func TestNoopMethod(t *testing.T) {
n.SetOperationName("aa")
n.SetPeer("localhost:1111")
n.SetSpanLayer(common.SpanLayer_Database)
n.SetComponent(2)
n.Tag("key", "value")
n.Log(time.Now(), "key", "value")
n.Error(time.Now(), "key", "value")
......
// Copyright 2019 Tetrate Labs
//
// Licensed 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.
package pkg
type Error string
func (e Error) Error() string {
return string(e)
}
// Copyright 2019 Tetrate Labs
//
// Licensed 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.
package http
import (
"net/http"
"strconv"
"time"
"github.com/tetratelabs/go2sky"
"github.com/tetratelabs/go2sky/propagation"
"github.com/tetratelabs/go2sky/reporter/grpc/common"
)
const httpClientComponentID int32 = 2
type ClientConfig struct {
name string
client *http.Client
tracer *go2sky.Tracer
extraTags map[string]string
}
// ClientOption allows optional configuration of Client.
type ClientOption func(*ClientConfig)
// WithOperationName override default operation name.
func WithClientOperationName(name string) ClientOption {
return func(c *ClientConfig) {
c.name = name
}
}
// WithClientTag adds extra tag to client spans.
func WithClientTag(key string, value string) ClientOption {
return func(c *ClientConfig) {
if c.extraTags == nil {
c.extraTags = make(map[string]string)
}
c.extraTags[key] = value
}
}
// WithClient set customer http client.
func WithClient(client *http.Client) ClientOption {
return func(c *ClientConfig) {
c.client = client
}
}
// NewClient returns an HTTP Client with tracer
func NewClient(tracer *go2sky.Tracer, options ...ClientOption) (*http.Client, error) {
if tracer == nil {
return nil, errInvalidTracer
}
co := &ClientConfig{tracer: tracer}
for _, option := range options {
option(co)
}
if co.client == nil {
co.client = &http.Client{}
}
tp := &transport{
ClientConfig: co,
delegated: http.DefaultTransport,
}
if co.client.Transport != nil {
tp.delegated = co.client.Transport
}
co.client.Transport = tp
return co.client, nil
}
type transport struct {
*ClientConfig
delegated http.RoundTripper
}
func (t *transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
span, err := t.tracer.CreateExitSpan(req.Context(), getOperationName(t.name, req), req.Host, func(header string) error {
req.Header.Set(propagation.Header, header)
return nil
})
if err != nil {
return t.delegated.RoundTrip(req)
}
defer span.End()
span.SetComponent(httpClientComponentID)
for k, v := range t.extraTags {
span.Tag(go2sky.Tag(k), v)
}
span.Tag(go2sky.TagHTTPMethod, req.Method)
span.Tag(go2sky.TagURL, req.URL.String())
span.SetSpanLayer(common.SpanLayer_Http)
res, err = t.delegated.RoundTrip(req)
if err != nil {
span.Error(time.Now(), err.Error())
return
}
span.Tag(go2sky.TagStatusCode, strconv.Itoa(res.StatusCode))
if res.StatusCode >= 400 {
span.Error(time.Now(), "Errors on handling client")
}
return res, nil
}
// Copyright 2019 Tetrate Labs
//
// Licensed 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.
package http
import (
"fmt"
"log"
"net/http"
"net/http/httptest"
"time"
"github.com/gorilla/mux"
"github.com/tetratelabs/go2sky"
"github.com/tetratelabs/go2sky/reporter"
)
func ExampleNewServerMiddleware() {
// Use gRPC reporter for production
r, err := reporter.NewLogReporter()
if err != nil {
log.Fatalf("new reporter error %v \n", err)
}
defer r.Close()
tracer, err := go2sky.NewTracer("example", go2sky.WithReporter(r))
if err != nil {
log.Fatalf("create tracer error %v \n", err)
}
tracer.WaitUntilRegister()
sm, err := NewServerMiddleware(tracer)
if err != nil {
log.Fatalf("create server middleware error %v \n", err)
}
client, err := NewClient(tracer)
if err != nil {
log.Fatalf("create client error %v \n", err)
}
router := mux.NewRouter()
// create test server
ts := httptest.NewServer(sm(router))
defer ts.Close()
// add handlers
router.Methods("GET").Path("/middle").HandlerFunc(middleFunc(client, ts.URL))
router.Methods("POST").Path("/end").HandlerFunc(endFunc())
// call end service
request, err := http.NewRequest("GET", fmt.Sprintf("%s/middle", ts.URL), nil)
if err != nil {
log.Fatalf("unable to create http request: %+v\n", err)
}
res, err := client.Do(request)
if err != nil {
log.Fatalf("unable to do http request: %+v\n", err)
}
_ = res.Body.Close()
time.Sleep(time.Second)
// Output:
}
func middleFunc(client *http.Client, url string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("middle func called with method: %s\n", r.Method)
// do some operation
time.Sleep(100 * time.Millisecond)
newRequest, err := http.NewRequest("POST", url+"/end", nil)
if err != nil {
log.Printf("unable to create client: %+v\n", err)
http.Error(w, err.Error(), 500)
return
}
//Link the context of entry and exit spans
newRequest = newRequest.WithContext(r.Context())
res, err := client.Do(newRequest)
if err != nil {
log.Printf("call to end fund returned error: %+v\n", err)
http.Error(w, err.Error(), 500)
return
}
_ = res.Body.Close()
}
}
func endFunc() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf("end func called with method: %s\n", r.Method)
time.Sleep(50 * time.Millisecond)
}
}
// Copyright 2019 Tetrate Labs
//
// Licensed 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.
package http
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/tetratelabs/go2sky"
"github.com/tetratelabs/go2sky/pkg"
"github.com/tetratelabs/go2sky/propagation"
"github.com/tetratelabs/go2sky/reporter/grpc/common"
)
const (
httpServerComponentID int32 = 49
errInvalidTracer = pkg.Error("invalid tracer")
)
type handler struct {
tracer *go2sky.Tracer
name string
next http.Handler
extraTags map[string]string
}
// ServerOption allows Middleware to be optionally configured.
type ServerOption func(*handler)
// Tag adds extra tag to server spans.
func WithServerTag(key string, value string) ServerOption {
return func(h *handler) {
if h.extraTags == nil {
h.extraTags = make(map[string]string)
}
h.extraTags[key] = value
}
}
// WithOperationName override default operation name.
func WithServerOperationName(name string) ServerOption {
return func(h *handler) {
h.name = name
}
}
// NewServerMiddleware returns a http.Handler middleware with tracing.
func NewServerMiddleware(tracer *go2sky.Tracer, options ...ServerOption) (func(http.Handler) http.Handler, error) {
if tracer == nil {
return nil, errInvalidTracer
}
return func(next http.Handler) http.Handler {
h := &handler{
tracer: tracer,
next: next,
}
for _, option := range options {
option(h)
}
return h
}, nil
}
// ServeHTTP implements http.Handler.
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
span, ctx, err := h.tracer.CreateEntrySpan(r.Context(), getOperationName(h.name, r), func() (string, error) {
return r.Header.Get(propagation.Header), nil
})
if err != nil {
h.next.ServeHTTP(w, r)
return
}
span.SetComponent(httpServerComponentID)
for k, v := range h.extraTags {
span.Tag(go2sky.Tag(k), v)
}
span.Tag(go2sky.TagHTTPMethod, r.Method)
span.Tag(go2sky.TagURL, fmt.Sprintf("%s%s", r.Host, r.URL.Path))
span.SetSpanLayer(common.SpanLayer_Http)
rww := &responseWriterWrapper{w: w, statusCode: 200}
defer func() {
code := rww.statusCode
if code >= 400 {
span.Error(time.Now(), "Error on handling request")
}
span.Tag(go2sky.TagStatusCode, strconv.Itoa(code))
span.End()
}()
h.next.ServeHTTP(rww, r.WithContext(ctx))
}
type responseWriterWrapper struct {
w http.ResponseWriter
statusCode int
}
func (rww *responseWriterWrapper) Header() http.Header {
return rww.w.Header()
}
func (rww *responseWriterWrapper) Write(bytes []byte) (int, error) {
return rww.w.Write(bytes)
}
func (rww *responseWriterWrapper) WriteHeader(statusCode int) {
rww.statusCode = statusCode
}
func getOperationName(name string, r *http.Request) string {
if name == "" {
return fmt.Sprintf("/%s%s", r.Method, r.URL.Path)
}
return name
}
......@@ -23,8 +23,11 @@ import (
"github.com/pkg/errors"
)
const splitToken string = "-"
const idToken string = "."
const (
Header string = "sw6"
splitToken string = "-"
idToken string = "."
)
var (
errEmptyHeader = errors.New("empty header")
......
......@@ -23,6 +23,7 @@ import (
"github.com/golang/protobuf/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"github.com/tetratelabs/go2sky"
"github.com/tetratelabs/go2sky/pkg"
......@@ -44,7 +45,7 @@ var (
// NewGRPCReporter create a new reporter to send data to gRPC oap server
func NewGRPCReporter(serverAddr string, opts ...GRPCReporterOption) (go2sky.Reporter, error) {
r := &gRPCReporter{
logger: log.New(os.Stderr, "go2sky", log.LstdFlags),
logger: log.New(os.Stderr, "go2sky-gRPC", log.LstdFlags),
sendCh: make(chan *common.UpstreamSegment, maxSendQueueSize),
pingInterval: defaultPingInterval,
}
......@@ -196,6 +197,7 @@ func (r *gRPCReporter) Send(spans []go2sky.ReportedSpan) {
IsError: s.IsError(),
Tags: s.Tags(),
Logs: s.Logs(),
ComponentId: s.ComponentID(),
}
srr := make([]*v2.SegmentReference, 0)
if i == (spanSize-1) && spanCtx.ParentSpanID > -1 {
......@@ -244,12 +246,6 @@ func (r *gRPCReporter) Send(spans []go2sky.ReportedSpan) {
func (r *gRPCReporter) Close() {
close(r.sendCh)
if r.conn != nil {
err := r.conn.Close()
if err != nil {
r.logger.Print(err)
}
}
}
func (r *gRPCReporter) initSendPipeline() {
......@@ -274,6 +270,12 @@ func (r *gRPCReporter) initSendPipeline() {
}
}
r.closeStream(stream)
if r.conn != nil {
if err := r.conn.Close(); err != nil {
r.logger.Print(err)
}
}
break
}
}()
}
......@@ -291,6 +293,9 @@ func (r *gRPCReporter) ping() {
}
go func() {
for {
if r.conn.GetState() == connectivity.Shutdown {
break
}
_, err := r.pingClient.DoPing(context.Background(), &register.ServiceInstancePingPkg{
Time: pkg.Millisecond(time.Now()),
ServiceInstanceId: r.instanceID,
......
// Copyright 2019 Tetrate Labs
//
// Licensed 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.
package reporter
import (
"encoding/json"
"log"
"os"
"github.com/tetratelabs/go2sky"
)
const (
mockServiceID = 1
mockInstanceID = 1
)
func NewLogReporter() (go2sky.Reporter, error) {
return &logReporter{logger: log.New(os.Stderr, "go2sky-log", log.LstdFlags)}, nil
}
type logReporter struct {
logger *log.Logger
}
func (lr *logReporter) Register(service string, instance string) (int32, int32, error) {
lr.logger.Println("Register log reporter")
// Mock register results for log reporter
return mockServiceID, mockInstanceID, nil
}
func (lr *logReporter) Send(spans []go2sky.ReportedSpan) {
if spans == nil {
return
}
b, err := json.Marshal(spans)
if err != nil {
lr.logger.Printf("Error: %s", err)
return
}
root := spans[len(spans)-1]
lr.logger.Printf("Segment-%v: %s \n", root.Context().SegmentID, b)
}
func (lr *logReporter) Close() {
lr.logger.Println("Close log reporter")
}
......@@ -64,6 +64,7 @@ type ReportedSpan interface {
IsError() bool
Tags() []*common.KeyStringValuePair
Logs() []*v2.Log
ComponentID() int32
}
type segmentSpan interface {
......@@ -97,39 +98,43 @@ func (s *segmentSpanImpl) Refs() []*propagation.SpanContext {
}
func (s *segmentSpanImpl) StartTime() int64 {
return pkg.Millisecond(s.startTime)
return pkg.Millisecond(s.defaultSpan.StartTime)
}
func (s *segmentSpanImpl) EndTime() int64 {
return pkg.Millisecond(s.endTime)
return pkg.Millisecond(s.defaultSpan.EndTime)
}
func (s *segmentSpanImpl) OperationName() string {
return s.operationName
return s.defaultSpan.OperationName
}
func (s *segmentSpanImpl) Peer() string {
return s.peer
return s.defaultSpan.Peer
}
func (s *segmentSpanImpl) SpanType() common.SpanType {
return common.SpanType(s.spanType)
return common.SpanType(s.defaultSpan.SpanType)
}
func (s *segmentSpanImpl) SpanLayer() common.SpanLayer {
return s.layer
return s.defaultSpan.Layer
}
func (s *segmentSpanImpl) IsError() bool {
return s.isError
return s.defaultSpan.IsError
}
func (s *segmentSpanImpl) Tags() []*common.KeyStringValuePair {
return s.tags
return s.defaultSpan.Tags
}
func (s *segmentSpanImpl) Logs() []*v2.Log {
return s.logs
return s.defaultSpan.Logs
}
func (s *segmentSpanImpl) ComponentID() int32 {
return s.defaultSpan.ComponentID
}
func (s *segmentSpanImpl) context() SegmentContext {
......
......@@ -41,7 +41,8 @@ type Span interface {
SetOperationName(string)
SetPeer(string)
SetSpanLayer(common.SpanLayer)
Tag(string, string)
SetComponent(int32)
Tag(Tag, string)
Log(time.Time, ...string)
Error(time.Time, ...string)
End()
......@@ -50,41 +51,46 @@ type Span interface {
func newLocalSpan(t *Tracer) *defaultSpan {
return &defaultSpan{
tracer: t,
startTime: time.Now(),
spanType: SpanTypeLocal,
StartTime: time.Now(),
SpanType: SpanTypeLocal,
}
}
type defaultSpan struct {
Refs []*propagation.SpanContext
tracer *Tracer
startTime time.Time
endTime time.Time
operationName string
peer string
layer common.SpanLayer
tags []*common.KeyStringValuePair
logs []*v2.Log
isError bool
spanType SpanType
StartTime time.Time
EndTime time.Time
OperationName string
Peer string
Layer common.SpanLayer
ComponentID int32
Tags []*common.KeyStringValuePair
Logs []*v2.Log
IsError bool
SpanType SpanType
}
// For Span
func (ds *defaultSpan) SetOperationName(name string) {
ds.operationName = name
ds.OperationName = name
}
func (ds *defaultSpan) SetPeer(peer string) {
ds.peer = peer
ds.Peer = peer
}
func (ds *defaultSpan) SetSpanLayer(layer common.SpanLayer) {
ds.layer = layer
ds.Layer = layer
}
func (ds *defaultSpan) Tag(key string, value string) {
ds.tags = append(ds.tags, &common.KeyStringValuePair{Key: key, Value: value})
func (ds *defaultSpan) SetComponent(componentID int32) {
ds.ComponentID = componentID
}
func (ds *defaultSpan) Tag(key Tag, value string) {
ds.Tags = append(ds.Tags, &common.KeyStringValuePair{Key: string(key), Value: value})
}
func (ds *defaultSpan) Log(time time.Time, ll ...string) {
......@@ -101,18 +107,36 @@ func (ds *defaultSpan) Log(time time.Time, ll ...string) {
}
}
}
ds.logs = append(ds.logs, &v2.Log{Time: pkg.Millisecond(time), Data: data})
ds.Logs = append(ds.Logs, &v2.Log{Time: pkg.Millisecond(time), Data: data})
}
func (ds *defaultSpan) Error(time time.Time, ll ...string) {
ds.isError = true
ds.IsError = true
ds.Log(time, ll...)
}
func (ds *defaultSpan) End() {
ds.endTime = time.Now()
ds.EndTime = time.Now()
}
// SpanOption allows for functional options to adjust behaviour
// of a Span to be created by CreateLocalSpan
type SpanOption func(s *defaultSpan)
// Tag are supported by sky-walking engine.
// As default, all Tags will be stored, but these ones have
// particular meanings.
type Tag string
const (
TagURL Tag = "url"
TagStatusCode Tag = "status_code"
TagHTTPMethod Tag = "http.method"
TagDBType Tag = "db.type"
TagDBInstance Tag = "db.instance"
TagDBStatement Tag = "db.statement"
TagDBBindVariables Tag = "db.bind_vars"
TagMQQueue Tag = "mq.queue"
TagMQBroker Tag = "mq.broker"
TagMQTopic Tag = "mq.topic"
)
......@@ -29,6 +29,6 @@ func WithContext(sc *propagation.SpanContext) SpanOption {
// WithSpanType setup span type of a span
func WithSpanType(spanType SpanType) SpanOption {
return func(s *defaultSpan) {
s.spanType = spanType
s.SpanType = spanType
}
}
......@@ -39,7 +39,7 @@ func Test_defaultSpan_SetOperationName(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ds := &defaultSpan{}
ds.SetOperationName(tt.args.name)
if ds.operationName != tt.args.name {
if ds.OperationName != tt.args.name {
t.Error("operation name is different")
}
})
......@@ -55,7 +55,7 @@ func Test_defaultSpan_SetPeer(t *testing.T) {
args args
}{
{
"set peer",
"set Peer",
struct{ name string }{name: "localhost:9999"},
},
}
......@@ -63,8 +63,8 @@ func Test_defaultSpan_SetPeer(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ds := &defaultSpan{}
ds.SetPeer(tt.args.name)
if ds.peer != tt.args.name {
t.Error("peer is different")
if ds.Peer != tt.args.name {
t.Error("Peer is different")
}
})
}
......@@ -107,8 +107,8 @@ func Test_defaultSpan_SetSpanLayer(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ds := &defaultSpan{}
ds.SetSpanLayer(tt.args.layer)
if ds.layer != tt.args.layer {
t.Error("span layer is different")
if ds.Layer != tt.args.layer {
t.Error("span Layer is different")
}
})
}
......@@ -116,7 +116,7 @@ func Test_defaultSpan_SetSpanLayer(t *testing.T) {
func Test_defaultSpan_Tag(t *testing.T) {
type args struct {
key string
key Tag
value string
}
tests := []struct {
......@@ -146,8 +146,8 @@ func Test_defaultSpan_Tag(t *testing.T) {
for _, a := range tt.args {
ds.Tag(a.key, a.value)
}
if len(ds.tags) != len(tt.args) {
t.Error("tags are not set property")
if len(ds.Tags) != len(tt.args) {
t.Error("Tags are not set property")
}
})
}
......@@ -159,19 +159,19 @@ func Test_defaultSpan_Log(t *testing.T) {
ll []string
}{
{
"set null logs",
"set null Logs",
[]string{},
},
{
"set logs",
"set Logs",
[]string{"name", "value", "name1", "value1"},
},
{
"set duplicated logs",
"set duplicated Logs",
[]string{"name", "value", "name1", "value1"},
},
{
"set invalid logs",
"set invalid Logs",
[]string{"name", "value", "name1"},
},
}
......@@ -179,12 +179,12 @@ func Test_defaultSpan_Log(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ds := &defaultSpan{}
ds.Log(time.Now(), tt.ll...)
if len(ds.logs) != 1 {
t.Error("logs are not set property")
if len(ds.Logs) != 1 {
t.Error("Logs are not set property")
}
for _, l := range ds.logs {
for _, l := range ds.Logs {
if len(l.Data) != int(math.Ceil(float64(len(tt.ll))/2)) {
t.Error("logs are not set property")
t.Error("Logs are not set property")
}
}
})
......@@ -213,13 +213,13 @@ func Test_defaultSpan_Error(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
ds := &defaultSpan{}
ds.Error(time.Now(), tt.ll...)
if !ds.isError {
if !ds.IsError {
t.Error("errors are not set property")
}
if len(ds.logs) != 1 {
if len(ds.Logs) != 1 {
t.Error("errors are not set property")
}
for _, l := range ds.logs {
for _, l := range ds.Logs {
if len(l.Data) != int(math.Ceil(float64(len(tt.ll))/2)) {
t.Error("errors are not set property")
}
......
......@@ -23,10 +23,11 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/tetratelabs/go2sky/pkg"
"github.com/tetratelabs/go2sky/propagation"
)
var errParameter = errors.New("parameter are nil")
const errParameter = pkg.Error("parameter are nil")
// Tracer is go2sky tracer implementation.
type Tracer struct {
......@@ -145,7 +146,7 @@ func (t *Tracer) CreateLocalSpan(ctx context.Context, opts ...SpanOption) (s Spa
if ctx == nil {
return nil, nil, errParameter
}
if s, _ = t.createNoop(ctx); s != nil {
if s, c = t.createNoop(ctx); s != nil {
return
}
ds := newLocalSpan(t)
......@@ -185,8 +186,9 @@ func (t *Tracer) CreateExitSpan(ctx context.Context, operationName string, peer
spanContext.ParentSegmentID = span.Context().SegmentID
spanContext.NetworkAddress = peer
spanContext.ParentServiceInstanceID = t.instanceID
// TODO confirm client
spanContext.EntryServiceInstanceID = t.instanceID
spanContext.EntryEndpoint = operationName
spanContext.ParentEndpoint = operationName
ref, ok := ctx.Value(refKeyInstance).(*propagation.SpanContext)
if ok && ref != nil {
spanContext.Sample = ref.Sample
......
......@@ -21,6 +21,7 @@ import (
"testing"
"github.com/pkg/errors"
"github.com/tetratelabs/go2sky/propagation"
)
......@@ -197,7 +198,7 @@ func TestTracer_CreateEntrySpan_Parameter(t *testing.T) {
true,
},
{
"operationName is nil",
"OperationName is nil",
struct {
ctx context.Context
operationName string
......@@ -301,7 +302,7 @@ func TestTracer_CreateExitSpan_Parameter(t *testing.T) {
true,
},
{
"operationName is nil",
"OperationName is nil",
struct {
ctx context.Context
operationName string
......@@ -313,7 +314,7 @@ func TestTracer_CreateExitSpan_Parameter(t *testing.T) {
true,
},
{
"peer is nil",
"Peer is nil",
struct {
ctx context.Context
operationName string
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册