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

refactor span verifiers and fix db attributes verifier ut #244

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,9 @@ github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/elastic/elastic-transport-go/v8 v8.0.0-alpha h1:SW9xcMVxx4Nv9oRm5rQxzAMAatwiZV8xROP2a48y45Q=
github.com/elastic/elastic-transport-go/v8 v8.0.0-alpha/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI=
github.com/elastic/elastic-transport-go/v8 v8.1.0 h1:NeqEz1ty4RQz+TVbUrpSU7pZ48XkzGWQj02k5koahIE=
github.com/elastic/elastic-transport-go/v8 v8.1.0/go.mod h1:87Tcz8IVNe6rVSLdBux1o/PEItLtyabHU3naC7IoqKI=
github.com/elastic/go-elasticsearch/v8 v8.0.0 h1:Hte+pgoEZI88j/sQx7u9vK9SqisvJYkYMmxDnQXiJyM=
github.com/elastic/go-elasticsearch/v8 v8.0.0/go.mod h1:8NCWP26meGbncX+R9sxo2JD8IqBjRTuS7yXMstHpd40=
github.com/elastic/go-elasticsearch/v8 v8.4.0 h1:Rn1mcqaIMcNT43hnx2H62cIFZ+B6mjWtzj85BDKrvCE=
github.com/elastic/go-elasticsearch/v8 v8.4.0/go.mod h1:yY52i2Vj0unLz+N3Nwx1gM5LXwoj3h2dgptNGBYkMLA=
github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les=
github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8=
Expand Down
37 changes: 13 additions & 24 deletions test/kratos/v2.6.3/test_kratos_grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,18 @@ func main() {
fmt.Printf("[grpc] SayHello %+v\n", reply)

verifier.WaitAndAssertTraces(func(stubs []tracetest.SpanStubs) {
protocolType := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.protocol.type").AsString()
if protocolType != "grpc" {
panic("protocol type should be grpc, actually got " + protocolType)
}
serviceName := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.name").AsString()
if serviceName != "opentelemetry-kratos-server" {
panic("service name should be opentelemetry-kratos-server, actually got " + serviceName)
}
serviceId := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.id").AsString()
if serviceId != "opentelemetry-id" {
panic("service id should be opentelemetry-id, actually got " + serviceId)
}
serviceVersion := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.version").AsString()
if serviceVersion != "v1" {
panic("service version should be v1, actually got " + serviceVersion)
}
serviceMetaAgent := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.meta.agent").AsString()
if serviceMetaAgent != "opentelemetry-go" {
panic("service meta agent should be opentelemetry-go, actually got " + serviceMetaAgent)
}
serviceEndpoint := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.endpoint").AsStringSlice()
if !strings.Contains(serviceEndpoint[0], ":9000") || !strings.Contains(serviceEndpoint[1], ":8000") {
panic("service endpoint should be grpc://30.221.144.142:9000 http://30.221.144.142:8000, actually got " + fmt.Sprintf("%v", serviceEndpoint))
}
verifier.NewSpanVerifier().
HasStringAttribute("kratos.protocol.type", "grpc").
HasStringAttribute("kratos.service.name", "opentelemetry-kratos-server").
HasStringAttribute("kratos.service.id", "opentelemetry-id").
HasStringAttribute("kratos.service.version", "v1").
HasStringAttribute("kratos.service.meta.agent", "opentelemetry-go").
HasItemInStringSliceAttribute("kratos.service.endpoint", 0, func(s string) (bool, string) {
return strings.Contains(s, ":9000"), fmt.Sprintf("First endpoint should be xxx:9000, actual value: %v", s)
}).
HasItemInStringSliceAttribute("kratos.service.endpoint", 1, func(s string) (bool, string) {
return strings.Contains(s, ":8000"), fmt.Sprintf("First endpoint should be xxx:8000, actual value: %v", s)
}).
Verify(stubs[0][2])
}, 1)
}
38 changes: 14 additions & 24 deletions test/kratos/v2.6.3/test_kratos_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,19 @@ func main() {
}
println()
}
protocolType := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.protocol.type").AsString()
if protocolType != "http" {
panic("protocol type should be http, actually got " + protocolType)
}
serviceName := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.name").AsString()
if serviceName != "opentelemetry-kratos-server" {
panic("service name should be opentelemetry-kratos-server, actually got " + serviceName)
}
serviceId := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.id").AsString()
if serviceId != "opentelemetry-id" {
panic("service id should be opentelemetry-id, actually got " + serviceId)
}
serviceVersion := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.version").AsString()
if serviceVersion != "v1" {
panic("service version should be v1, actually got " + serviceVersion)
}
serviceMetaAgent := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.meta.agent").AsString()
if serviceMetaAgent != "opentelemetry-go" {
panic("service meta agent should be opentelemetry-go, actually got " + serviceMetaAgent)
}
serviceEndpoint := verifier.GetAttribute(stubs[0][2].Attributes, "kratos.service.endpoint").AsStringSlice()
if !strings.Contains(serviceEndpoint[0], ":9000") || !strings.Contains(serviceEndpoint[1], ":8000") {
panic("service endpoint should be grpc://30.221.144.142:9000 http://30.221.144.142:8000, actually got " + fmt.Sprintf("%v", serviceEndpoint))
}

verifier.NewSpanVerifier().
HasStringAttribute("kratos.protocol.type", "http").
HasStringAttribute("kratos.service.name", "opentelemetry-kratos-server").
HasStringAttribute("kratos.service.id", "opentelemetry-id").
HasStringAttribute("kratos.service.version", "v1").
HasStringAttribute("kratos.service.meta.agent", "opentelemetry-go").
HasItemInStringSliceAttribute("kratos.service.endpoint", 0, func(s string) (bool, string) {
return strings.Contains(s, ":9000"), fmt.Sprintf("First endpoint should be xxx:9000, actual value: %v", s)
}).
HasItemInStringSliceAttribute("kratos.service.endpoint", 1, func(s string) (bool, string) {
return strings.Contains(s, ":8000"), fmt.Sprintf("First endpoint should be xxx:8000, actual value: %v", s)
}).
Verify(stubs[0][2])
}, 1)
}
235 changes: 235 additions & 0 deletions test/verifier/span_verifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package verifier

import (
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"go.opentelemetry.io/otel/trace"
"sort"
"strings"
)

type SpanVerifier struct {
verifiers []func(tracetest.SpanStub)
conditionalVerifiers []conditionalVerifier
}

func NewSpanVerifier() *SpanVerifier {
return &SpanVerifier{
verifiers: make([]func(tracetest.SpanStub), 0),
}
}

func (sv *SpanVerifier) Verify(span tracetest.SpanStub) {
for _, verifier := range sv.verifiers {
verifier(span)
}
for _, cv := range sv.conditionalVerifiers {
cv.Verify(span)
}
}

func (sv *SpanVerifier) HasSpanKind(kind trace.SpanKind) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
Assert(kind == span.SpanKind, "Failed to verify span kind, expect value: %v, actual value: %v", kind, span.SpanKind)
})
return sv
}

func (sv *SpanVerifier) HasName(name string) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
Assert(name == span.Name, "Failed to verify span name, expect value: %v, actual value: %v", name, span.Name)
})
return sv
}

func (sv *SpanVerifier) HasNoParent() *SpanVerifier {
noopSpanId := trace.SpanID{}.String()
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
Assert(span.Parent.SpanID().String() == noopSpanId, "Failed to verify parent span, expect value: %v, actual value: %v", trace.SpanID{}.String(), span.Parent.SpanID().String())
})
return sv
}

func (sv *SpanVerifier) HasParent(parentSpan tracetest.SpanStub) *SpanVerifier {
pTraceId := parentSpan.SpanContext.TraceID().String()
pSpanId := parentSpan.SpanContext.SpanID().String()
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
Assert(span.SpanContext.TraceID().String() == pTraceId, "Failed to verify parent trace id, expect value: %v, actual value: %v", pTraceId, span.SpanContext.TraceID().String())
Assert(span.Parent.SpanID().String() == pSpanId, "Failed to verify parent span id, expect value: %v, actual value: %v", pSpanId, span.Parent.SpanID().String())
})
return sv
}

func (sv *SpanVerifier) HasBoolAttribute(key string, value bool) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, value)
v := attr.AsBool()
Assert(value == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, value, v)
})
return sv
}

func (sv *SpanVerifier) HasInt64Attribute(key string, value int64) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, value)
v := attr.AsInt64()
Assert(value == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, value, v)
})
return sv
}

func (sv *SpanVerifier) HasFloat64Attribute(key string, value float64) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, value)
v := attr.AsFloat64()
Assert(value == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, value, v)
})
return sv
}

func (sv *SpanVerifier) HasStringAttribute(key string, value string) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, value)
v := attr.AsString()
Assert(value == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, value, v)
})
return sv
}

func (sv *SpanVerifier) HasStringAttributeContains(key string, value string) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value contains: %v, actual value: <unset>", key, value)
v := attr.AsString()
Assert(strings.Contains(v, value), "Failed to verify attribute of %v, expect value contains: %v, actual value: %v", key, value, v)
})
return sv
}

func (sv *SpanVerifier) HasBoolSliceAttribute(key string, values []bool, ignoreOrder bool) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, values)
vs := attr.AsBoolSlice()
Assert(len(values) == len(vs), "Failed to verify attribute of %v, expect length: %v, actual length: %v", key, len(values), len(vs))
if ignoreOrder {
ac := 0
ec := 0
for i, v := range vs {
if v {
ac++
}
if values[i] {
ec++
}
}
Assert(ac == ec, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, values, vs)
} else {
for i, v := range vs {
Assert(values[i] == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, values, vs)
}
}
})
return sv
}

func (sv *SpanVerifier) HasInt64SliceAttribute(key string, values []int64, ignoreOrder bool) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, values)
vs := attr.AsInt64Slice()
Assert(len(values) == len(vs), "Failed to verify attribute of %v, expect length: %v, actual length: %v", key, len(values), len(vs))
if ignoreOrder {
sort.Slice(values, func(i, j int) bool {
return values[i] < values[j]
})
sort.Slice(vs, func(i, j int) bool {
return vs[i] < vs[j]
})
}
for i, v := range vs {
Assert(values[i] == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, values, vs)
}
})
return sv
}

func (sv *SpanVerifier) HasFloat64SliceAttribute(key string, values []float64, ignoreOrder bool) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, values)
vs := attr.AsFloat64Slice()
Assert(len(values) == len(vs), "Failed to verify attribute of %v, expect length: %v, actual length: %v", key, len(values), len(vs))
if ignoreOrder {
sort.Slice(values, func(i, j int) bool {
return values[i] < values[j]
})
sort.Slice(vs, func(i, j int) bool {
return vs[i] < vs[j]
})
}
for i, v := range vs {
Assert(values[i] == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, values, vs)
}
})
return sv
}

func (sv *SpanVerifier) HasStringSliceAttribute(key string, values []string, ignoreOrder bool) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v, expect value: %v, actual value: <unset>", key, values)
vs := attr.AsStringSlice()
Assert(len(values) == len(vs), "Failed to verify attribute of %v, expect length: %v, actual length: %v", key, len(values), len(vs))
if ignoreOrder {
sort.Strings(values)
sort.Strings(vs)
}
for i, v := range vs {
Assert(values[i] == v, "Failed to verify attribute of %v, expect value: %v, actual value: %v", key, values, vs)
}
})
return sv
}

func (sv *SpanVerifier) HasItemInStringSliceAttribute(key string, index int, predicate func(string) (bool, string)) *SpanVerifier {
sv.verifiers = append(sv.verifiers, func(span tracetest.SpanStub) {
attr := GetAttribute(span.Attributes, key)
Assert(!IsAttributeNoop(attr), "Failed to verify attribute of %v[%v], actual value: <unset>", key, index)
vs := attr.AsStringSlice()
Assert(len(vs) > index, "Failed to verify attribute of %v[%v], cause index out of bound, actual length: %v", key, index, len(vs))
result, message := predicate(vs[index])
Assert(result, message)
})
return sv
}

func (sv *SpanVerifier) ConditionalVerifier(predicate func() bool, verifier *SpanVerifier) *SpanVerifier {
sv.conditionalVerifiers = append(sv.conditionalVerifiers, conditionalVerifier{
predicate: predicate,
SpanVerifier: verifier,
})
return sv
}

func (sv *SpanVerifier) Merge(verifier *SpanVerifier) *SpanVerifier {
if verifier != nil {
sv.verifiers = append(sv.verifiers, verifier.verifiers...)
sv.conditionalVerifiers = append(sv.conditionalVerifiers, verifier.conditionalVerifiers...)
}
return sv
}

type conditionalVerifier struct {
*SpanVerifier
predicate func() bool
}

func (cv *conditionalVerifier) Verify(span tracetest.SpanStub) {
if cv.predicate() {
cv.SpanVerifier.Verify(span)
}
}
Loading
Loading