Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
227
plugins/inputs/zipkin/codec/codec.go
Normal file
227
plugins/inputs/zipkin/codec/codec.go
Normal file
|
@ -0,0 +1,227 @@
|
|||
package codec
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf/plugins/inputs/zipkin/codec/thrift/gen-go/zipkincore"
|
||||
"github.com/influxdata/telegraf/plugins/inputs/zipkin/trace"
|
||||
)
|
||||
|
||||
// now is a mockable time for now
|
||||
var now = time.Now
|
||||
|
||||
// DefaultServiceName when the span does not have any serviceName
|
||||
const DefaultServiceName = "unknown"
|
||||
|
||||
// Decoder decodes the bytes and returns a trace
|
||||
type Decoder interface {
|
||||
// Decode decodes the given byte slice into a slice of Spans.
|
||||
Decode(octets []byte) ([]Span, error)
|
||||
}
|
||||
|
||||
// Span represents a span created by instrumentation in RPC clients or servers.
|
||||
type Span interface {
|
||||
// Trace returns the trace ID of the span.
|
||||
Trace() (string, error)
|
||||
// SpanID returns the span ID.
|
||||
SpanID() (string, error)
|
||||
// Parent returns the parent span ID.
|
||||
Parent() (string, error)
|
||||
// Name returns the name of the span.
|
||||
Name() string
|
||||
// Annotations returns the annotations of the span.
|
||||
Annotations() []Annotation
|
||||
// BinaryAnnotations returns the binary annotations of the span.
|
||||
BinaryAnnotations() ([]BinaryAnnotation, error)
|
||||
// Timestamp returns the timestamp of the span.
|
||||
Timestamp() time.Time
|
||||
// Duration returns the duration of the span.
|
||||
Duration() time.Duration
|
||||
}
|
||||
|
||||
// Annotation represents an event that explains latency with a timestamp.
|
||||
type Annotation interface {
|
||||
// Timestamp returns the timestamp of the annotation.
|
||||
Timestamp() time.Time
|
||||
// Value returns the value of the annotation.
|
||||
Value() string
|
||||
// Host returns the endpoint associated with the annotation.
|
||||
Host() Endpoint
|
||||
}
|
||||
|
||||
// BinaryAnnotation represents tags applied to a Span to give it context.
|
||||
type BinaryAnnotation interface {
|
||||
// Key returns the key of the binary annotation.
|
||||
Key() string
|
||||
// Value returns the value of the binary annotation.
|
||||
Value() string
|
||||
// Host returns the endpoint associated with the binary annotation.
|
||||
Host() Endpoint
|
||||
}
|
||||
|
||||
// Endpoint represents the network context of a service recording an annotation.
|
||||
type Endpoint interface {
|
||||
// Host returns the host address of the endpoint.
|
||||
Host() string
|
||||
// Name returns the name of the service associated with the endpoint.
|
||||
Name() string
|
||||
}
|
||||
|
||||
// defaultEndpoint is used if the annotations have no endpoints.
|
||||
type defaultEndpoint struct{}
|
||||
|
||||
// Host returns 0.0.0.0; used when the host is unknown.
|
||||
func (*defaultEndpoint) Host() string { return "0.0.0.0" }
|
||||
|
||||
// Name returns "unknown" when an endpoint doesn't exist.
|
||||
func (*defaultEndpoint) Name() string { return DefaultServiceName }
|
||||
|
||||
// MicroToTime converts zipkin's native time of microseconds into time.Time.
|
||||
func MicroToTime(micro int64) time.Time {
|
||||
return time.Unix(0, micro*int64(time.Microsecond)).UTC()
|
||||
}
|
||||
|
||||
// NewTrace converts a slice of Spans into a new Trace.
|
||||
func NewTrace(spans []Span) (trace.Trace, error) {
|
||||
tr := make(trace.Trace, len(spans))
|
||||
for i, span := range spans {
|
||||
bin, err := span.BinaryAnnotations()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endpoint := serviceEndpoint(span.Annotations(), bin)
|
||||
id, err := span.SpanID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tid, err := span.Trace()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pid, err := parentID(span)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tr[i] = trace.Span{
|
||||
ID: id,
|
||||
TraceID: tid,
|
||||
Name: span.Name(),
|
||||
Timestamp: guessTimestamp(span),
|
||||
Duration: convertDuration(span),
|
||||
ParentID: pid,
|
||||
ServiceName: endpoint.Name(),
|
||||
Annotations: NewAnnotations(span.Annotations(), endpoint),
|
||||
BinaryAnnotations: NewBinaryAnnotations(bin, endpoint),
|
||||
}
|
||||
}
|
||||
return tr, nil
|
||||
}
|
||||
|
||||
// NewAnnotations converts a slice of Annotation into a slice of new Annotations
|
||||
func NewAnnotations(annotations []Annotation, endpoint Endpoint) []trace.Annotation {
|
||||
formatted := make([]trace.Annotation, 0, len(annotations))
|
||||
for _, annotation := range annotations {
|
||||
formatted = append(formatted, trace.Annotation{
|
||||
Host: endpoint.Host(),
|
||||
ServiceName: endpoint.Name(),
|
||||
Timestamp: annotation.Timestamp(),
|
||||
Value: annotation.Value(),
|
||||
})
|
||||
}
|
||||
|
||||
return formatted
|
||||
}
|
||||
|
||||
// NewBinaryAnnotations is very similar to NewAnnotations, but it
|
||||
// converts BinaryAnnotations instead of the normal Annotation
|
||||
func NewBinaryAnnotations(annotations []BinaryAnnotation, endpoint Endpoint) []trace.BinaryAnnotation {
|
||||
formatted := make([]trace.BinaryAnnotation, 0, len(annotations))
|
||||
for _, annotation := range annotations {
|
||||
formatted = append(formatted, trace.BinaryAnnotation{
|
||||
Host: endpoint.Host(),
|
||||
ServiceName: endpoint.Name(),
|
||||
Key: annotation.Key(),
|
||||
Value: annotation.Value(),
|
||||
})
|
||||
}
|
||||
return formatted
|
||||
}
|
||||
|
||||
func minMax(span Span) (low, high time.Time) {
|
||||
low = now().UTC()
|
||||
high = time.Time{}.UTC()
|
||||
for _, annotation := range span.Annotations() {
|
||||
ts := annotation.Timestamp()
|
||||
if !ts.IsZero() && ts.Before(low) {
|
||||
low = ts
|
||||
}
|
||||
if !ts.IsZero() && ts.After(high) {
|
||||
high = ts
|
||||
}
|
||||
}
|
||||
if high.IsZero() {
|
||||
high = low
|
||||
}
|
||||
return low, high
|
||||
}
|
||||
|
||||
func guessTimestamp(span Span) time.Time {
|
||||
ts := span.Timestamp()
|
||||
if !ts.IsZero() {
|
||||
return ts
|
||||
}
|
||||
|
||||
low, _ := minMax(span)
|
||||
return low
|
||||
}
|
||||
|
||||
func convertDuration(span Span) time.Duration {
|
||||
duration := span.Duration()
|
||||
if duration != 0 {
|
||||
return duration
|
||||
}
|
||||
low, high := minMax(span)
|
||||
return high.Sub(low)
|
||||
}
|
||||
|
||||
func parentID(span Span) (string, error) {
|
||||
// A parent ID of "" means that this is a parent span. In this case,
|
||||
// we set the parent ID of the span to be its own id, so it points to
|
||||
// itself.
|
||||
id, err := span.Parent()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if id != "" {
|
||||
return id, nil
|
||||
}
|
||||
return span.SpanID()
|
||||
}
|
||||
|
||||
func serviceEndpoint(ann []Annotation, bann []BinaryAnnotation) Endpoint {
|
||||
for _, a := range ann {
|
||||
switch a.Value() {
|
||||
case zipkincore.SERVER_RECV, zipkincore.SERVER_SEND, zipkincore.CLIENT_RECV, zipkincore.CLIENT_SEND:
|
||||
if a.Host() != nil && a.Host().Name() != "" {
|
||||
return a.Host()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, a := range bann {
|
||||
if a.Key() == zipkincore.LOCAL_COMPONENT && a.Host() != nil && a.Host().Name() != "" {
|
||||
return a.Host()
|
||||
}
|
||||
}
|
||||
// Unable to find any "standard" endpoint host, so, use any that exist in the regular annotations
|
||||
for _, a := range ann {
|
||||
if a.Host() != nil && a.Host().Name() != "" {
|
||||
return a.Host()
|
||||
}
|
||||
}
|
||||
return &defaultEndpoint{}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue