123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- package trace
- import (
- "encoding/binary"
- "fmt"
- "math"
- "strconv"
- "time"
- "github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/ptypes/duration"
- "github.com/golang/protobuf/ptypes/timestamp"
- protogen "go-common/library/net/trace/proto"
- )
- const protoVersion2 int32 = 2
- func marshalSpan(sp *span, version int32) ([]byte, error) {
- if version == protoVersion2 {
- return marshalSpanV2(sp)
- }
- return marshalSpanV1(sp)
- }
- func marshalSpanV2(sp *span) ([]byte, error) {
- protoSpan := new(protogen.Span)
- protoSpan.Version = protoVersion2
- protoSpan.ServiceName = sp.dapper.serviceName
- protoSpan.OperationName = sp.operationName
- protoSpan.TraceId = sp.context.traceID
- protoSpan.SpanId = sp.context.spanID
- protoSpan.ParentId = sp.context.parentID
- protoSpan.SamplingProbability = sp.context.probability
- protoSpan.StartTime = ×tamp.Timestamp{
- Seconds: sp.startTime.Unix(),
- Nanos: int32(sp.startTime.Nanosecond()),
- }
- protoSpan.Duration = &duration.Duration{
- Seconds: int64(sp.duration / time.Second),
- Nanos: int32(sp.duration % time.Second),
- }
- protoSpan.Tags = make([]*protogen.Tag, len(sp.tags))
- for i := range sp.tags {
- protoSpan.Tags[i] = toProtoTag(sp.tags[i])
- }
- protoSpan.Logs = sp.logs
- return proto.Marshal(protoSpan)
- }
- func toLeagcyTag(tag Tag) *protogen.Tag {
- ptag := &protogen.Tag{Key: tag.Key}
- switch value := tag.Value.(type) {
- case string:
- ptag.Kind = protogen.Tag_STRING
- ptag.Value = []byte(value)
- case int:
- ptag.Kind = protogen.Tag_INT
- ptag.Value = []byte(strconv.FormatInt(int64(value), 10))
- case int32:
- ptag.Kind = protogen.Tag_INT
- ptag.Value = []byte(strconv.FormatInt(int64(value), 10))
- case int64:
- ptag.Kind = protogen.Tag_INT
- ptag.Value = []byte(strconv.FormatInt(value, 10))
- case bool:
- ptag.Kind = protogen.Tag_BOOL
- ptag.Value = []byte(strconv.FormatBool(value))
- case float32:
- ptag.Kind = protogen.Tag_BOOL
- ptag.Value = []byte(strconv.FormatFloat(float64(value), 'E', -1, 64))
- case float64:
- ptag.Kind = protogen.Tag_BOOL
- ptag.Value = []byte(strconv.FormatFloat(value, 'E', -1, 64))
- default:
- ptag.Kind = protogen.Tag_STRING
- ptag.Value = []byte((fmt.Sprintf("%v", tag.Value)))
- }
- return ptag
- }
- func toLeagcyLog(logs []*protogen.Log) []*protogen.Log {
- for _, log := range logs {
- if len(log.Fields) == 0 {
- continue
- }
- log.Key = log.Fields[0].Key
- log.Value = log.Fields[0].Value
- }
- return logs
- }
- func marshalSpanV1(sp *span) ([]byte, error) {
- protoSpan := new(protogen.Span)
- protoSpan.ServiceName = sp.dapper.serviceName
- protoSpan.OperationName = sp.operationName
- protoSpan.TraceId = sp.context.traceID
- protoSpan.SpanId = sp.context.spanID
- protoSpan.ParentId = sp.context.parentID
- protoSpan.SamplingProbability = sp.context.probability
- protoSpan.StartAt = sp.startTime.UnixNano()
- protoSpan.FinishAt = sp.startTime.UnixNano() + int64(sp.duration)
- protoSpan.Tags = make([]*protogen.Tag, len(sp.tags))
- for i := range sp.tags {
- protoSpan.Tags[i] = toLeagcyTag(sp.tags[i])
- }
- protoSpan.Logs = toLeagcyLog(sp.logs)
- return proto.Marshal(protoSpan)
- }
- func serializeInt64(v int64) []byte {
- data := make([]byte, 8)
- binary.BigEndian.PutUint64(data, uint64(v))
- return data
- }
- func serializeFloat64(v float64) []byte {
- data := make([]byte, 8)
- binary.BigEndian.PutUint64(data, math.Float64bits(v))
- return data
- }
- func serializeBool(v bool) []byte {
- data := make([]byte, 1)
- if v {
- data[0] = byte(1)
- } else {
- data[0] = byte(0)
- }
- return data
- }
- func toProtoTag(tag Tag) *protogen.Tag {
- ptag := &protogen.Tag{Key: tag.Key}
- switch value := tag.Value.(type) {
- case string:
- ptag.Kind = protogen.Tag_STRING
- ptag.Value = []byte(value)
- case int:
- ptag.Kind = protogen.Tag_INT
- ptag.Value = serializeInt64(int64(value))
- case int32:
- ptag.Kind = protogen.Tag_INT
- ptag.Value = serializeInt64(int64(value))
- case int64:
- ptag.Kind = protogen.Tag_INT
- ptag.Value = serializeInt64(value)
- case bool:
- ptag.Kind = protogen.Tag_BOOL
- ptag.Value = serializeBool(value)
- case float32:
- ptag.Kind = protogen.Tag_BOOL
- ptag.Value = serializeFloat64(float64(value))
- case float64:
- ptag.Kind = protogen.Tag_BOOL
- ptag.Value = serializeFloat64(value)
- default:
- ptag.Kind = protogen.Tag_STRING
- ptag.Value = []byte((fmt.Sprintf("%v", tag.Value)))
- }
- return ptag
- }
|