mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-22 14:56:56 +00:00
Add OpenTracing support to TimeRequestHistogram (#2023)
* Vendor open tracing * Extend TimeRequestHistorgram to also emit opentracing spans. * Update some of the labels
This commit is contained in:
@@ -91,7 +91,7 @@ type AWSCollector interface {
|
||||
|
||||
// ReportStore is a thing that we can get reports from.
|
||||
type ReportStore interface {
|
||||
FetchReports([]string) (map[string]report.Report, []string, error)
|
||||
FetchReports(context.Context, []string) (map[string]report.Report, []string, error)
|
||||
}
|
||||
|
||||
// AWSCollectorConfig has everything we need to make an AWS collector.
|
||||
@@ -215,10 +215,10 @@ func (c *awsCollector) CreateTables() error {
|
||||
}
|
||||
|
||||
// getReportKeys gets the s3 keys for reports in this range
|
||||
func (c *awsCollector) getReportKeys(userid string, row int64, start, end time.Time) ([]string, error) {
|
||||
func (c *awsCollector) getReportKeys(ctx context.Context, userid string, row int64, start, end time.Time) ([]string, error) {
|
||||
rowKey := fmt.Sprintf("%s-%s", userid, strconv.FormatInt(row, 10))
|
||||
var resp *dynamodb.QueryOutput
|
||||
err := instrument.TimeRequestHistogram("Query", dynamoRequestDuration, func() error {
|
||||
err := instrument.TimeRequestHistogram(ctx, "DynamoDB.Query", dynamoRequestDuration, func(_ context.Context) error {
|
||||
var err error
|
||||
resp, err = c.db.Query(&dynamodb.QueryInput{
|
||||
TableName: aws.String(c.tableName),
|
||||
@@ -263,7 +263,7 @@ func (c *awsCollector) getReportKeys(userid string, row int64, start, end time.T
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *awsCollector) getReports(reportKeys []string) ([]report.Report, error) {
|
||||
func (c *awsCollector) getReports(ctx context.Context, reportKeys []string) ([]report.Report, error) {
|
||||
missing := reportKeys
|
||||
|
||||
stores := []ReportStore{c.inProcess}
|
||||
@@ -277,7 +277,7 @@ func (c *awsCollector) getReports(reportKeys []string) ([]report.Report, error)
|
||||
if store == nil {
|
||||
continue
|
||||
}
|
||||
found, newMissing, err := store.FetchReports(missing)
|
||||
found, newMissing, err := store.FetchReports(ctx, missing)
|
||||
missing = newMissing
|
||||
if err != nil {
|
||||
log.Warningf("Error fetching from cache: %v", err)
|
||||
@@ -311,12 +311,12 @@ func (c *awsCollector) Report(ctx context.Context) (report.Report, error) {
|
||||
// Queries will only every span 2 rows max.
|
||||
var reportKeys []string
|
||||
if rowStart != rowEnd {
|
||||
reportKeys1, err := c.getReportKeys(userid, rowStart, start, now)
|
||||
reportKeys1, err := c.getReportKeys(ctx, userid, rowStart, start, now)
|
||||
if err != nil {
|
||||
return report.MakeReport(), err
|
||||
}
|
||||
|
||||
reportKeys2, err := c.getReportKeys(userid, rowEnd, start, now)
|
||||
reportKeys2, err := c.getReportKeys(ctx, userid, rowEnd, start, now)
|
||||
if err != nil {
|
||||
return report.MakeReport(), err
|
||||
}
|
||||
@@ -324,13 +324,13 @@ func (c *awsCollector) Report(ctx context.Context) (report.Report, error) {
|
||||
reportKeys = append(reportKeys, reportKeys1...)
|
||||
reportKeys = append(reportKeys, reportKeys2...)
|
||||
} else {
|
||||
if reportKeys, err = c.getReportKeys(userid, rowEnd, start, now); err != nil {
|
||||
if reportKeys, err = c.getReportKeys(ctx, userid, rowEnd, start, now); err != nil {
|
||||
return report.MakeReport(), err
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("Fetching %d reports from %v to %v", len(reportKeys), start, now)
|
||||
reports, err := c.getReports(reportKeys)
|
||||
reports, err := c.getReports(ctx, reportKeys)
|
||||
if err != nil {
|
||||
return report.MakeReport(), err
|
||||
}
|
||||
@@ -367,7 +367,7 @@ func (c *awsCollector) Add(ctx context.Context, rep report.Report, buf []byte) e
|
||||
return err
|
||||
}
|
||||
|
||||
reportSize, err := c.s3.StoreReportBytes(reportKey, buf)
|
||||
reportSize, err := c.s3.StoreReportBytes(ctx, reportKey, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -375,7 +375,7 @@ func (c *awsCollector) Add(ctx context.Context, rep report.Report, buf []byte) e
|
||||
|
||||
// third, put it in memcache
|
||||
if c.memcache != nil {
|
||||
_, err = c.memcache.StoreReportBytes(reportKey, buf)
|
||||
_, err = c.memcache.StoreReportBytes(ctx, reportKey, buf)
|
||||
if err != nil {
|
||||
// NOTE: We don't abort here because failing to store in memcache
|
||||
// doesn't actually break anything else -- it's just an
|
||||
@@ -389,7 +389,7 @@ func (c *awsCollector) Add(ctx context.Context, rep report.Report, buf []byte) e
|
||||
Add(float64(len(reportKey)))
|
||||
|
||||
var resp *dynamodb.PutItemOutput
|
||||
err = instrument.TimeRequestHistogram("PutItem", dynamoRequestDuration, func() error {
|
||||
err = instrument.TimeRequestHistogram(ctx, "S3.PutItem", dynamoRequestDuration, func(_ context.Context) error {
|
||||
var err error
|
||||
resp, err = c.db.PutItem(&dynamodb.PutItemInput{
|
||||
TableName: aws.String(c.tableName),
|
||||
@@ -502,7 +502,7 @@ func newInProcessStore(size int, expiration time.Duration) inProcessStore {
|
||||
}
|
||||
|
||||
// FetchReports retrieves the given reports from the store.
|
||||
func (c inProcessStore) FetchReports(keys []string) (map[string]report.Report, []string, error) {
|
||||
func (c inProcessStore) FetchReports(_ context.Context, keys []string) (map[string]report.Report, []string, error) {
|
||||
found := map[string]report.Report{}
|
||||
missing := []string{}
|
||||
for _, key := range keys {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/bradfitz/gomemcache/memcache"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/weaveworks/scope/common/instrument"
|
||||
"github.com/weaveworks/scope/report"
|
||||
@@ -149,10 +150,10 @@ func memcacheStatusCode(err error) string {
|
||||
}
|
||||
|
||||
// FetchReports gets reports from memcache.
|
||||
func (c *MemcacheClient) FetchReports(keys []string) (map[string]report.Report, []string, error) {
|
||||
func (c *MemcacheClient) FetchReports(ctx context.Context, keys []string) (map[string]report.Report, []string, error) {
|
||||
defer memcacheRequests.Add(float64(len(keys)))
|
||||
var found map[string]*memcache.Item
|
||||
err := instrument.TimeRequestHistogramStatus("Get", memcacheRequestDuration, memcacheStatusCode, func() error {
|
||||
err := instrument.TimeRequestHistogramStatus(ctx, "Memcache.GetMulti", memcacheRequestDuration, memcacheStatusCode, func(_ context.Context) error {
|
||||
var err error
|
||||
found, err = c.client.GetMulti(keys)
|
||||
return err
|
||||
@@ -206,8 +207,8 @@ func (c *MemcacheClient) FetchReports(keys []string) (map[string]report.Report,
|
||||
}
|
||||
|
||||
// StoreReportBytes stores a report.
|
||||
func (c *MemcacheClient) StoreReportBytes(key string, rpt []byte) (int, error) {
|
||||
err := instrument.TimeRequestHistogramStatus("Put", memcacheRequestDuration, memcacheStatusCode, func() error {
|
||||
func (c *MemcacheClient) StoreReportBytes(ctx context.Context, key string, rpt []byte) (int, error) {
|
||||
err := instrument.TimeRequestHistogramStatus(ctx, "Memcache.Put", memcacheRequestDuration, memcacheStatusCode, func(_ context.Context) error {
|
||||
item := memcache.Item{Key: key, Value: rpt, Expiration: c.expiration}
|
||||
return c.client.Set(&item)
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
"github.com/weaveworks/scope/common/instrument"
|
||||
"github.com/weaveworks/scope/report"
|
||||
@@ -40,7 +41,7 @@ func NewS3Client(config *aws.Config, bucketName string) S3Store {
|
||||
}
|
||||
|
||||
// FetchReports fetches multiple reports in parallel from S3.
|
||||
func (store *S3Store) FetchReports(keys []string) (map[string]report.Report, []string, error) {
|
||||
func (store *S3Store) FetchReports(ctx context.Context, keys []string) (map[string]report.Report, []string, error) {
|
||||
type result struct {
|
||||
key string
|
||||
report *report.Report
|
||||
@@ -52,7 +53,7 @@ func (store *S3Store) FetchReports(keys []string) (map[string]report.Report, []s
|
||||
for _, key := range keys {
|
||||
go func(key string) {
|
||||
r := result{key: key}
|
||||
r.report, r.err = store.fetchReport(key)
|
||||
r.report, r.err = store.fetchReport(ctx, key)
|
||||
ch <- r
|
||||
}(key)
|
||||
}
|
||||
@@ -68,9 +69,9 @@ func (store *S3Store) FetchReports(keys []string) (map[string]report.Report, []s
|
||||
return reports, []string{}, nil
|
||||
}
|
||||
|
||||
func (store *S3Store) fetchReport(key string) (*report.Report, error) {
|
||||
func (store *S3Store) fetchReport(ctx context.Context, key string) (*report.Report, error) {
|
||||
var resp *s3.GetObjectOutput
|
||||
err := instrument.TimeRequestHistogram("Get", s3RequestDuration, func() error {
|
||||
err := instrument.TimeRequestHistogram(ctx, "S3.Get", s3RequestDuration, func(_ context.Context) error {
|
||||
var err error
|
||||
resp, err = store.s3.GetObject(&s3.GetObjectInput{
|
||||
Bucket: aws.String(store.bucketName),
|
||||
@@ -85,8 +86,8 @@ func (store *S3Store) fetchReport(key string) (*report.Report, error) {
|
||||
}
|
||||
|
||||
// StoreReportBytes stores a report.
|
||||
func (store *S3Store) StoreReportBytes(key string, buf []byte) (int, error) {
|
||||
err := instrument.TimeRequestHistogram("Put", s3RequestDuration, func() error {
|
||||
func (store *S3Store) StoreReportBytes(ctx context.Context, key string, buf []byte) (int, error) {
|
||||
err := instrument.TimeRequestHistogram(ctx, "S3.Put", s3RequestDuration, func(_ context.Context) error {
|
||||
_, err := store.s3.PutObject(&s3.PutObjectInput{
|
||||
Body: bytes.NewReader(buf),
|
||||
Bucket: aws.String(store.bucketName),
|
||||
|
||||
@@ -92,11 +92,11 @@ func (cr *sqsControlRouter) getResponseQueueURL() *string {
|
||||
return cr.responseQueueURL
|
||||
}
|
||||
|
||||
func (cr *sqsControlRouter) getOrCreateQueue(name string) (*string, error) {
|
||||
func (cr *sqsControlRouter) getOrCreateQueue(ctx context.Context, name string) (*string, error) {
|
||||
// CreateQueue creates a queue or if it already exists, returns url of said queue
|
||||
var createQueueRes *sqs.CreateQueueOutput
|
||||
var err error
|
||||
err = instrument.TimeRequestHistogram("CreateQueue", sqsRequestDuration, func() error {
|
||||
err = instrument.TimeRequestHistogram(ctx, "SQS.CreateQueue", sqsRequestDuration, func(_ context.Context) error {
|
||||
createQueueRes, err = cr.service.CreateQueue(&sqs.CreateQueueInput{
|
||||
QueueName: aws.String(name),
|
||||
})
|
||||
@@ -112,11 +112,12 @@ func (cr *sqsControlRouter) loop() {
|
||||
var (
|
||||
responseQueueURL *string
|
||||
err error
|
||||
ctx = context.Background()
|
||||
)
|
||||
for {
|
||||
// This app has a random id and uses this as a return path for all responses from probes.
|
||||
name := fmt.Sprintf("%scontrol-app-%d", cr.prefix, rand.Int63())
|
||||
responseQueueURL, err = cr.getOrCreateQueue(name)
|
||||
responseQueueURL, err = cr.getOrCreateQueue(ctx, name)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to create queue: %v", err)
|
||||
time.Sleep(1 * time.Second)
|
||||
@@ -129,7 +130,7 @@ func (cr *sqsControlRouter) loop() {
|
||||
for {
|
||||
var res *sqs.ReceiveMessageOutput
|
||||
var err error
|
||||
err = instrument.TimeRequestHistogram("ReceiveMessage", sqsRequestDuration, func() error {
|
||||
err = instrument.TimeRequestHistogram(ctx, "SQS.ReceiveMessage", sqsRequestDuration, func(_ context.Context) error {
|
||||
res, err = cr.service.ReceiveMessage(&sqs.ReceiveMessageInput{
|
||||
QueueUrl: responseQueueURL,
|
||||
WaitTimeSeconds: longPollTime,
|
||||
@@ -144,14 +145,14 @@ func (cr *sqsControlRouter) loop() {
|
||||
if len(res.Messages) == 0 {
|
||||
continue
|
||||
}
|
||||
if err := cr.deleteMessages(responseQueueURL, res.Messages); err != nil {
|
||||
if err := cr.deleteMessages(ctx, responseQueueURL, res.Messages); err != nil {
|
||||
log.Errorf("Error deleting message from %s: %v", *responseQueueURL, err)
|
||||
}
|
||||
cr.handleResponses(res)
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *sqsControlRouter) deleteMessages(queueURL *string, messages []*sqs.Message) error {
|
||||
func (cr *sqsControlRouter) deleteMessages(ctx context.Context, queueURL *string, messages []*sqs.Message) error {
|
||||
entries := []*sqs.DeleteMessageBatchRequestEntry{}
|
||||
for _, message := range messages {
|
||||
entries = append(entries, &sqs.DeleteMessageBatchRequestEntry{
|
||||
@@ -159,7 +160,7 @@ func (cr *sqsControlRouter) deleteMessages(queueURL *string, messages []*sqs.Mes
|
||||
Id: message.MessageId,
|
||||
})
|
||||
}
|
||||
return instrument.TimeRequestHistogram("DeleteMessageBatch", sqsRequestDuration, func() error {
|
||||
return instrument.TimeRequestHistogram(ctx, "SQS.DeleteMessageBatch", sqsRequestDuration, func(_ context.Context) error {
|
||||
_, err := cr.service.DeleteMessageBatch(&sqs.DeleteMessageBatchInput{
|
||||
QueueUrl: queueURL,
|
||||
Entries: entries,
|
||||
@@ -188,14 +189,14 @@ func (cr *sqsControlRouter) handleResponses(res *sqs.ReceiveMessageOutput) {
|
||||
}
|
||||
}
|
||||
|
||||
func (cr *sqsControlRouter) sendMessage(queueURL *string, message interface{}) error {
|
||||
func (cr *sqsControlRouter) sendMessage(ctx context.Context, queueURL *string, message interface{}) error {
|
||||
buf := bytes.Buffer{}
|
||||
if err := json.NewEncoder(&buf).Encode(message); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("sendMessage to %s: %s", *queueURL, buf.String())
|
||||
|
||||
return instrument.TimeRequestHistogram("SendMessage", sqsRequestDuration, func() error {
|
||||
return instrument.TimeRequestHistogram(ctx, "SQS.SendMessage", sqsRequestDuration, func(_ context.Context) error {
|
||||
_, err := cr.service.SendMessage(&sqs.SendMessageInput{
|
||||
QueueUrl: queueURL,
|
||||
MessageBody: aws.String(buf.String()),
|
||||
@@ -218,7 +219,7 @@ func (cr *sqsControlRouter) Handle(ctx context.Context, probeID string, req xfer
|
||||
}
|
||||
|
||||
var probeQueueURL *sqs.GetQueueUrlOutput
|
||||
err = instrument.TimeRequestHistogram("GetQueueUrl", sqsRequestDuration, func() error {
|
||||
err = instrument.TimeRequestHistogram(ctx, "SQS.GetQueueUrl", sqsRequestDuration, func(_ context.Context) error {
|
||||
probeQueueName := fmt.Sprintf("%sprobe-%s-%s", cr.prefix, userID, probeID)
|
||||
probeQueueURL, err = cr.service.GetQueueUrl(&sqs.GetQueueUrlInput{
|
||||
QueueName: aws.String(probeQueueName),
|
||||
@@ -242,8 +243,8 @@ func (cr *sqsControlRouter) Handle(ctx context.Context, probeID string, req xfer
|
||||
}()
|
||||
|
||||
// Next, send the request to that queue
|
||||
if err := instrument.TimeRequestHistogram("SendMessage", sqsRequestDuration, func() error {
|
||||
return cr.sendMessage(probeQueueURL.QueueUrl, sqsRequestMessage{
|
||||
if err := instrument.TimeRequestHistogram(ctx, "SQS.SendMessage", sqsRequestDuration, func(ctx context.Context) error {
|
||||
return cr.sendMessage(ctx, probeQueueURL.QueueUrl, sqsRequestMessage{
|
||||
ID: id,
|
||||
Request: req,
|
||||
ResponseQueueURL: *responseQueueURL,
|
||||
@@ -268,13 +269,14 @@ func (cr *sqsControlRouter) Register(ctx context.Context, probeID string, handle
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("%sprobe-%s-%s", cr.prefix, userID, probeID)
|
||||
queueURL, err := cr.getOrCreateQueue(name)
|
||||
queueURL, err := cr.getOrCreateQueue(ctx, name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
pwID := rand.Int63()
|
||||
pw := &probeWorker{
|
||||
ctx: ctx,
|
||||
router: cr,
|
||||
requestQueueURL: queueURL,
|
||||
handler: handler,
|
||||
@@ -302,6 +304,7 @@ func (cr *sqsControlRouter) Deregister(_ context.Context, probeID string, id int
|
||||
|
||||
// a probeWorker encapsulates a goroutine serving a probe's websocket connection.
|
||||
type probeWorker struct {
|
||||
ctx context.Context
|
||||
router *sqsControlRouter
|
||||
requestQueueURL *string
|
||||
handler xfer.ControlHandlerFunc
|
||||
@@ -326,7 +329,7 @@ func (pw *probeWorker) loop() {
|
||||
|
||||
var res *sqs.ReceiveMessageOutput
|
||||
var err error
|
||||
err = instrument.TimeRequestHistogram("ReceiveMessage", sqsRequestDuration, func() error {
|
||||
err = instrument.TimeRequestHistogram(pw.ctx, "SQS.ReceiveMessage", sqsRequestDuration, func(_ context.Context) error {
|
||||
res, err = pw.router.service.ReceiveMessage(&sqs.ReceiveMessageInput{
|
||||
QueueUrl: pw.requestQueueURL,
|
||||
WaitTimeSeconds: longPollTime,
|
||||
@@ -341,7 +344,7 @@ func (pw *probeWorker) loop() {
|
||||
if len(res.Messages) == 0 {
|
||||
continue
|
||||
}
|
||||
if err := pw.router.deleteMessages(pw.requestQueueURL, res.Messages); err != nil {
|
||||
if err := pw.router.deleteMessages(pw.ctx, pw.requestQueueURL, res.Messages); err != nil {
|
||||
log.Errorf("Error deleting message from %s: %v", *pw.requestQueueURL, err)
|
||||
}
|
||||
|
||||
@@ -354,7 +357,7 @@ func (pw *probeWorker) loop() {
|
||||
|
||||
response := pw.handler(sqsRequest.Request)
|
||||
|
||||
if err := pw.router.sendMessage(&sqsRequest.ResponseQueueURL, sqsResponseMessage{
|
||||
if err := pw.router.sendMessage(pw.ctx, &sqsRequest.ResponseQueueURL, sqsResponseMessage{
|
||||
ID: sqsRequest.ID,
|
||||
Response: response,
|
||||
}); err != nil {
|
||||
|
||||
@@ -3,7 +3,10 @@ package instrument
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ErrorCode converts an error in to an http-style error-code.
|
||||
@@ -16,26 +19,35 @@ func ErrorCode(err error) string {
|
||||
|
||||
// TimeRequestHistogram runs 'f' and records how long it took in the given Prometheus
|
||||
// histogram metric. If 'f' returns successfully, record a "200". Otherwise, record
|
||||
// "500".
|
||||
// "500". It will also emit an OpenTracing span if you have a global tracer configured.
|
||||
//
|
||||
// If you want more complicated logic for translating errors into statuses,
|
||||
// use 'TimeRequestStatus'.
|
||||
func TimeRequestHistogram(method string, metric *prometheus.HistogramVec, f func() error) error {
|
||||
return TimeRequestHistogramStatus(method, metric, ErrorCode, f)
|
||||
func TimeRequestHistogram(ctx context.Context, method string, metric *prometheus.HistogramVec, f func(context.Context) error) error {
|
||||
return TimeRequestHistogramStatus(ctx, method, metric, ErrorCode, f)
|
||||
}
|
||||
|
||||
// TimeRequestHistogramStatus runs 'f' and records how long it took in the given
|
||||
// Prometheus histogram metric.
|
||||
// Prometheus histogram metric. It will also emit an OpenTracing span if you have
|
||||
// a global tracer configured.
|
||||
//
|
||||
// toStatusCode is a function that translates errors returned by 'f' into
|
||||
// HTTP-like status codes.
|
||||
func TimeRequestHistogramStatus(method string, metric *prometheus.HistogramVec, toStatusCode func(error) string, f func() error) error {
|
||||
func TimeRequestHistogramStatus(ctx context.Context, method string, metric *prometheus.HistogramVec, toStatusCode func(error) string, f func(context.Context) error) error {
|
||||
if toStatusCode == nil {
|
||||
toStatusCode = ErrorCode
|
||||
}
|
||||
|
||||
sp, newCtx := opentracing.StartSpanFromContext(ctx, method)
|
||||
ext.SpanKindRPCClient.Set(sp)
|
||||
startTime := time.Now()
|
||||
err := f()
|
||||
duration := time.Now().Sub(startTime)
|
||||
metric.WithLabelValues(method, toStatusCode(err)).Observe(duration.Seconds())
|
||||
|
||||
err := f(newCtx)
|
||||
|
||||
if err != nil {
|
||||
ext.Error.Set(sp, true)
|
||||
}
|
||||
sp.Finish()
|
||||
metric.WithLabelValues(method, toStatusCode(err)).Observe(time.Now().Sub(startTime).Seconds())
|
||||
return err
|
||||
}
|
||||
|
||||
21
vendor/github.com/opentracing/opentracing-go/LICENSE
generated
vendored
Normal file
21
vendor/github.com/opentracing/opentracing-go/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 The OpenTracing Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
158
vendor/github.com/opentracing/opentracing-go/ext/tags.go
generated
vendored
Normal file
158
vendor/github.com/opentracing/opentracing-go/ext/tags.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
package ext
|
||||
|
||||
import opentracing "github.com/opentracing/opentracing-go"
|
||||
|
||||
// These constants define common tag names recommended for better portability across
|
||||
// tracing systems and languages/platforms.
|
||||
//
|
||||
// The tag names are defined as typed strings, so that in addition to the usual use
|
||||
//
|
||||
// span.setTag(TagName, value)
|
||||
//
|
||||
// they also support value type validation via this additional syntax:
|
||||
//
|
||||
// TagName.Set(span, value)
|
||||
//
|
||||
var (
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// SpanKind (client/server)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SpanKind hints at relationship between spans, e.g. client/server
|
||||
SpanKind = spanKindTagName("span.kind")
|
||||
|
||||
// SpanKindRPCClient marks a span representing the client-side of an RPC
|
||||
// or other remote call
|
||||
SpanKindRPCClientEnum = SpanKindEnum("client")
|
||||
SpanKindRPCClient = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCClientEnum}
|
||||
|
||||
// SpanKindRPCServer marks a span representing the server-side of an RPC
|
||||
// or other remote call
|
||||
SpanKindRPCServerEnum = SpanKindEnum("server")
|
||||
SpanKindRPCServer = opentracing.Tag{Key: string(SpanKind), Value: SpanKindRPCServerEnum}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Component name
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Component is a low-cardinality identifier of the module, library,
|
||||
// or package that is generating a span.
|
||||
Component = stringTagName("component")
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Sampling hint
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SamplingPriority determines the priority of sampling this Span.
|
||||
SamplingPriority = uint16TagName("sampling.priority")
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Peer tags. These tags can be emitted by either client-side of
|
||||
// server-side to describe the other side/service in a peer-to-peer
|
||||
// communications, like an RPC call.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PeerService records the service name of the peer
|
||||
PeerService = stringTagName("peer.service")
|
||||
|
||||
// PeerHostname records the host name of the peer
|
||||
PeerHostname = stringTagName("peer.hostname")
|
||||
|
||||
// PeerHostIPv4 records IP v4 host address of the peer
|
||||
PeerHostIPv4 = uint32TagName("peer.ipv4")
|
||||
|
||||
// PeerHostIPv6 records IP v6 host address of the peer
|
||||
PeerHostIPv6 = stringTagName("peer.ipv6")
|
||||
|
||||
// PeerPort records port number of the peer
|
||||
PeerPort = uint16TagName("peer.port")
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// HTTP Tags
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// HTTPUrl should be the URL of the request being handled in this segment
|
||||
// of the trace, in standard URI format. The protocol is optional.
|
||||
HTTPUrl = stringTagName("http.url")
|
||||
|
||||
// HTTPMethod is the HTTP method of the request, and is case-insensitive.
|
||||
HTTPMethod = stringTagName("http.method")
|
||||
|
||||
// HTTPStatusCode is the numeric HTTP status code (200, 404, etc) of the
|
||||
// HTTP response.
|
||||
HTTPStatusCode = uint16TagName("http.status_code")
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Error Tag
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Error indicates that operation represented by the span resulted in an error.
|
||||
Error = boolTagName("error")
|
||||
)
|
||||
|
||||
// ---
|
||||
|
||||
// SpanKindEnum represents common span types
|
||||
type SpanKindEnum string
|
||||
|
||||
type spanKindTagName string
|
||||
|
||||
// Set adds a string tag to the `span`
|
||||
func (tag spanKindTagName) Set(span opentracing.Span, value SpanKindEnum) {
|
||||
span.SetTag(string(tag), value)
|
||||
}
|
||||
|
||||
type rpcServerOption struct {
|
||||
clientContext opentracing.SpanContext
|
||||
}
|
||||
|
||||
func (r rpcServerOption) Apply(o *opentracing.StartSpanOptions) {
|
||||
if r.clientContext != nil {
|
||||
opentracing.ChildOf(r.clientContext).Apply(o)
|
||||
}
|
||||
SpanKindRPCServer.Apply(o)
|
||||
}
|
||||
|
||||
// RPCServerOption returns a StartSpanOption appropriate for an RPC server span
|
||||
// with `client` representing the metadata for the remote peer Span if available.
|
||||
// In case client == nil, due to the client not being instrumented, this RPC
|
||||
// server span will be a root span.
|
||||
func RPCServerOption(client opentracing.SpanContext) opentracing.StartSpanOption {
|
||||
return rpcServerOption{client}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type stringTagName string
|
||||
|
||||
// Set adds a string tag to the `span`
|
||||
func (tag stringTagName) Set(span opentracing.Span, value string) {
|
||||
span.SetTag(string(tag), value)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type uint32TagName string
|
||||
|
||||
// Set adds a uint32 tag to the `span`
|
||||
func (tag uint32TagName) Set(span opentracing.Span, value uint32) {
|
||||
span.SetTag(string(tag), value)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type uint16TagName string
|
||||
|
||||
// Set adds a uint16 tag to the `span`
|
||||
func (tag uint16TagName) Set(span opentracing.Span, value uint16) {
|
||||
span.SetTag(string(tag), value)
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
type boolTagName string
|
||||
|
||||
// Add adds a bool tag to the `span`
|
||||
func (tag boolTagName) Set(span opentracing.Span, value bool) {
|
||||
span.SetTag(string(tag), value)
|
||||
}
|
||||
27
vendor/github.com/opentracing/opentracing-go/globaltracer.go
generated
vendored
Normal file
27
vendor/github.com/opentracing/opentracing-go/globaltracer.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package opentracing
|
||||
|
||||
var (
|
||||
globalTracer Tracer = NoopTracer{}
|
||||
)
|
||||
|
||||
// InitGlobalTracer sets the [singleton] opentracing.Tracer returned by
|
||||
// GlobalTracer(). Those who use GlobalTracer (rather than directly manage an
|
||||
// opentracing.Tracer instance) should call InitGlobalTracer as early as
|
||||
// possible in main(), prior to calling the `StartSpan` global func below.
|
||||
// Prior to calling `InitGlobalTracer`, any Spans started via the `StartSpan`
|
||||
// (etc) globals are noops.
|
||||
func InitGlobalTracer(tracer Tracer) {
|
||||
globalTracer = tracer
|
||||
}
|
||||
|
||||
// GlobalTracer returns the global singleton `Tracer` implementation.
|
||||
// Before `InitGlobalTracer()` is called, the `GlobalTracer()` is a noop
|
||||
// implementation that drops all data handed to it.
|
||||
func GlobalTracer() Tracer {
|
||||
return globalTracer
|
||||
}
|
||||
|
||||
// StartSpan defers to `Tracer.StartSpan`. See `GlobalTracer()`.
|
||||
func StartSpan(operationName string, opts ...StartSpanOption) Span {
|
||||
return globalTracer.StartSpan(operationName, opts...)
|
||||
}
|
||||
57
vendor/github.com/opentracing/opentracing-go/gocontext.go
generated
vendored
Normal file
57
vendor/github.com/opentracing/opentracing-go/gocontext.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package opentracing
|
||||
|
||||
import "golang.org/x/net/context"
|
||||
|
||||
type contextKey struct{}
|
||||
|
||||
var activeSpanKey = contextKey{}
|
||||
|
||||
// ContextWithSpan returns a new `context.Context` that holds a reference to
|
||||
// `span`'s SpanContext.
|
||||
func ContextWithSpan(ctx context.Context, span Span) context.Context {
|
||||
return context.WithValue(ctx, activeSpanKey, span)
|
||||
}
|
||||
|
||||
// SpanFromContext returns the `Span` previously associated with `ctx`, or
|
||||
// `nil` if no such `Span` could be found.
|
||||
//
|
||||
// NOTE: context.Context != SpanContext: the former is Go's intra-process
|
||||
// context propagation mechanism, and the latter houses OpenTracing's per-Span
|
||||
// identity and baggage information.
|
||||
func SpanFromContext(ctx context.Context) Span {
|
||||
val := ctx.Value(activeSpanKey)
|
||||
if sp, ok := val.(Span); ok {
|
||||
return sp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartSpanFromContext starts and returns a Span with `operationName`, using
|
||||
// any Span found within `ctx` as a ChildOfRef. If no such parent could be
|
||||
// found, StartSpanFromContext creates a root (parentless) Span.
|
||||
//
|
||||
// The second return value is a context.Context object built around the
|
||||
// returned Span.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// SomeFunction(ctx context.Context, ...) {
|
||||
// sp, ctx := opentracing.StartSpanFromContext(ctx, "SomeFunction")
|
||||
// defer sp.Finish()
|
||||
// ...
|
||||
// }
|
||||
func StartSpanFromContext(ctx context.Context, operationName string, opts ...StartSpanOption) (Span, context.Context) {
|
||||
return startSpanFromContextWithTracer(ctx, GlobalTracer(), operationName, opts...)
|
||||
}
|
||||
|
||||
// startSpanFromContextWithTracer is factored out for testing purposes.
|
||||
func startSpanFromContextWithTracer(ctx context.Context, tracer Tracer, operationName string, opts ...StartSpanOption) (Span, context.Context) {
|
||||
var span Span
|
||||
if parentSpan := SpanFromContext(ctx); parentSpan != nil {
|
||||
opts = append(opts, ChildOf(parentSpan.Context()))
|
||||
span = tracer.StartSpan(operationName, opts...)
|
||||
} else {
|
||||
span = tracer.StartSpan(operationName, opts...)
|
||||
}
|
||||
return span, ContextWithSpan(ctx, span)
|
||||
}
|
||||
241
vendor/github.com/opentracing/opentracing-go/log/field.go
generated
vendored
Normal file
241
vendor/github.com/opentracing/opentracing-go/log/field.go
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
type fieldType int
|
||||
|
||||
const (
|
||||
stringType fieldType = iota
|
||||
boolType
|
||||
intType
|
||||
int32Type
|
||||
uint32Type
|
||||
int64Type
|
||||
uint64Type
|
||||
float32Type
|
||||
float64Type
|
||||
errorType
|
||||
objectType
|
||||
lazyLoggerType
|
||||
)
|
||||
|
||||
// Field instances are constructed via LogBool, LogString, and so on.
|
||||
// Tracing implementations may then handle them via the Field.Marshal
|
||||
// method.
|
||||
//
|
||||
// "heavily influenced by" (i.e., partially stolen from)
|
||||
// https://github.com/uber-go/zap
|
||||
type Field struct {
|
||||
key string
|
||||
fieldType fieldType
|
||||
numericVal int64
|
||||
stringVal string
|
||||
interfaceVal interface{}
|
||||
}
|
||||
|
||||
// String adds a string-valued key:value pair to a Span.LogFields() record
|
||||
func String(key, val string) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: stringType,
|
||||
stringVal: val,
|
||||
}
|
||||
}
|
||||
|
||||
// Bool adds a bool-valued key:value pair to a Span.LogFields() record
|
||||
func Bool(key string, val bool) Field {
|
||||
var numericVal int64
|
||||
if val {
|
||||
numericVal = 1
|
||||
}
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: boolType,
|
||||
numericVal: numericVal,
|
||||
}
|
||||
}
|
||||
|
||||
// Int adds an int-valued key:value pair to a Span.LogFields() record
|
||||
func Int(key string, val int) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: intType,
|
||||
numericVal: int64(val),
|
||||
}
|
||||
}
|
||||
|
||||
// Int32 adds an int32-valued key:value pair to a Span.LogFields() record
|
||||
func Int32(key string, val int32) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: int32Type,
|
||||
numericVal: int64(val),
|
||||
}
|
||||
}
|
||||
|
||||
// Int64 adds an int64-valued key:value pair to a Span.LogFields() record
|
||||
func Int64(key string, val int64) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: int64Type,
|
||||
numericVal: val,
|
||||
}
|
||||
}
|
||||
|
||||
// Uint32 adds a uint32-valued key:value pair to a Span.LogFields() record
|
||||
func Uint32(key string, val uint32) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: uint32Type,
|
||||
numericVal: int64(val),
|
||||
}
|
||||
}
|
||||
|
||||
// Uint64 adds a uint64-valued key:value pair to a Span.LogFields() record
|
||||
func Uint64(key string, val uint64) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: uint64Type,
|
||||
numericVal: int64(val),
|
||||
}
|
||||
}
|
||||
|
||||
// Float32 adds a float32-valued key:value pair to a Span.LogFields() record
|
||||
func Float32(key string, val float32) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: float32Type,
|
||||
numericVal: int64(math.Float32bits(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// Float64 adds a float64-valued key:value pair to a Span.LogFields() record
|
||||
func Float64(key string, val float64) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: float64Type,
|
||||
numericVal: int64(math.Float64bits(val)),
|
||||
}
|
||||
}
|
||||
|
||||
// Error adds an error with the key "error" to a Span.LogFields() record
|
||||
func Error(err error) Field {
|
||||
return Field{
|
||||
key: "error",
|
||||
fieldType: errorType,
|
||||
interfaceVal: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Object adds an object-valued key:value pair to a Span.LogFields() record
|
||||
func Object(key string, obj interface{}) Field {
|
||||
return Field{
|
||||
key: key,
|
||||
fieldType: objectType,
|
||||
interfaceVal: obj,
|
||||
}
|
||||
}
|
||||
|
||||
// LazyLogger allows for user-defined, late-bound logging of arbitrary data
|
||||
type LazyLogger func(fv Encoder)
|
||||
|
||||
// Lazy adds a LazyLogger to a Span.LogFields() record; the tracing
|
||||
// implementation will call the LazyLogger function at an indefinite time in
|
||||
// the future (after Lazy() returns).
|
||||
func Lazy(ll LazyLogger) Field {
|
||||
return Field{
|
||||
fieldType: lazyLoggerType,
|
||||
interfaceVal: ll,
|
||||
}
|
||||
}
|
||||
|
||||
// Encoder allows access to the contents of a Field (via a call to
|
||||
// Field.Marshal).
|
||||
//
|
||||
// Tracer implementations typically provide an implementation of Encoder;
|
||||
// OpenTracing callers typically do not need to concern themselves with it.
|
||||
type Encoder interface {
|
||||
EmitString(key, value string)
|
||||
EmitBool(key string, value bool)
|
||||
EmitInt(key string, value int)
|
||||
EmitInt32(key string, value int32)
|
||||
EmitInt64(key string, value int64)
|
||||
EmitUint32(key string, value uint32)
|
||||
EmitUint64(key string, value uint64)
|
||||
EmitFloat32(key string, value float32)
|
||||
EmitFloat64(key string, value float64)
|
||||
EmitObject(key string, value interface{})
|
||||
EmitLazyLogger(value LazyLogger)
|
||||
}
|
||||
|
||||
// Marshal passes a Field instance through to the appropriate
|
||||
// field-type-specific method of an Encoder.
|
||||
func (lf Field) Marshal(visitor Encoder) {
|
||||
switch lf.fieldType {
|
||||
case stringType:
|
||||
visitor.EmitString(lf.key, lf.stringVal)
|
||||
case boolType:
|
||||
visitor.EmitBool(lf.key, lf.numericVal != 0)
|
||||
case intType:
|
||||
visitor.EmitInt(lf.key, int(lf.numericVal))
|
||||
case int32Type:
|
||||
visitor.EmitInt32(lf.key, int32(lf.numericVal))
|
||||
case int64Type:
|
||||
visitor.EmitInt64(lf.key, int64(lf.numericVal))
|
||||
case uint32Type:
|
||||
visitor.EmitUint32(lf.key, uint32(lf.numericVal))
|
||||
case uint64Type:
|
||||
visitor.EmitUint64(lf.key, uint64(lf.numericVal))
|
||||
case float32Type:
|
||||
visitor.EmitFloat32(lf.key, math.Float32frombits(uint32(lf.numericVal)))
|
||||
case float64Type:
|
||||
visitor.EmitFloat64(lf.key, math.Float64frombits(uint64(lf.numericVal)))
|
||||
case errorType:
|
||||
visitor.EmitString(lf.key, lf.interfaceVal.(error).Error())
|
||||
case objectType:
|
||||
visitor.EmitObject(lf.key, lf.interfaceVal)
|
||||
case lazyLoggerType:
|
||||
visitor.EmitLazyLogger(lf.interfaceVal.(LazyLogger))
|
||||
}
|
||||
}
|
||||
|
||||
// Key returns the field's key.
|
||||
func (lf Field) Key() string {
|
||||
return lf.key
|
||||
}
|
||||
|
||||
// Value returns the field's value as interface{}.
|
||||
func (lf Field) Value() interface{} {
|
||||
switch lf.fieldType {
|
||||
case stringType:
|
||||
return lf.stringVal
|
||||
case boolType:
|
||||
return lf.numericVal != 0
|
||||
case intType:
|
||||
return int(lf.numericVal)
|
||||
case int32Type:
|
||||
return int32(lf.numericVal)
|
||||
case int64Type:
|
||||
return int64(lf.numericVal)
|
||||
case uint32Type:
|
||||
return uint32(lf.numericVal)
|
||||
case uint64Type:
|
||||
return uint64(lf.numericVal)
|
||||
case float32Type:
|
||||
return math.Float32frombits(uint32(lf.numericVal))
|
||||
case float64Type:
|
||||
return math.Float64frombits(uint64(lf.numericVal))
|
||||
case errorType, objectType, lazyLoggerType:
|
||||
return lf.interfaceVal
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of the key and value.
|
||||
func (lf Field) String() string {
|
||||
return fmt.Sprint(lf.key, ":", lf.Value())
|
||||
}
|
||||
54
vendor/github.com/opentracing/opentracing-go/log/util.go
generated
vendored
Normal file
54
vendor/github.com/opentracing/opentracing-go/log/util.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package log
|
||||
|
||||
import "fmt"
|
||||
|
||||
// InterleavedKVToFields converts keyValues a la Span.LogKV() to a Field slice
|
||||
// a la Span.LogFields().
|
||||
func InterleavedKVToFields(keyValues ...interface{}) ([]Field, error) {
|
||||
if len(keyValues)%2 != 0 {
|
||||
return nil, fmt.Errorf("non-even keyValues len: %d", len(keyValues))
|
||||
}
|
||||
fields := make([]Field, len(keyValues)/2)
|
||||
for i := 0; i*2 < len(keyValues); i++ {
|
||||
key, ok := keyValues[i*2].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(
|
||||
"non-string key (pair #%d): %T",
|
||||
i, keyValues[i*2])
|
||||
}
|
||||
switch typedVal := keyValues[i*2+1].(type) {
|
||||
case bool:
|
||||
fields[i] = Bool(key, typedVal)
|
||||
case string:
|
||||
fields[i] = String(key, typedVal)
|
||||
case int:
|
||||
fields[i] = Int(key, typedVal)
|
||||
case int8:
|
||||
fields[i] = Int32(key, int32(typedVal))
|
||||
case int16:
|
||||
fields[i] = Int32(key, int32(typedVal))
|
||||
case int32:
|
||||
fields[i] = Int32(key, typedVal)
|
||||
case int64:
|
||||
fields[i] = Int64(key, typedVal)
|
||||
case uint:
|
||||
fields[i] = Uint64(key, uint64(typedVal))
|
||||
case uint64:
|
||||
fields[i] = Uint64(key, typedVal)
|
||||
case uint8:
|
||||
fields[i] = Uint32(key, uint32(typedVal))
|
||||
case uint16:
|
||||
fields[i] = Uint32(key, uint32(typedVal))
|
||||
case uint32:
|
||||
fields[i] = Uint32(key, typedVal)
|
||||
case float32:
|
||||
fields[i] = Float32(key, typedVal)
|
||||
case float64:
|
||||
fields[i] = Float64(key, typedVal)
|
||||
default:
|
||||
// When in doubt, coerce to a string
|
||||
fields[i] = String(key, fmt.Sprint(typedVal))
|
||||
}
|
||||
}
|
||||
return fields, nil
|
||||
}
|
||||
105
vendor/github.com/opentracing/opentracing-go/mocktracer/mocklogrecord.go
generated
vendored
Normal file
105
vendor/github.com/opentracing/opentracing-go/mocktracer/mocklogrecord.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package mocktracer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/opentracing/opentracing-go/log"
|
||||
)
|
||||
|
||||
// MockLogRecord represents data logged to a Span via Span.LogFields or
|
||||
// Span.LogKV.
|
||||
type MockLogRecord struct {
|
||||
Timestamp time.Time
|
||||
Fields []MockKeyValue
|
||||
}
|
||||
|
||||
// MockKeyValue represents a single key:value pair.
|
||||
type MockKeyValue struct {
|
||||
Key string
|
||||
|
||||
// All MockLogRecord values are coerced to strings via fmt.Sprint(), though
|
||||
// we retain their type separately.
|
||||
ValueKind reflect.Kind
|
||||
ValueString string
|
||||
}
|
||||
|
||||
// EmitString belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitString(key, value string) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitBool belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitBool(key string, value bool) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitInt belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitInt(key string, value int) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitInt32 belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitInt32(key string, value int32) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitInt64 belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitInt64(key string, value int64) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitUint32 belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitUint32(key string, value uint32) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitUint64 belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitUint64(key string, value uint64) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitFloat32 belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitFloat32(key string, value float32) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitFloat64 belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitFloat64(key string, value float64) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitObject belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitObject(key string, value interface{}) {
|
||||
m.Key = key
|
||||
m.ValueKind = reflect.TypeOf(value).Kind()
|
||||
m.ValueString = fmt.Sprint(value)
|
||||
}
|
||||
|
||||
// EmitLazyLogger belongs to the log.Encoder interface
|
||||
func (m *MockKeyValue) EmitLazyLogger(value log.LazyLogger) {
|
||||
var meta MockKeyValue
|
||||
value(&meta)
|
||||
m.Key = meta.Key
|
||||
m.ValueKind = meta.ValueKind
|
||||
m.ValueString = meta.ValueString
|
||||
}
|
||||
283
vendor/github.com/opentracing/opentracing-go/mocktracer/mockspan.go
generated
vendored
Normal file
283
vendor/github.com/opentracing/opentracing-go/mocktracer/mockspan.go
generated
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
package mocktracer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/opentracing/opentracing-go/ext"
|
||||
"github.com/opentracing/opentracing-go/log"
|
||||
)
|
||||
|
||||
// MockSpanContext is an opentracing.SpanContext implementation.
|
||||
//
|
||||
// It is entirely unsuitable for production use, but appropriate for tests
|
||||
// that want to verify tracing behavior in other frameworks/applications.
|
||||
//
|
||||
// By default all spans have Sampled=true flag, unless {"sampling.priority": 0}
|
||||
// tag is set.
|
||||
type MockSpanContext struct {
|
||||
TraceID int
|
||||
SpanID int
|
||||
Sampled bool
|
||||
Baggage map[string]string
|
||||
}
|
||||
|
||||
var mockIDSource = uint32(42)
|
||||
|
||||
func nextMockID() int {
|
||||
atomic.AddUint32(&mockIDSource, 1)
|
||||
return int(atomic.LoadUint32(&mockIDSource))
|
||||
}
|
||||
|
||||
// ForeachBaggageItem belongs to the SpanContext interface
|
||||
func (c MockSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {
|
||||
for k, v := range c.Baggage {
|
||||
if !handler(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithBaggageItem creates a new context with an extra baggage item.
|
||||
func (c MockSpanContext) WithBaggageItem(key, value string) MockSpanContext {
|
||||
var newBaggage map[string]string
|
||||
if c.Baggage == nil {
|
||||
newBaggage = map[string]string{key: value}
|
||||
} else {
|
||||
newBaggage = make(map[string]string, len(c.Baggage)+1)
|
||||
for k, v := range c.Baggage {
|
||||
newBaggage[k] = v
|
||||
}
|
||||
newBaggage[key] = value
|
||||
}
|
||||
// Use positional parameters so the compiler will help catch new fields.
|
||||
return MockSpanContext{c.TraceID, c.SpanID, c.Sampled, newBaggage}
|
||||
}
|
||||
|
||||
// MockSpan is an opentracing.Span implementation that exports its internal
|
||||
// state for testing purposes.
|
||||
type MockSpan struct {
|
||||
sync.RWMutex
|
||||
|
||||
ParentID int
|
||||
|
||||
OperationName string
|
||||
StartTime time.Time
|
||||
FinishTime time.Time
|
||||
|
||||
// All of the below are protected by the embedded RWMutex.
|
||||
SpanContext MockSpanContext
|
||||
tags map[string]interface{}
|
||||
logs []MockLogRecord
|
||||
tracer *MockTracer
|
||||
}
|
||||
|
||||
func newMockSpan(t *MockTracer, name string, opts opentracing.StartSpanOptions) *MockSpan {
|
||||
tags := opts.Tags
|
||||
if tags == nil {
|
||||
tags = map[string]interface{}{}
|
||||
}
|
||||
traceID := nextMockID()
|
||||
parentID := int(0)
|
||||
var baggage map[string]string
|
||||
sampled := true
|
||||
if len(opts.References) > 0 {
|
||||
traceID = opts.References[0].ReferencedContext.(MockSpanContext).TraceID
|
||||
parentID = opts.References[0].ReferencedContext.(MockSpanContext).SpanID
|
||||
sampled = opts.References[0].ReferencedContext.(MockSpanContext).Sampled
|
||||
baggage = opts.References[0].ReferencedContext.(MockSpanContext).Baggage
|
||||
}
|
||||
spanContext := MockSpanContext{traceID, nextMockID(), sampled, baggage}
|
||||
startTime := opts.StartTime
|
||||
if startTime.IsZero() {
|
||||
startTime = time.Now()
|
||||
}
|
||||
return &MockSpan{
|
||||
ParentID: parentID,
|
||||
OperationName: name,
|
||||
StartTime: startTime,
|
||||
tags: tags,
|
||||
logs: []MockLogRecord{},
|
||||
SpanContext: spanContext,
|
||||
|
||||
tracer: t,
|
||||
}
|
||||
}
|
||||
|
||||
// Tags returns a copy of tags accumulated by the span so far
|
||||
func (s *MockSpan) Tags() map[string]interface{} {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
tags := make(map[string]interface{})
|
||||
for k, v := range s.tags {
|
||||
tags[k] = v
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
// Tag returns a single tag
|
||||
func (s *MockSpan) Tag(k string) interface{} {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
return s.tags[k]
|
||||
}
|
||||
|
||||
// Logs returns a copy of logs accumulated in the span so far
|
||||
func (s *MockSpan) Logs() []MockLogRecord {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
logs := make([]MockLogRecord, len(s.logs))
|
||||
copy(logs, s.logs)
|
||||
return logs
|
||||
}
|
||||
|
||||
// Context belongs to the Span interface
|
||||
func (s *MockSpan) Context() opentracing.SpanContext {
|
||||
return s.SpanContext
|
||||
}
|
||||
|
||||
// SetTag belongs to the Span interface
|
||||
func (s *MockSpan) SetTag(key string, value interface{}) opentracing.Span {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
if key == string(ext.SamplingPriority) {
|
||||
if v, ok := value.(uint16); ok {
|
||||
s.SpanContext.Sampled = v > 0
|
||||
return s
|
||||
}
|
||||
if v, ok := value.(int); ok {
|
||||
s.SpanContext.Sampled = v > 0
|
||||
return s
|
||||
}
|
||||
}
|
||||
s.tags[key] = value
|
||||
return s
|
||||
}
|
||||
|
||||
// SetBaggageItem belongs to the Span interface
|
||||
func (s *MockSpan) SetBaggageItem(key, val string) opentracing.Span {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.SpanContext = s.SpanContext.WithBaggageItem(key, val)
|
||||
return s
|
||||
}
|
||||
|
||||
// BaggageItem belongs to the Span interface
|
||||
func (s *MockSpan) BaggageItem(key string) string {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
return s.SpanContext.Baggage[key]
|
||||
}
|
||||
|
||||
// Finish belongs to the Span interface
|
||||
func (s *MockSpan) Finish() {
|
||||
s.Lock()
|
||||
s.FinishTime = time.Now()
|
||||
s.Unlock()
|
||||
s.tracer.recordSpan(s)
|
||||
}
|
||||
|
||||
// FinishWithOptions belongs to the Span interface
|
||||
func (s *MockSpan) FinishWithOptions(opts opentracing.FinishOptions) {
|
||||
s.Lock()
|
||||
s.FinishTime = opts.FinishTime
|
||||
s.Unlock()
|
||||
|
||||
// Handle any late-bound LogRecords.
|
||||
for _, lr := range opts.LogRecords {
|
||||
s.logFieldsWithTimestamp(lr.Timestamp, lr.Fields...)
|
||||
}
|
||||
// Handle (deprecated) BulkLogData.
|
||||
for _, ld := range opts.BulkLogData {
|
||||
if ld.Payload != nil {
|
||||
s.logFieldsWithTimestamp(
|
||||
ld.Timestamp,
|
||||
log.String("event", ld.Event),
|
||||
log.Object("payload", ld.Payload))
|
||||
} else {
|
||||
s.logFieldsWithTimestamp(
|
||||
ld.Timestamp,
|
||||
log.String("event", ld.Event))
|
||||
}
|
||||
}
|
||||
|
||||
s.tracer.recordSpan(s)
|
||||
}
|
||||
|
||||
// String allows printing span for debugging
|
||||
func (s *MockSpan) String() string {
|
||||
return fmt.Sprintf(
|
||||
"traceId=%d, spanId=%d, parentId=%d, sampled=%t, name=%s",
|
||||
s.SpanContext.TraceID, s.SpanContext.SpanID, s.ParentID,
|
||||
s.SpanContext.Sampled, s.OperationName)
|
||||
}
|
||||
|
||||
// LogFields belongs to the Span interface
|
||||
func (s *MockSpan) LogFields(fields ...log.Field) {
|
||||
s.logFieldsWithTimestamp(time.Now(), fields...)
|
||||
}
|
||||
|
||||
// The caller MUST NOT hold s.Lock
|
||||
func (s *MockSpan) logFieldsWithTimestamp(ts time.Time, fields ...log.Field) {
|
||||
lr := MockLogRecord{
|
||||
Timestamp: ts,
|
||||
Fields: make([]MockKeyValue, len(fields)),
|
||||
}
|
||||
for i, f := range fields {
|
||||
outField := &(lr.Fields[i])
|
||||
f.Marshal(outField)
|
||||
}
|
||||
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.logs = append(s.logs, lr)
|
||||
}
|
||||
|
||||
// LogKV belongs to the Span interface.
|
||||
//
|
||||
// This implementations coerces all "values" to strings, though that is not
|
||||
// something all implementations need to do. Indeed, a motivated person can and
|
||||
// probably should have this do a typed switch on the values.
|
||||
func (s *MockSpan) LogKV(keyValues ...interface{}) {
|
||||
if len(keyValues)%2 != 0 {
|
||||
s.LogFields(log.Error(fmt.Errorf("Non-even keyValues len: %v", len(keyValues))))
|
||||
return
|
||||
}
|
||||
fields, err := log.InterleavedKVToFields(keyValues...)
|
||||
if err != nil {
|
||||
s.LogFields(log.Error(err), log.String("function", "LogKV"))
|
||||
return
|
||||
}
|
||||
s.LogFields(fields...)
|
||||
}
|
||||
|
||||
// LogEvent belongs to the Span interface
|
||||
func (s *MockSpan) LogEvent(event string) {
|
||||
s.LogFields(log.String("event", event))
|
||||
}
|
||||
|
||||
// LogEventWithPayload belongs to the Span interface
|
||||
func (s *MockSpan) LogEventWithPayload(event string, payload interface{}) {
|
||||
s.LogFields(log.String("event", event), log.Object("payload", payload))
|
||||
}
|
||||
|
||||
// Log belongs to the Span interface
|
||||
func (s *MockSpan) Log(data opentracing.LogData) {
|
||||
panic("MockSpan.Log() no longer supported")
|
||||
}
|
||||
|
||||
// SetOperationName belongs to the Span interface
|
||||
func (s *MockSpan) SetOperationName(operationName string) opentracing.Span {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.OperationName = operationName
|
||||
return s
|
||||
}
|
||||
|
||||
// Tracer belongs to the Span interface
|
||||
func (s *MockSpan) Tracer() opentracing.Tracer {
|
||||
return s.tracer
|
||||
}
|
||||
105
vendor/github.com/opentracing/opentracing-go/mocktracer/mocktracer.go
generated
vendored
Normal file
105
vendor/github.com/opentracing/opentracing-go/mocktracer/mocktracer.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package mocktracer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
// New returns a MockTracer opentracing.Tracer implementation that's intended
|
||||
// to facilitate tests of OpenTracing instrumentation.
|
||||
func New() *MockTracer {
|
||||
t := &MockTracer{
|
||||
finishedSpans: []*MockSpan{},
|
||||
injectors: make(map[interface{}]Injector),
|
||||
extractors: make(map[interface{}]Extractor),
|
||||
}
|
||||
|
||||
// register default injectors/extractors
|
||||
textPropagator := new(TextMapPropagator)
|
||||
t.RegisterInjector(opentracing.TextMap, textPropagator)
|
||||
t.RegisterExtractor(opentracing.TextMap, textPropagator)
|
||||
|
||||
httpPropagator := &TextMapPropagator{HTTPHeaders: true}
|
||||
t.RegisterInjector(opentracing.HTTPHeaders, httpPropagator)
|
||||
t.RegisterExtractor(opentracing.HTTPHeaders, httpPropagator)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// MockTracer is only intended for testing OpenTracing instrumentation.
|
||||
//
|
||||
// It is entirely unsuitable for production use, but appropriate for tests
|
||||
// that want to verify tracing behavior in other frameworks/applications.
|
||||
type MockTracer struct {
|
||||
sync.RWMutex
|
||||
finishedSpans []*MockSpan
|
||||
injectors map[interface{}]Injector
|
||||
extractors map[interface{}]Extractor
|
||||
}
|
||||
|
||||
// FinishedSpans returns all spans that have been Finish()'ed since the
|
||||
// MockTracer was constructed or since the last call to its Reset() method.
|
||||
func (t *MockTracer) FinishedSpans() []*MockSpan {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
spans := make([]*MockSpan, len(t.finishedSpans))
|
||||
copy(spans, t.finishedSpans)
|
||||
return spans
|
||||
}
|
||||
|
||||
// Reset clears the internally accumulated finished spans. Note that any
|
||||
// extant MockSpans will still append to finishedSpans when they Finish(),
|
||||
// even after a call to Reset().
|
||||
func (t *MockTracer) Reset() {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.finishedSpans = []*MockSpan{}
|
||||
}
|
||||
|
||||
// StartSpan belongs to the Tracer interface.
|
||||
func (t *MockTracer) StartSpan(operationName string, opts ...opentracing.StartSpanOption) opentracing.Span {
|
||||
sso := opentracing.StartSpanOptions{}
|
||||
for _, o := range opts {
|
||||
o.Apply(&sso)
|
||||
}
|
||||
return newMockSpan(t, operationName, sso)
|
||||
}
|
||||
|
||||
// RegisterInjector registers injector for given format
|
||||
func (t *MockTracer) RegisterInjector(format interface{}, injector Injector) {
|
||||
t.injectors[format] = injector
|
||||
}
|
||||
|
||||
// RegisterExtractor registers extractor for given format
|
||||
func (t *MockTracer) RegisterExtractor(format interface{}, extractor Extractor) {
|
||||
t.extractors[format] = extractor
|
||||
}
|
||||
|
||||
// Inject belongs to the Tracer interface.
|
||||
func (t *MockTracer) Inject(sm opentracing.SpanContext, format interface{}, carrier interface{}) error {
|
||||
spanContext, ok := sm.(MockSpanContext)
|
||||
if !ok {
|
||||
return opentracing.ErrInvalidCarrier
|
||||
}
|
||||
injector, ok := t.injectors[format]
|
||||
if !ok {
|
||||
return opentracing.ErrUnsupportedFormat
|
||||
}
|
||||
return injector.Inject(spanContext, carrier)
|
||||
}
|
||||
|
||||
// Extract belongs to the Tracer interface.
|
||||
func (t *MockTracer) Extract(format interface{}, carrier interface{}) (opentracing.SpanContext, error) {
|
||||
extractor, ok := t.extractors[format]
|
||||
if !ok {
|
||||
return nil, opentracing.ErrUnsupportedFormat
|
||||
}
|
||||
return extractor.Extract(carrier)
|
||||
}
|
||||
|
||||
func (t *MockTracer) recordSpan(span *MockSpan) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
t.finishedSpans = append(t.finishedSpans, span)
|
||||
}
|
||||
120
vendor/github.com/opentracing/opentracing-go/mocktracer/propagation.go
generated
vendored
Normal file
120
vendor/github.com/opentracing/opentracing-go/mocktracer/propagation.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package mocktracer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/opentracing/opentracing-go"
|
||||
)
|
||||
|
||||
const mockTextMapIdsPrefix = "mockpfx-ids-"
|
||||
const mockTextMapBaggagePrefix = "mockpfx-baggage-"
|
||||
|
||||
var emptyContext = MockSpanContext{}
|
||||
|
||||
// Injector is responsible for injecting SpanContext instances in a manner suitable
|
||||
// for propagation via a format-specific "carrier" object. Typically the
|
||||
// injection will take place across an RPC boundary, but message queues and
|
||||
// other IPC mechanisms are also reasonable places to use an Injector.
|
||||
type Injector interface {
|
||||
// Inject takes `SpanContext` and injects it into `carrier`. The actual type
|
||||
// of `carrier` depends on the `format` passed to `Tracer.Inject()`.
|
||||
//
|
||||
// Implementations may return opentracing.ErrInvalidCarrier or any other
|
||||
// implementation-specific error if injection fails.
|
||||
Inject(ctx MockSpanContext, carrier interface{}) error
|
||||
}
|
||||
|
||||
// Extractor is responsible for extracting SpanContext instances from a
|
||||
// format-specific "carrier" object. Typically the extraction will take place
|
||||
// on the server side of an RPC boundary, but message queues and other IPC
|
||||
// mechanisms are also reasonable places to use an Extractor.
|
||||
type Extractor interface {
|
||||
// Extract decodes a SpanContext instance from the given `carrier`,
|
||||
// or (nil, opentracing.ErrSpanContextNotFound) if no context could
|
||||
// be found in the `carrier`.
|
||||
Extract(carrier interface{}) (MockSpanContext, error)
|
||||
}
|
||||
|
||||
// TextMapPropagator implements Injector/Extractor for TextMap and HTTPHeaders formats.
|
||||
type TextMapPropagator struct {
|
||||
HTTPHeaders bool
|
||||
}
|
||||
|
||||
// Inject implements the Injector interface
|
||||
func (t *TextMapPropagator) Inject(spanContext MockSpanContext, carrier interface{}) error {
|
||||
writer, ok := carrier.(opentracing.TextMapWriter)
|
||||
if !ok {
|
||||
return opentracing.ErrInvalidCarrier
|
||||
}
|
||||
// Ids:
|
||||
writer.Set(mockTextMapIdsPrefix+"traceid", strconv.Itoa(spanContext.TraceID))
|
||||
writer.Set(mockTextMapIdsPrefix+"spanid", strconv.Itoa(spanContext.SpanID))
|
||||
writer.Set(mockTextMapIdsPrefix+"sampled", fmt.Sprint(spanContext.Sampled))
|
||||
// Baggage:
|
||||
for baggageKey, baggageVal := range spanContext.Baggage {
|
||||
safeVal := baggageVal
|
||||
if t.HTTPHeaders {
|
||||
safeVal = url.QueryEscape(baggageVal)
|
||||
}
|
||||
writer.Set(mockTextMapBaggagePrefix+baggageKey, safeVal)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Extract implements the Extractor interface
|
||||
func (t *TextMapPropagator) Extract(carrier interface{}) (MockSpanContext, error) {
|
||||
reader, ok := carrier.(opentracing.TextMapReader)
|
||||
if !ok {
|
||||
return emptyContext, opentracing.ErrInvalidCarrier
|
||||
}
|
||||
rval := MockSpanContext{0, 0, true, nil}
|
||||
err := reader.ForeachKey(func(key, val string) error {
|
||||
lowerKey := strings.ToLower(key)
|
||||
switch {
|
||||
case lowerKey == mockTextMapIdsPrefix+"traceid":
|
||||
// Ids:
|
||||
i, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rval.TraceID = i
|
||||
case lowerKey == mockTextMapIdsPrefix+"spanid":
|
||||
// Ids:
|
||||
i, err := strconv.Atoi(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rval.SpanID = i
|
||||
case lowerKey == mockTextMapIdsPrefix+"sampled":
|
||||
b, err := strconv.ParseBool(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rval.Sampled = b
|
||||
case strings.HasPrefix(lowerKey, mockTextMapBaggagePrefix):
|
||||
// Baggage:
|
||||
if rval.Baggage == nil {
|
||||
rval.Baggage = make(map[string]string)
|
||||
}
|
||||
safeVal := val
|
||||
if t.HTTPHeaders {
|
||||
// unescape errors are ignored, nothing can be done
|
||||
if rawVal, err := url.QueryUnescape(val); err == nil {
|
||||
safeVal = rawVal
|
||||
}
|
||||
}
|
||||
rval.Baggage[lowerKey[len(mockTextMapBaggagePrefix):]] = safeVal
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if rval.TraceID == 0 || rval.SpanID == 0 {
|
||||
return emptyContext, opentracing.ErrSpanContextNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return emptyContext, err
|
||||
}
|
||||
return rval, nil
|
||||
}
|
||||
53
vendor/github.com/opentracing/opentracing-go/noop.go
generated
vendored
Normal file
53
vendor/github.com/opentracing/opentracing-go/noop.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package opentracing
|
||||
|
||||
import "github.com/opentracing/opentracing-go/log"
|
||||
|
||||
// A NoopTracer is a trivial implementation of Tracer for which all operations
|
||||
// are no-ops.
|
||||
type NoopTracer struct{}
|
||||
|
||||
type noopSpan struct{}
|
||||
type noopSpanContext struct{}
|
||||
|
||||
var (
|
||||
defaultNoopSpanContext = noopSpanContext{}
|
||||
defaultNoopSpan = noopSpan{}
|
||||
defaultNoopTracer = NoopTracer{}
|
||||
)
|
||||
|
||||
const (
|
||||
emptyString = ""
|
||||
)
|
||||
|
||||
// noopSpanContext:
|
||||
func (n noopSpanContext) ForeachBaggageItem(handler func(k, v string) bool) {}
|
||||
|
||||
// noopSpan:
|
||||
func (n noopSpan) Context() SpanContext { return defaultNoopSpanContext }
|
||||
func (n noopSpan) SetBaggageItem(key, val string) Span { return defaultNoopSpan }
|
||||
func (n noopSpan) BaggageItem(key string) string { return emptyString }
|
||||
func (n noopSpan) SetTag(key string, value interface{}) Span { return n }
|
||||
func (n noopSpan) LogFields(fields ...log.Field) {}
|
||||
func (n noopSpan) LogKV(keyVals ...interface{}) {}
|
||||
func (n noopSpan) Finish() {}
|
||||
func (n noopSpan) FinishWithOptions(opts FinishOptions) {}
|
||||
func (n noopSpan) SetOperationName(operationName string) Span { return n }
|
||||
func (n noopSpan) Tracer() Tracer { return defaultNoopTracer }
|
||||
func (n noopSpan) LogEvent(event string) {}
|
||||
func (n noopSpan) LogEventWithPayload(event string, payload interface{}) {}
|
||||
func (n noopSpan) Log(data LogData) {}
|
||||
|
||||
// StartSpan belongs to the Tracer interface.
|
||||
func (n NoopTracer) StartSpan(operationName string, opts ...StartSpanOption) Span {
|
||||
return defaultNoopSpan
|
||||
}
|
||||
|
||||
// Inject belongs to the Tracer interface.
|
||||
func (n NoopTracer) Inject(sp SpanContext, format interface{}, carrier interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Extract belongs to the Tracer interface.
|
||||
func (n NoopTracer) Extract(format interface{}, carrier interface{}) (SpanContext, error) {
|
||||
return nil, ErrSpanContextNotFound
|
||||
}
|
||||
176
vendor/github.com/opentracing/opentracing-go/propagation.go
generated
vendored
Normal file
176
vendor/github.com/opentracing/opentracing-go/propagation.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
package opentracing
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CORE PROPAGATION INTERFACES:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var (
|
||||
// ErrUnsupportedFormat occurs when the `format` passed to Tracer.Inject() or
|
||||
// Tracer.Extract() is not recognized by the Tracer implementation.
|
||||
ErrUnsupportedFormat = errors.New("opentracing: Unknown or unsupported Inject/Extract format")
|
||||
|
||||
// ErrSpanContextNotFound occurs when the `carrier` passed to
|
||||
// Tracer.Extract() is valid and uncorrupted but has insufficient
|
||||
// information to extract a SpanContext.
|
||||
ErrSpanContextNotFound = errors.New("opentracing: SpanContext not found in Extract carrier")
|
||||
|
||||
// ErrInvalidSpanContext errors occur when Tracer.Inject() is asked to
|
||||
// operate on a SpanContext which it is not prepared to handle (for
|
||||
// example, since it was created by a different tracer implementation).
|
||||
ErrInvalidSpanContext = errors.New("opentracing: SpanContext type incompatible with tracer")
|
||||
|
||||
// ErrInvalidCarrier errors occur when Tracer.Inject() or Tracer.Extract()
|
||||
// implementations expect a different type of `carrier` than they are
|
||||
// given.
|
||||
ErrInvalidCarrier = errors.New("opentracing: Invalid Inject/Extract carrier")
|
||||
|
||||
// ErrSpanContextCorrupted occurs when the `carrier` passed to
|
||||
// Tracer.Extract() is of the expected type but is corrupted.
|
||||
ErrSpanContextCorrupted = errors.New("opentracing: SpanContext data corrupted in Extract carrier")
|
||||
)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BUILTIN PROPAGATION FORMATS:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// BuiltinFormat is used to demarcate the values within package `opentracing`
|
||||
// that are intended for use with the Tracer.Inject() and Tracer.Extract()
|
||||
// methods.
|
||||
type BuiltinFormat byte
|
||||
|
||||
const (
|
||||
// Binary represents SpanContexts as opaque binary data.
|
||||
//
|
||||
// For Tracer.Inject(): the carrier must be an `io.Writer`.
|
||||
//
|
||||
// For Tracer.Extract(): the carrier must be an `io.Reader`.
|
||||
Binary BuiltinFormat = iota
|
||||
|
||||
// TextMap represents SpanContexts as key:value string pairs.
|
||||
//
|
||||
// Unlike HTTPHeaders, the TextMap format does not restrict the key or
|
||||
// value character sets in any way.
|
||||
//
|
||||
// For Tracer.Inject(): the carrier must be a `TextMapWriter`.
|
||||
//
|
||||
// For Tracer.Extract(): the carrier must be a `TextMapReader`.
|
||||
TextMap
|
||||
|
||||
// HTTPHeaders represents SpanContexts as HTTP header string pairs.
|
||||
//
|
||||
// Unlike TextMap, the HTTPHeaders format requires that the keys and values
|
||||
// be valid as HTTP headers as-is (i.e., character casing may be unstable
|
||||
// and special characters are disallowed in keys, values should be
|
||||
// URL-escaped, etc).
|
||||
//
|
||||
// For Tracer.Inject(): the carrier must be a `TextMapWriter`.
|
||||
//
|
||||
// For Tracer.Extract(): the carrier must be a `TextMapReader`.
|
||||
//
|
||||
// See HTTPHeaderCarrier for an implementation of both TextMapWriter
|
||||
// and TextMapReader that defers to an http.Header instance for storage.
|
||||
// For example, Inject():
|
||||
//
|
||||
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||||
// err := span.Tracer().Inject(
|
||||
// span, opentracing.HTTPHeaders, carrier)
|
||||
//
|
||||
// Or Extract():
|
||||
//
|
||||
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||||
// span, err := tracer.Extract(
|
||||
// opentracing.HTTPHeaders, carrier)
|
||||
//
|
||||
HTTPHeaders
|
||||
)
|
||||
|
||||
// TextMapWriter is the Inject() carrier for the TextMap builtin format. With
|
||||
// it, the caller can encode a SpanContext for propagation as entries in a map
|
||||
// of unicode strings.
|
||||
type TextMapWriter interface {
|
||||
// Set a key:value pair to the carrier. Multiple calls to Set() for the
|
||||
// same key leads to undefined behavior.
|
||||
//
|
||||
// NOTE: The backing store for the TextMapWriter may contain data unrelated
|
||||
// to SpanContext. As such, Inject() and Extract() implementations that
|
||||
// call the TextMapWriter and TextMapReader interfaces must agree on a
|
||||
// prefix or other convention to distinguish their own key:value pairs.
|
||||
Set(key, val string)
|
||||
}
|
||||
|
||||
// TextMapReader is the Extract() carrier for the TextMap builtin format. With it,
|
||||
// the caller can decode a propagated SpanContext as entries in a map of
|
||||
// unicode strings.
|
||||
type TextMapReader interface {
|
||||
// ForeachKey returns TextMap contents via repeated calls to the `handler`
|
||||
// function. If any call to `handler` returns a non-nil error, ForeachKey
|
||||
// terminates and returns that error.
|
||||
//
|
||||
// NOTE: The backing store for the TextMapReader may contain data unrelated
|
||||
// to SpanContext. As such, Inject() and Extract() implementations that
|
||||
// call the TextMapWriter and TextMapReader interfaces must agree on a
|
||||
// prefix or other convention to distinguish their own key:value pairs.
|
||||
//
|
||||
// The "foreach" callback pattern reduces unnecessary copying in some cases
|
||||
// and also allows implementations to hold locks while the map is read.
|
||||
ForeachKey(handler func(key, val string) error) error
|
||||
}
|
||||
|
||||
// TextMapCarrier allows the use of regular map[string]string
|
||||
// as both TextMapWriter and TextMapReader.
|
||||
type TextMapCarrier map[string]string
|
||||
|
||||
// ForeachKey conforms to the TextMapReader interface.
|
||||
func (c TextMapCarrier) ForeachKey(handler func(key, val string) error) error {
|
||||
for k, v := range c {
|
||||
if err := handler(k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set implements Set() of opentracing.TextMapWriter
|
||||
func (c TextMapCarrier) Set(key, val string) {
|
||||
c[key] = val
|
||||
}
|
||||
|
||||
// HTTPHeadersCarrier satisfies both TextMapWriter and TextMapReader.
|
||||
//
|
||||
// Example usage for server side:
|
||||
//
|
||||
// carrier := opentracing.HttpHeadersCarrier(httpReq.Header)
|
||||
// spanContext, err := tracer.Extract(opentracing.HttpHeaders, carrier)
|
||||
//
|
||||
// Example usage for client side:
|
||||
//
|
||||
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||||
// err := tracer.Inject(
|
||||
// span.Context(),
|
||||
// opentracing.HttpHeaders,
|
||||
// carrier)
|
||||
//
|
||||
type HTTPHeadersCarrier http.Header
|
||||
|
||||
// Set conforms to the TextMapWriter interface.
|
||||
func (c HTTPHeadersCarrier) Set(key, val string) {
|
||||
h := http.Header(c)
|
||||
h.Add(key, val)
|
||||
}
|
||||
|
||||
// ForeachKey conforms to the TextMapReader interface.
|
||||
func (c HTTPHeadersCarrier) ForeachKey(handler func(key, val string) error) error {
|
||||
for k, vals := range c {
|
||||
for _, v := range vals {
|
||||
if err := handler(k, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
185
vendor/github.com/opentracing/opentracing-go/span.go
generated
vendored
Normal file
185
vendor/github.com/opentracing/opentracing-go/span.go
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
package opentracing
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/opentracing/opentracing-go/log"
|
||||
)
|
||||
|
||||
// SpanContext represents Span state that must propagate to descendant Spans and across process
|
||||
// boundaries (e.g., a <trace_id, span_id, sampled> tuple).
|
||||
type SpanContext interface {
|
||||
// ForeachBaggageItem grants access to all baggage items stored in the
|
||||
// SpanContext.
|
||||
// The handler function will be called for each baggage key/value pair.
|
||||
// The ordering of items is not guaranteed.
|
||||
//
|
||||
// The bool return value indicates if the handler wants to continue iterating
|
||||
// through the rest of the baggage items; for example if the handler is trying to
|
||||
// find some baggage item by pattern matching the name, it can return false
|
||||
// as soon as the item is found to stop further iterations.
|
||||
ForeachBaggageItem(handler func(k, v string) bool)
|
||||
}
|
||||
|
||||
// Span represents an active, un-finished span in the OpenTracing system.
|
||||
//
|
||||
// Spans are created by the Tracer interface.
|
||||
type Span interface {
|
||||
// Sets the end timestamp and finalizes Span state.
|
||||
//
|
||||
// With the exception of calls to Context() (which are always allowed),
|
||||
// Finish() must be the last call made to any span instance, and to do
|
||||
// otherwise leads to undefined behavior.
|
||||
Finish()
|
||||
// FinishWithOptions is like Finish() but with explicit control over
|
||||
// timestamps and log data.
|
||||
FinishWithOptions(opts FinishOptions)
|
||||
|
||||
// Context() yields the SpanContext for this Span. Note that the return
|
||||
// value of Context() is still valid after a call to Span.Finish(), as is
|
||||
// a call to Span.Context() after a call to Span.Finish().
|
||||
Context() SpanContext
|
||||
|
||||
// Sets or changes the operation name.
|
||||
SetOperationName(operationName string) Span
|
||||
|
||||
// Adds a tag to the span.
|
||||
//
|
||||
// If there is a pre-existing tag set for `key`, it is overwritten.
|
||||
//
|
||||
// Tag values can be numeric types, strings, or bools. The behavior of
|
||||
// other tag value types is undefined at the OpenTracing level. If a
|
||||
// tracing system does not know how to handle a particular value type, it
|
||||
// may ignore the tag, but shall not panic.
|
||||
SetTag(key string, value interface{}) Span
|
||||
|
||||
// LogFields is an efficient and type-checked way to record key:value
|
||||
// logging data about a Span, though the programming interface is a little
|
||||
// more verbose than LogKV(). Here's an example:
|
||||
//
|
||||
// span.LogFields(
|
||||
// log.String("event", "soft error"),
|
||||
// log.String("type", "cache timeout"),
|
||||
// log.Int("waited.millis", 1500))
|
||||
//
|
||||
// Also see Span.FinishWithOptions() and FinishOptions.BulkLogData.
|
||||
LogFields(fields ...log.Field)
|
||||
|
||||
// LogKV is a concise, readable way to record key:value logging data about
|
||||
// a Span, though unfortunately this also makes it less efficient and less
|
||||
// type-safe than LogFields(). Here's an example:
|
||||
//
|
||||
// span.LogKV(
|
||||
// "event", "soft error",
|
||||
// "type", "cache timeout",
|
||||
// "waited.millis", 1500)
|
||||
//
|
||||
// For LogKV (as opposed to LogFields()), the parameters must appear as
|
||||
// key-value pairs, like
|
||||
//
|
||||
// span.LogKV(key1, val1, key2, val2, key3, val3, ...)
|
||||
//
|
||||
// The keys must all be strings. The values may be strings, numeric types,
|
||||
// bools, Go error instances, or arbitrary structs.
|
||||
//
|
||||
// (Note to implementors: consider the log.InterleavedKVToFields() helper)
|
||||
LogKV(alternatingKeyValues ...interface{})
|
||||
|
||||
// SetBaggageItem sets a key:value pair on this Span and its SpanContext
|
||||
// that also propagates to descendants of this Span.
|
||||
//
|
||||
// SetBaggageItem() enables powerful functionality given a full-stack
|
||||
// opentracing integration (e.g., arbitrary application data from a mobile
|
||||
// app can make it, transparently, all the way into the depths of a storage
|
||||
// system), and with it some powerful costs: use this feature with care.
|
||||
//
|
||||
// IMPORTANT NOTE #1: SetBaggageItem() will only propagate baggage items to
|
||||
// *future* causal descendants of the associated Span.
|
||||
//
|
||||
// IMPORTANT NOTE #2: Use this thoughtfully and with care. Every key and
|
||||
// value is copied into every local *and remote* child of the associated
|
||||
// Span, and that can add up to a lot of network and cpu overhead.
|
||||
//
|
||||
// Returns a reference to this Span for chaining.
|
||||
SetBaggageItem(restrictedKey, value string) Span
|
||||
|
||||
// Gets the value for a baggage item given its key. Returns the empty string
|
||||
// if the value isn't found in this Span.
|
||||
BaggageItem(restrictedKey string) string
|
||||
|
||||
// Provides access to the Tracer that created this Span.
|
||||
Tracer() Tracer
|
||||
|
||||
// Deprecated: use LogFields or LogKV
|
||||
LogEvent(event string)
|
||||
// Deprecated: use LogFields or LogKV
|
||||
LogEventWithPayload(event string, payload interface{})
|
||||
// Deprecated: use LogFields or LogKV
|
||||
Log(data LogData)
|
||||
}
|
||||
|
||||
// LogRecord is data associated with a single Span log. Every LogRecord
|
||||
// instance must specify at least one Field.
|
||||
type LogRecord struct {
|
||||
Timestamp time.Time
|
||||
Fields []log.Field
|
||||
}
|
||||
|
||||
// FinishOptions allows Span.FinishWithOptions callers to override the finish
|
||||
// timestamp and provide log data via a bulk interface.
|
||||
type FinishOptions struct {
|
||||
// FinishTime overrides the Span's finish time, or implicitly becomes
|
||||
// time.Now() if FinishTime.IsZero().
|
||||
//
|
||||
// FinishTime must resolve to a timestamp that's >= the Span's StartTime
|
||||
// (per StartSpanOptions).
|
||||
FinishTime time.Time
|
||||
|
||||
// LogRecords allows the caller to specify the contents of many LogFields()
|
||||
// calls with a single slice. May be nil.
|
||||
//
|
||||
// None of the LogRecord.Timestamp values may be .IsZero() (i.e., they must
|
||||
// be set explicitly). Also, they must be >= the Span's start timestamp and
|
||||
// <= the FinishTime (or time.Now() if FinishTime.IsZero()). Otherwise the
|
||||
// behavior of FinishWithOptions() is undefined.
|
||||
//
|
||||
// If specified, the caller hands off ownership of LogRecords at
|
||||
// FinishWithOptions() invocation time.
|
||||
//
|
||||
// If specified, the (deprecated) BulkLogData must be nil or empty.
|
||||
LogRecords []LogRecord
|
||||
|
||||
// BulkLogData is DEPRECATED.
|
||||
BulkLogData []LogData
|
||||
}
|
||||
|
||||
// LogData is DEPRECATED
|
||||
type LogData struct {
|
||||
Timestamp time.Time
|
||||
Event string
|
||||
Payload interface{}
|
||||
}
|
||||
|
||||
// ToLogRecord converts a deprecated LogData to a non-deprecated LogRecord
|
||||
func (ld *LogData) ToLogRecord() LogRecord {
|
||||
var literalTimestamp time.Time
|
||||
if ld.Timestamp.IsZero() {
|
||||
literalTimestamp = time.Now()
|
||||
} else {
|
||||
literalTimestamp = ld.Timestamp
|
||||
}
|
||||
rval := LogRecord{
|
||||
Timestamp: literalTimestamp,
|
||||
}
|
||||
if ld.Payload == nil {
|
||||
rval.Fields = []log.Field{
|
||||
log.String("event", ld.Event),
|
||||
}
|
||||
} else {
|
||||
rval.Fields = []log.Field{
|
||||
log.String("event", ld.Event),
|
||||
log.Object("payload", ld.Payload),
|
||||
}
|
||||
}
|
||||
return rval
|
||||
}
|
||||
305
vendor/github.com/opentracing/opentracing-go/tracer.go
generated
vendored
Normal file
305
vendor/github.com/opentracing/opentracing-go/tracer.go
generated
vendored
Normal file
@@ -0,0 +1,305 @@
|
||||
package opentracing
|
||||
|
||||
import "time"
|
||||
|
||||
// Tracer is a simple, thin interface for Span creation and SpanContext
|
||||
// propagation.
|
||||
type Tracer interface {
|
||||
|
||||
// Create, start, and return a new Span with the given `operationName` and
|
||||
// incorporate the given StartSpanOption `opts`. (Note that `opts` borrows
|
||||
// from the "functional options" pattern, per
|
||||
// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis)
|
||||
//
|
||||
// A Span with no SpanReference options (e.g., opentracing.ChildOf() or
|
||||
// opentracing.FollowsFrom()) becomes the root of its own trace.
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// var tracer opentracing.Tracer = ...
|
||||
//
|
||||
// // The root-span case:
|
||||
// sp := tracer.StartSpan("GetFeed")
|
||||
//
|
||||
// // The vanilla child span case:
|
||||
// sp := tracer.StartSpan(
|
||||
// "GetFeed",
|
||||
// opentracing.ChildOf(parentSpan.Context()))
|
||||
//
|
||||
// // All the bells and whistles:
|
||||
// sp := tracer.StartSpan(
|
||||
// "GetFeed",
|
||||
// opentracing.ChildOf(parentSpan.Context()),
|
||||
// opentracing.Tag("user_agent", loggedReq.UserAgent),
|
||||
// opentracing.StartTime(loggedReq.Timestamp),
|
||||
// )
|
||||
//
|
||||
StartSpan(operationName string, opts ...StartSpanOption) Span
|
||||
|
||||
// Inject() takes the `sm` SpanContext instance and injects it for
|
||||
// propagation within `carrier`. The actual type of `carrier` depends on
|
||||
// the value of `format`.
|
||||
//
|
||||
// OpenTracing defines a common set of `format` values (see BuiltinFormat),
|
||||
// and each has an expected carrier type.
|
||||
//
|
||||
// Other packages may declare their own `format` values, much like the keys
|
||||
// used by `context.Context` (see
|
||||
// https://godoc.org/golang.org/x/net/context#WithValue).
|
||||
//
|
||||
// Example usage (sans error handling):
|
||||
//
|
||||
// carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
|
||||
// err := tracer.Inject(
|
||||
// span.Context(),
|
||||
// opentracing.HttpHeaders,
|
||||
// carrier)
|
||||
//
|
||||
// NOTE: All opentracing.Tracer implementations MUST support all
|
||||
// BuiltinFormats.
|
||||
//
|
||||
// Implementations may return opentracing.ErrUnsupportedFormat if `format`
|
||||
// is not supported by (or not known by) the implementation.
|
||||
//
|
||||
// Implementations may return opentracing.ErrInvalidCarrier or any other
|
||||
// implementation-specific error if the format is supported but injection
|
||||
// fails anyway.
|
||||
//
|
||||
// See Tracer.Extract().
|
||||
Inject(sm SpanContext, format interface{}, carrier interface{}) error
|
||||
|
||||
// Extract() returns a SpanContext instance given `format` and `carrier`.
|
||||
//
|
||||
// OpenTracing defines a common set of `format` values (see BuiltinFormat),
|
||||
// and each has an expected carrier type.
|
||||
//
|
||||
// Other packages may declare their own `format` values, much like the keys
|
||||
// used by `context.Context` (see
|
||||
// https://godoc.org/golang.org/x/net/context#WithValue).
|
||||
//
|
||||
// Example usage (with StartSpan):
|
||||
//
|
||||
//
|
||||
// carrier := opentracing.HttpHeadersCarrier(httpReq.Header)
|
||||
// clientContext, err := tracer.Extract(opentracing.HttpHeaders, carrier)
|
||||
//
|
||||
// // ... assuming the ultimate goal here is to resume the trace with a
|
||||
// // server-side Span:
|
||||
// var serverSpan opentracing.Span
|
||||
// if err == nil {
|
||||
// span = tracer.StartSpan(
|
||||
// rpcMethodName, ext.RPCServerOption(clientContext))
|
||||
// } else {
|
||||
// span = tracer.StartSpan(rpcMethodName)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// NOTE: All opentracing.Tracer implementations MUST support all
|
||||
// BuiltinFormats.
|
||||
//
|
||||
// Return values:
|
||||
// - A successful Extract returns a SpanContext instance and a nil error
|
||||
// - If there was simply no SpanContext to extract in `carrier`, Extract()
|
||||
// returns (nil, opentracing.ErrSpanContextNotFound)
|
||||
// - If `format` is unsupported or unrecognized, Extract() returns (nil,
|
||||
// opentracing.ErrUnsupportedFormat)
|
||||
// - If there are more fundamental problems with the `carrier` object,
|
||||
// Extract() may return opentracing.ErrInvalidCarrier,
|
||||
// opentracing.ErrSpanContextCorrupted, or implementation-specific
|
||||
// errors.
|
||||
//
|
||||
// See Tracer.Inject().
|
||||
Extract(format interface{}, carrier interface{}) (SpanContext, error)
|
||||
}
|
||||
|
||||
// StartSpanOptions allows Tracer.StartSpan() callers and implementors a
|
||||
// mechanism to override the start timestamp, specify Span References, and make
|
||||
// a single Tag or multiple Tags available at Span start time.
|
||||
//
|
||||
// StartSpan() callers should look at the StartSpanOption interface and
|
||||
// implementations available in this package.
|
||||
//
|
||||
// Tracer implementations can convert a slice of `StartSpanOption` instances
|
||||
// into a `StartSpanOptions` struct like so:
|
||||
//
|
||||
// func StartSpan(opName string, opts ...opentracing.StartSpanOption) {
|
||||
// sso := opentracing.StartSpanOptions{}
|
||||
// for _, o := range opts {
|
||||
// o.Apply(&sso)
|
||||
// }
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
type StartSpanOptions struct {
|
||||
// Zero or more causal references to other Spans (via their SpanContext).
|
||||
// If empty, start a "root" Span (i.e., start a new trace).
|
||||
References []SpanReference
|
||||
|
||||
// StartTime overrides the Span's start time, or implicitly becomes
|
||||
// time.Now() if StartTime.IsZero().
|
||||
StartTime time.Time
|
||||
|
||||
// Tags may have zero or more entries; the restrictions on map values are
|
||||
// identical to those for Span.SetTag(). May be nil.
|
||||
//
|
||||
// If specified, the caller hands off ownership of Tags at
|
||||
// StartSpan() invocation time.
|
||||
Tags map[string]interface{}
|
||||
}
|
||||
|
||||
// StartSpanOption instances (zero or more) may be passed to Tracer.StartSpan.
|
||||
//
|
||||
// StartSpanOption borrows from the "functional options" pattern, per
|
||||
// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
|
||||
type StartSpanOption interface {
|
||||
Apply(*StartSpanOptions)
|
||||
}
|
||||
|
||||
// SpanReferenceType is an enum type describing different categories of
|
||||
// relationships between two Spans. If Span-2 refers to Span-1, the
|
||||
// SpanReferenceType describes Span-1 from Span-2's perspective. For example,
|
||||
// ChildOfRef means that Span-1 created Span-2.
|
||||
//
|
||||
// NOTE: Span-1 and Span-2 do *not* necessarily depend on each other for
|
||||
// completion; e.g., Span-2 may be part of a background job enqueued by Span-1,
|
||||
// or Span-2 may be sitting in a distributed queue behind Span-1.
|
||||
type SpanReferenceType int
|
||||
|
||||
const (
|
||||
// ChildOfRef refers to a parent Span that caused *and* somehow depends
|
||||
// upon the new child Span. Often (but not always), the parent Span cannot
|
||||
// finish until the child Span does.
|
||||
//
|
||||
// An timing diagram for a ChildOfRef that's blocked on the new Span:
|
||||
//
|
||||
// [-Parent Span---------]
|
||||
// [-Child Span----]
|
||||
//
|
||||
// See http://opentracing.io/spec/
|
||||
//
|
||||
// See opentracing.ChildOf()
|
||||
ChildOfRef SpanReferenceType = iota
|
||||
|
||||
// FollowsFromRef refers to a parent Span that does not depend in any way
|
||||
// on the result of the new child Span. For instance, one might use
|
||||
// FollowsFromRefs to describe pipeline stages separated by queues,
|
||||
// or a fire-and-forget cache insert at the tail end of a web request.
|
||||
//
|
||||
// A FollowsFromRef Span is part of the same logical trace as the new Span:
|
||||
// i.e., the new Span is somehow caused by the work of its FollowsFromRef.
|
||||
//
|
||||
// All of the following could be valid timing diagrams for children that
|
||||
// "FollowFrom" a parent.
|
||||
//
|
||||
// [-Parent Span-] [-Child Span-]
|
||||
//
|
||||
//
|
||||
// [-Parent Span--]
|
||||
// [-Child Span-]
|
||||
//
|
||||
//
|
||||
// [-Parent Span-]
|
||||
// [-Child Span-]
|
||||
//
|
||||
// See http://opentracing.io/spec/
|
||||
//
|
||||
// See opentracing.FollowsFrom()
|
||||
FollowsFromRef
|
||||
)
|
||||
|
||||
// SpanReference is a StartSpanOption that pairs a SpanReferenceType and a
|
||||
// referenced SpanContext. See the SpanReferenceType documentation for
|
||||
// supported relationships. If SpanReference is created with
|
||||
// ReferencedContext==nil, it has no effect. Thus it allows for a more concise
|
||||
// syntax for starting spans:
|
||||
//
|
||||
// sc, _ := tracer.Extract(someFormat, someCarrier)
|
||||
// span := tracer.StartSpan("operation", opentracing.ChildOf(sc))
|
||||
//
|
||||
// The `ChildOf(sc)` option above will not panic if sc == nil, it will just
|
||||
// not add the parent span reference to the options.
|
||||
type SpanReference struct {
|
||||
Type SpanReferenceType
|
||||
ReferencedContext SpanContext
|
||||
}
|
||||
|
||||
// Apply satisfies the StartSpanOption interface.
|
||||
func (r SpanReference) Apply(o *StartSpanOptions) {
|
||||
if r.ReferencedContext != nil {
|
||||
o.References = append(o.References, r)
|
||||
}
|
||||
}
|
||||
|
||||
// ChildOf returns a StartSpanOption pointing to a dependent parent span.
|
||||
// If sc == nil, the option has no effect.
|
||||
//
|
||||
// See ChildOfRef, SpanReference
|
||||
func ChildOf(sc SpanContext) SpanReference {
|
||||
return SpanReference{
|
||||
Type: ChildOfRef,
|
||||
ReferencedContext: sc,
|
||||
}
|
||||
}
|
||||
|
||||
// FollowsFrom returns a StartSpanOption pointing to a parent Span that caused
|
||||
// the child Span but does not directly depend on its result in any way.
|
||||
// If sc == nil, the option has no effect.
|
||||
//
|
||||
// See FollowsFromRef, SpanReference
|
||||
func FollowsFrom(sc SpanContext) SpanReference {
|
||||
return SpanReference{
|
||||
Type: FollowsFromRef,
|
||||
ReferencedContext: sc,
|
||||
}
|
||||
}
|
||||
|
||||
// StartTime is a StartSpanOption that sets an explicit start timestamp for the
|
||||
// new Span.
|
||||
type StartTime time.Time
|
||||
|
||||
// Apply satisfies the StartSpanOption interface.
|
||||
func (t StartTime) Apply(o *StartSpanOptions) {
|
||||
o.StartTime = time.Time(t)
|
||||
}
|
||||
|
||||
// Tags are a generic map from an arbitrary string key to an opaque value type.
|
||||
// The underlying tracing system is responsible for interpreting and
|
||||
// serializing the values.
|
||||
type Tags map[string]interface{}
|
||||
|
||||
// Apply satisfies the StartSpanOption interface.
|
||||
func (t Tags) Apply(o *StartSpanOptions) {
|
||||
if o.Tags == nil {
|
||||
o.Tags = make(map[string]interface{})
|
||||
}
|
||||
for k, v := range t {
|
||||
o.Tags[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// Tag may be passed as a StartSpanOption to add a tag to new spans,
|
||||
// or its Set method may be used to apply the tag to an existing Span,
|
||||
// for example:
|
||||
//
|
||||
// tracer.StartSpan("opName", Tag{"Key", value})
|
||||
//
|
||||
// or
|
||||
//
|
||||
// Tag{"key", value}.Set(span)
|
||||
type Tag struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// Apply satisfies the StartSpanOption interface.
|
||||
func (t Tag) Apply(o *StartSpanOptions) {
|
||||
if o.Tags == nil {
|
||||
o.Tags = make(map[string]interface{})
|
||||
}
|
||||
o.Tags[t.Key] = t.Value
|
||||
}
|
||||
|
||||
// Set applies the tag to an existing Span.
|
||||
func (t Tag) Set(s Span) {
|
||||
s.SetTag(t.Key, t.Value)
|
||||
}
|
||||
8
vendor/manifest
vendored
8
vendor/manifest
vendored
@@ -1116,6 +1116,14 @@
|
||||
"branch": "master",
|
||||
"path": "/libcontainer/utils"
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/opentracing/opentracing-go",
|
||||
"repository": "https://github.com/opentracing/opentracing-go",
|
||||
"vcs": "git",
|
||||
"revision": "902ca977fd85455c364050f985eba376b44315f0",
|
||||
"branch": "master",
|
||||
"notests": true
|
||||
},
|
||||
{
|
||||
"importpath": "github.com/paypal/ionet",
|
||||
"repository": "https://github.com/paypal/ionet",
|
||||
|
||||
Reference in New Issue
Block a user