telegraf/plugins/inputs/zipkin/convert_test.go

545 lines
14 KiB
Go

package zipkin
import (
"reflect"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/testutil"
"github.com/openzipkin/zipkin-go-opentracing/_thrift/gen-go/zipkincore"
)
func TestLineProtocolConverter_Record(t *testing.T) {
mockAcc := testutil.Accumulator{}
type fields struct {
acc telegraf.Accumulator
}
type args struct {
t Trace
}
tests := []struct {
name string
fields fields
args args
wantErr bool
want []testutil.Metric
}{
{
name: "threespan",
fields: fields{
acc: &mockAcc,
},
args: args{
t: Trace{
Span{
ID: "8090652509916334619",
TraceID: "2505404965370368069",
Name: "Child",
ParentID: "22964302721410078",
Timestamp: time.Unix(0, 1498688360851331000).UTC(),
Duration: time.Duration(53106) * time.Microsecond,
ServiceName: "trivial",
Annotations: []Annotation{},
BinaryAnnotations: []BinaryAnnotation{
BinaryAnnotation{
Key: "lc",
Value: "dHJpdmlhbA==",
Host: "2130706433:0",
ServiceName: "trivial",
Type: "STRING",
},
},
},
Span{
ID: "103618986556047333",
TraceID: "2505404965370368069",
Name: "Child",
ParentID: "22964302721410078",
Timestamp: time.Unix(0, 1498688360904552000).UTC(),
Duration: time.Duration(50410) * time.Microsecond,
ServiceName: "trivial",
Annotations: []Annotation{},
BinaryAnnotations: []BinaryAnnotation{
BinaryAnnotation{
Key: "lc",
Value: "dHJpdmlhbA==",
Host: "2130706433:0",
ServiceName: "trivial",
Type: "STRING",
},
},
},
Span{
ID: "22964302721410078",
TraceID: "2505404965370368069",
Name: "Parent",
ParentID: "22964302721410078",
Timestamp: time.Unix(0, 1498688360851318000).UTC(),
Duration: time.Duration(103680) * time.Microsecond,
ServiceName: "trivial",
Annotations: []Annotation{
Annotation{
Timestamp: time.Unix(0, 1498688360851325000).UTC(),
Value: "Starting child #0",
Host: "2130706433:0",
ServiceName: "trivial",
},
Annotation{
Timestamp: time.Unix(0, 1498688360904545000).UTC(),
Value: "Starting child #1",
Host: "2130706433:0",
ServiceName: "trivial",
},
Annotation{
Timestamp: time.Unix(0, 1498688360954992000).UTC(),
Value: "A Log",
Host: "2130706433:0",
ServiceName: "trivial",
},
},
BinaryAnnotations: []BinaryAnnotation{
BinaryAnnotation{
Key: "lc",
Value: "dHJpdmlhbA==",
Host: "2130706433:0",
ServiceName: "trivial",
Type: "STRING",
},
},
},
},
},
want: []testutil.Metric{
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"id": "8090652509916334619",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"service_name": "trivial",
"name": "Child",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(53106) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851331000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"id": "8090652509916334619",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"name": "Child",
"service_name": "trivial",
"annotation": "dHJpdmlhbA==",
"endpoint_host": "2130706433:0",
"annotation_key": "lc",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(53106) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851331000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"id": "103618986556047333",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"service_name": "trivial",
"name": "Child",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(50410) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360904552000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"id": "103618986556047333",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"name": "Child",
"service_name": "trivial",
"annotation": "dHJpdmlhbA==",
"endpoint_host": "2130706433:0",
"annotation_key": "lc",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(50410) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360904552000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"id": "22964302721410078",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"service_name": "trivial",
"name": "Parent",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(103680) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851318000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"service_name": "trivial",
"annotation": "Starting child #0",
"endpoint_host": "2130706433:0",
"id": "22964302721410078",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"name": "Parent",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(103680) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851318000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"service_name": "trivial",
"annotation": "Starting child #1",
"endpoint_host": "2130706433:0",
"id": "22964302721410078",
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"name": "Parent",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(103680) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851318000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"parent_id": "22964302721410078",
"trace_id": "2505404965370368069",
"name": "Parent",
"service_name": "trivial",
"annotation": "A Log",
"endpoint_host": "2130706433:0",
"id": "22964302721410078",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(103680) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851318000).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"trace_id": "2505404965370368069",
"service_name": "trivial",
"annotation": "dHJpdmlhbA==",
"annotation_key": "lc",
"id": "22964302721410078",
"parent_id": "22964302721410078",
"name": "Parent",
"endpoint_host": "2130706433:0",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(103680) * time.Microsecond).Nanoseconds(),
},
Time: time.Unix(0, 1498688360851318000).UTC(),
},
},
wantErr: false,
},
//// Test data from distributed trace repo sample json
// https://github.com/mattkanwisher/distributedtrace/blob/master/testclient/sample.json
{
name: "distributed_trace_sample",
fields: fields{
acc: &mockAcc,
},
args: args{
t: Trace{
Span{
ID: "6802735349851856000",
TraceID: "0:6802735349851856000",
Name: "main.dud",
ParentID: "6802735349851856000",
Timestamp: time.Unix(1, 0).UTC(),
Duration: 1,
ServiceName: "trivial",
Annotations: []Annotation{
Annotation{
Timestamp: time.Unix(0, 1433330263415871000).UTC(),
Value: "cs",
Host: "0:9410",
ServiceName: "go-zipkin-testclient",
},
},
BinaryAnnotations: []BinaryAnnotation{},
},
},
},
want: []testutil.Metric{
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"id": "6802735349851856000",
"parent_id": "6802735349851856000",
"trace_id": "0:6802735349851856000",
"name": "main.dud",
"service_name": "trivial",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(1) * time.Nanosecond).Nanoseconds(),
},
Time: time.Unix(1, 0).UTC(),
},
testutil.Metric{
Measurement: "zipkin",
Tags: map[string]string{
"annotation": "cs",
"endpoint_host": "0:9410",
"id": "6802735349851856000",
"parent_id": "6802735349851856000",
"trace_id": "0:6802735349851856000",
"name": "main.dud",
"service_name": "go-zipkin-testclient",
},
Fields: map[string]interface{}{
"duration_ns": (time.Duration(1) * time.Nanosecond).Nanoseconds(),
},
Time: time.Unix(1, 0).UTC(),
},
},
},
}
for i, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockAcc.ClearMetrics()
l := &LineProtocolConverter{
acc: tt.fields.acc,
}
if err := l.Record(tt.args.t); (err != nil) != tt.wantErr {
t.Errorf("LineProtocolConverter.Record() error = %v, wantErr %v", err, tt.wantErr)
}
got := []testutil.Metric{}
for _, metric := range mockAcc.Metrics {
got = append(got, *metric)
}
if !cmp.Equal(got, tt.want) {
t.Errorf("LineProtocolConverter.Record()/%s/%d error = %s ", tt.name, i, cmp.Diff(got, tt.want))
}
})
}
}
func Test_microToTime(t *testing.T) {
type args struct {
micro int64
}
tests := []struct {
name string
args args
want time.Time
}{
{
name: "given zero micro seconds expected unix time zero",
args: args{
micro: 0,
},
want: time.Unix(0, 0).UTC(),
},
{
name: "given a million micro seconds expected unix time one",
args: args{
micro: 1000000,
},
want: time.Unix(1, 0).UTC(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := microToTime(tt.args.micro); !reflect.DeepEqual(got, tt.want) {
t.Errorf("microToTime() = %v, want %v", got, tt.want)
}
})
}
}
func newAnnotation(micro int64) *zipkincore.Annotation {
return &zipkincore.Annotation{
Timestamp: micro,
}
}
func Test_minMax(t *testing.T) {
type args struct {
span *zipkincore.Span
}
tests := []struct {
name string
args args
now func() time.Time
wantMin time.Time
wantMax time.Time
}{
{
name: "Single annotation",
args: args{
span: &zipkincore.Span{
Annotations: []*zipkincore.Annotation{
newAnnotation(1000000),
},
},
},
wantMin: time.Unix(1, 0).UTC(),
wantMax: time.Unix(1, 0).UTC(),
},
{
name: "Three annotations",
args: args{
span: &zipkincore.Span{
Annotations: []*zipkincore.Annotation{
newAnnotation(1000000),
newAnnotation(2000000),
newAnnotation(3000000),
},
},
},
wantMin: time.Unix(1, 0).UTC(),
wantMax: time.Unix(3, 0).UTC(),
},
{
name: "Annotations are in the future",
args: args{
span: &zipkincore.Span{
Annotations: []*zipkincore.Annotation{
newAnnotation(3000000),
},
},
},
wantMin: time.Unix(2, 0).UTC(),
wantMax: time.Unix(3, 0).UTC(),
now: func() time.Time {
return time.Unix(2, 0).UTC()
},
},
{
name: "No Annotations",
args: args{
span: &zipkincore.Span{
Annotations: []*zipkincore.Annotation{},
},
},
wantMin: time.Unix(2, 0).UTC(),
wantMax: time.Unix(2, 0).UTC(),
now: func() time.Time {
return time.Unix(2, 0).UTC()
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.now != nil {
now = tt.now
}
got, got1 := minMax(tt.args.span)
if !reflect.DeepEqual(got, tt.wantMin) {
t.Errorf("minMax() got = %v, want %v", got, tt.wantMin)
}
if !reflect.DeepEqual(got1, tt.wantMax) {
t.Errorf("minMax() got1 = %v, want %v", got1, tt.wantMax)
}
now = time.Now
})
}
}
func Test_host(t *testing.T) {
type args struct {
h *zipkincore.Endpoint
}
tests := []struct {
name string
args args
want string
}{
{
name: "Host Found",
args: args{
h: &zipkincore.Endpoint{
Ipv4: 1234,
Port: 8888,
},
},
want: "0.0.4.210:8888",
},
{
name: "No Host",
args: args{
h: nil,
},
want: "0.0.0.0",
},
{
name: "int overflow zipkin uses an int16 type as an unsigned int 16.",
args: args{
h: &zipkincore.Endpoint{
Ipv4: 1234,
Port: -1,
},
},
want: "0.0.4.210:65535",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := host(tt.args.h); got != tt.want {
t.Errorf("host() = %v, want %v", got, tt.want)
}
})
}
}
func Test_serviceName(t *testing.T) {
type args struct {
h *zipkincore.Endpoint
}
tests := []struct {
name string
args args
want string
}{
{
name: "Found ServiceName",
args: args{
h: &zipkincore.Endpoint{
ServiceName: "zipkin",
},
},
want: "zipkin",
},
{
name: "No ServiceName",
args: args{
h: nil,
},
want: "unknown",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := serviceName(tt.args.h); got != tt.want {
t.Errorf("serviceName() = %v, want %v", got, tt.want)
}
})
}
}