165 lines
4.5 KiB
Go
165 lines
4.5 KiB
Go
|
/*
|
||
|
* Copyright 2018 Expedia Group.
|
||
|
*
|
||
|
* 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 haystack
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"time"
|
||
|
|
||
|
"github.com/opentracing/opentracing-go"
|
||
|
"github.com/opentracing/opentracing-go/log"
|
||
|
)
|
||
|
|
||
|
/*_Span implements opentracing.Span*/
|
||
|
type _Span struct {
|
||
|
tracer *Tracer
|
||
|
context *SpanContext
|
||
|
|
||
|
operationName string
|
||
|
|
||
|
// startTime is the timestamp indicating when the span began, with microseconds precision.
|
||
|
startTime time.Time
|
||
|
// duration returns duration of the span with microseconds precision.
|
||
|
duration time.Duration
|
||
|
|
||
|
tags []opentracing.Tag
|
||
|
logs []opentracing.LogRecord
|
||
|
}
|
||
|
|
||
|
// SetOperationName sets or changes the operation name.
|
||
|
func (span *_Span) SetOperationName(operationName string) opentracing.Span {
|
||
|
span.operationName = operationName
|
||
|
return span
|
||
|
}
|
||
|
|
||
|
// SetTag implements SetTag() of opentracing.Span
|
||
|
func (span *_Span) SetTag(key string, value interface{}) opentracing.Span {
|
||
|
span.tags = append(span.tags,
|
||
|
opentracing.Tag{
|
||
|
Key: key,
|
||
|
Value: value,
|
||
|
})
|
||
|
return span
|
||
|
}
|
||
|
|
||
|
// LogFields implements opentracing.Span API
|
||
|
func (span *_Span) LogFields(fields ...log.Field) {
|
||
|
log := opentracing.LogRecord{
|
||
|
Fields: fields,
|
||
|
Timestamp: time.Now(),
|
||
|
}
|
||
|
span.logs = append(span.logs, log)
|
||
|
}
|
||
|
|
||
|
// LogKV implements opentracing.Span API
|
||
|
func (span *_Span) LogKV(alternatingKeyValues ...interface{}) {
|
||
|
fields, err := log.InterleavedKVToFields(alternatingKeyValues...)
|
||
|
if err != nil {
|
||
|
span.LogFields(log.Error(err), log.String("function", "LogKV"))
|
||
|
return
|
||
|
}
|
||
|
span.LogFields(fields...)
|
||
|
}
|
||
|
|
||
|
// LogEvent implements opentracing.Span API
|
||
|
func (span *_Span) LogEvent(event string) {
|
||
|
span.Log(opentracing.LogData{Event: event})
|
||
|
}
|
||
|
|
||
|
// LogEventWithPayload implements opentracing.Span API
|
||
|
func (span *_Span) LogEventWithPayload(event string, payload interface{}) {
|
||
|
span.Log(opentracing.LogData{Event: event, Payload: payload})
|
||
|
}
|
||
|
|
||
|
// Log implements opentracing.Span API
|
||
|
func (span *_Span) Log(ld opentracing.LogData) {
|
||
|
span.logs = append(span.logs, ld.ToLogRecord())
|
||
|
}
|
||
|
|
||
|
// SetBaggageItem implements SetBaggageItem() of opentracing.SpanContext
|
||
|
func (span *_Span) SetBaggageItem(key, value string) opentracing.Span {
|
||
|
span.context = span.context.WithBaggageItem(key, value)
|
||
|
span.LogFields(log.String("event", "baggage"), log.String("payload", key), log.String("payload", value))
|
||
|
return span
|
||
|
}
|
||
|
|
||
|
// BaggageItem implements BaggageItem() of opentracing.SpanContext
|
||
|
func (span *_Span) BaggageItem(key string) string {
|
||
|
return span.context.Baggage[key]
|
||
|
}
|
||
|
|
||
|
// Finish implements opentracing.Span API
|
||
|
func (span *_Span) Finish() {
|
||
|
span.FinishWithOptions(opentracing.FinishOptions{})
|
||
|
}
|
||
|
|
||
|
// FinishWithOptions implements opentracing.Span API
|
||
|
func (span *_Span) FinishWithOptions(options opentracing.FinishOptions) {
|
||
|
if options.FinishTime.IsZero() {
|
||
|
options.FinishTime = span.tracer.timeNow()
|
||
|
}
|
||
|
span.duration = options.FinishTime.Sub(span.startTime)
|
||
|
if options.LogRecords != nil {
|
||
|
span.logs = append(span.logs, options.LogRecords...)
|
||
|
}
|
||
|
for _, ld := range options.BulkLogData {
|
||
|
span.logs = append(span.logs, ld.ToLogRecord())
|
||
|
}
|
||
|
span.tracer.DispatchSpan(span)
|
||
|
}
|
||
|
|
||
|
// Context implements opentracing.Span API
|
||
|
func (span *_Span) Context() opentracing.SpanContext {
|
||
|
return span.context
|
||
|
}
|
||
|
|
||
|
/*Tracer returns the tracer*/
|
||
|
func (span *_Span) Tracer() opentracing.Tracer {
|
||
|
return span.tracer
|
||
|
}
|
||
|
|
||
|
/*OperationName allows retrieving current operation name*/
|
||
|
func (span *_Span) OperationName() string {
|
||
|
return span.operationName
|
||
|
}
|
||
|
|
||
|
/*ServiceName returns the name of the service*/
|
||
|
func (span *_Span) ServiceName() string {
|
||
|
return span.tracer.serviceName
|
||
|
}
|
||
|
|
||
|
func (span *_Span) String() string {
|
||
|
data, err := json.Marshal(map[string]interface{}{
|
||
|
"traceId": span.context.TraceID,
|
||
|
"spanId": span.context.SpanID,
|
||
|
"parentSpanId": span.context.ParentID,
|
||
|
"operationName": span.OperationName(),
|
||
|
"serviceName": span.ServiceName(),
|
||
|
"tags": span.Tags(),
|
||
|
"logs": span.logs,
|
||
|
})
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return string(data)
|
||
|
}
|
||
|
|
||
|
func (span *_Span) Tags() []opentracing.Tag {
|
||
|
return span.tags
|
||
|
}
|