mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Instrument Prometheus with OpenTracing (#2554)
* Use request.Context() instead of a global map of contexts. * Add some basic opentracing instrumentation on the query path. * Remove tracehandler endpoint.
This commit is contained in:
parent
0b9fca983b
commit
4d9b917d11
|
@ -21,6 +21,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
@ -34,6 +35,7 @@ import (
|
||||||
const (
|
const (
|
||||||
namespace = "prometheus"
|
namespace = "prometheus"
|
||||||
subsystem = "engine"
|
subsystem = "engine"
|
||||||
|
queryTag = "query"
|
||||||
|
|
||||||
// The largest SampleValue that can be converted to an int64 without overflow.
|
// The largest SampleValue that can be converted to an int64 without overflow.
|
||||||
maxInt64 model.SampleValue = 9223372036854774784
|
maxInt64 model.SampleValue = 9223372036854774784
|
||||||
|
@ -272,6 +274,10 @@ func (q *query) Cancel() {
|
||||||
|
|
||||||
// Exec implements the Query interface.
|
// Exec implements the Query interface.
|
||||||
func (q *query) Exec(ctx context.Context) *Result {
|
func (q *query) Exec(ctx context.Context) *Result {
|
||||||
|
if span := opentracing.SpanFromContext(ctx); span != nil {
|
||||||
|
span.SetTag(queryTag, q.stmt.String())
|
||||||
|
}
|
||||||
|
|
||||||
res, err := q.ng.exec(ctx, q)
|
res, err := q.ng.exec(ctx, q)
|
||||||
return &Result{Err: err, Value: res}
|
return &Result{Err: err, Value: res}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
@ -78,6 +79,12 @@ const (
|
||||||
// real-life production scenario.
|
// real-life production scenario.
|
||||||
fpEqualMatchThreshold = 1000
|
fpEqualMatchThreshold = 1000
|
||||||
fpOtherMatchThreshold = 10000
|
fpOtherMatchThreshold = 10000
|
||||||
|
|
||||||
|
selectorsTag = "selectors"
|
||||||
|
fromTag = "from"
|
||||||
|
throughTag = "through"
|
||||||
|
tsTag = "ts"
|
||||||
|
numSeries = "num_series"
|
||||||
)
|
)
|
||||||
|
|
||||||
type quarantineRequest struct {
|
type quarantineRequest struct {
|
||||||
|
@ -567,7 +574,13 @@ func (bit *boundedIterator) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryRange implements Storage.
|
// QueryRange implements Storage.
|
||||||
func (s *MemorySeriesStorage) QueryRange(_ context.Context, from, through model.Time, matchers ...*metric.LabelMatcher) ([]SeriesIterator, error) {
|
func (s *MemorySeriesStorage) QueryRange(ctx context.Context, from, through model.Time, matchers ...*metric.LabelMatcher) ([]SeriesIterator, error) {
|
||||||
|
span, _ := opentracing.StartSpanFromContext(ctx, "QueryRange")
|
||||||
|
span.SetTag(selectorsTag, metric.LabelMatchers(matchers).String())
|
||||||
|
span.SetTag(fromTag, int64(from))
|
||||||
|
span.SetTag(throughTag, int64(through))
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
if through.Before(from) {
|
if through.Before(from) {
|
||||||
// In that case, nothing will match.
|
// In that case, nothing will match.
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -576,6 +589,7 @@ func (s *MemorySeriesStorage) QueryRange(_ context.Context, from, through model.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
span.SetTag(numSeries, len(fpSeriesPairs))
|
||||||
iterators := make([]SeriesIterator, 0, len(fpSeriesPairs))
|
iterators := make([]SeriesIterator, 0, len(fpSeriesPairs))
|
||||||
for _, pair := range fpSeriesPairs {
|
for _, pair := range fpSeriesPairs {
|
||||||
it := s.preloadChunksForRange(pair, from, through)
|
it := s.preloadChunksForRange(pair, from, through)
|
||||||
|
@ -585,7 +599,12 @@ func (s *MemorySeriesStorage) QueryRange(_ context.Context, from, through model.
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryInstant implements Storage.
|
// QueryInstant implements Storage.
|
||||||
func (s *MemorySeriesStorage) QueryInstant(_ context.Context, ts model.Time, stalenessDelta time.Duration, matchers ...*metric.LabelMatcher) ([]SeriesIterator, error) {
|
func (s *MemorySeriesStorage) QueryInstant(ctx context.Context, ts model.Time, stalenessDelta time.Duration, matchers ...*metric.LabelMatcher) ([]SeriesIterator, error) {
|
||||||
|
span, _ := opentracing.StartSpanFromContext(ctx, "QueryInstant")
|
||||||
|
span.SetTag(selectorsTag, metric.LabelMatchers(matchers).String())
|
||||||
|
span.SetTag(tsTag, ts)
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
if stalenessDelta < 0 {
|
if stalenessDelta < 0 {
|
||||||
panic("negative staleness delta")
|
panic("negative staleness delta")
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,14 @@ func (lms LabelMatchers) Len() int { return len(lms) }
|
||||||
func (lms LabelMatchers) Swap(i, j int) { lms[i], lms[j] = lms[j], lms[i] }
|
func (lms LabelMatchers) Swap(i, j int) { lms[i], lms[j] = lms[j], lms[i] }
|
||||||
func (lms LabelMatchers) Less(i, j int) bool { return lms[i].score < lms[j].score }
|
func (lms LabelMatchers) Less(i, j int) bool { return lms[i].score < lms[j].score }
|
||||||
|
|
||||||
|
func (lms LabelMatchers) String() string {
|
||||||
|
result := make([]string, 0, len(lms))
|
||||||
|
for _, lm := range lms {
|
||||||
|
result = append(result, lm.String())
|
||||||
|
}
|
||||||
|
return strings.Join(result, ",")
|
||||||
|
}
|
||||||
|
|
||||||
// LabelMatcher models the matching of a label. Create with NewLabelMatcher.
|
// LabelMatcher models the matching of a label. Create with NewLabelMatcher.
|
||||||
type LabelMatcher struct {
|
type LabelMatcher struct {
|
||||||
Type MatchType
|
Type MatchType
|
||||||
|
|
27
vendor/github.com/opentracing-contrib/go-stdlib/LICENSE
generated
vendored
Normal file
27
vendor/github.com/opentracing-contrib/go-stdlib/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2016, opentracing-contrib
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of go-stdlib nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
250
vendor/github.com/opentracing-contrib/go-stdlib/nethttp/client.go
generated
vendored
Normal file
250
vendor/github.com/opentracing-contrib/go-stdlib/nethttp/client.go
generated
vendored
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package nethttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptrace"
|
||||||
|
|
||||||
|
"github.com/opentracing/opentracing-go"
|
||||||
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
)
|
||||||
|
|
||||||
|
type contextKey int
|
||||||
|
|
||||||
|
const (
|
||||||
|
keyTracer contextKey = iota
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transport wraps a RoundTripper. If a request is being traced with
|
||||||
|
// Tracer, Transport will inject the current span into the headers,
|
||||||
|
// and set HTTP related tags on the span.
|
||||||
|
type Transport struct {
|
||||||
|
// The actual RoundTripper to use for the request. A nil
|
||||||
|
// RoundTripper defaults to http.DefaultTransport.
|
||||||
|
http.RoundTripper
|
||||||
|
}
|
||||||
|
|
||||||
|
type clientOptions struct {
|
||||||
|
opName string
|
||||||
|
disableClientTrace bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientOption contols the behavior of TraceRequest.
|
||||||
|
type ClientOption func(*clientOptions)
|
||||||
|
|
||||||
|
// OperationName returns a ClientOption that sets the operation
|
||||||
|
// name for the client-side span.
|
||||||
|
func OperationName(opName string) ClientOption {
|
||||||
|
return func(options *clientOptions) {
|
||||||
|
options.opName = opName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientTrace returns a ClientOption that turns on or off
|
||||||
|
// extra instrumentation via httptrace.WithClientTrace.
|
||||||
|
func ClientTrace(enabled bool) ClientOption {
|
||||||
|
return func(options *clientOptions) {
|
||||||
|
options.disableClientTrace = !enabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TraceRequest adds a ClientTracer to req, tracing the request and
|
||||||
|
// all requests caused due to redirects. When tracing requests this
|
||||||
|
// way you must also use Transport.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// func AskGoogle(ctx context.Context) error {
|
||||||
|
// client := &http.Client{Transport: &nethttp.Transport{}}
|
||||||
|
// req, err := http.NewRequest("GET", "http://google.com", nil)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// req = req.WithContext(ctx) // extend existing trace, if any
|
||||||
|
//
|
||||||
|
// req, ht := nethttp.TraceRequest(tracer, req)
|
||||||
|
// defer ht.Finish()
|
||||||
|
//
|
||||||
|
// res, err := client.Do(req)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// res.Body.Close()
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
func TraceRequest(tr opentracing.Tracer, req *http.Request, options ...ClientOption) (*http.Request, *Tracer) {
|
||||||
|
opts := &clientOptions{}
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(opts)
|
||||||
|
}
|
||||||
|
ht := &Tracer{tr: tr, opts: opts}
|
||||||
|
ctx := req.Context()
|
||||||
|
if !opts.disableClientTrace {
|
||||||
|
ctx = httptrace.WithClientTrace(ctx, ht.clientTrace())
|
||||||
|
}
|
||||||
|
req = req.WithContext(context.WithValue(ctx, keyTracer, ht))
|
||||||
|
return req, ht
|
||||||
|
}
|
||||||
|
|
||||||
|
type closeTracker struct {
|
||||||
|
io.ReadCloser
|
||||||
|
sp opentracing.Span
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c closeTracker) Close() error {
|
||||||
|
err := c.ReadCloser.Close()
|
||||||
|
c.sp.LogEvent("Closed body")
|
||||||
|
c.sp.Finish()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoundTrip implements the RoundTripper interface.
|
||||||
|
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
|
rt := t.RoundTripper
|
||||||
|
if rt == nil {
|
||||||
|
rt = http.DefaultTransport
|
||||||
|
}
|
||||||
|
tracer, ok := req.Context().Value(keyTracer).(*Tracer)
|
||||||
|
if !ok {
|
||||||
|
return rt.RoundTrip(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
tracer.start(req)
|
||||||
|
|
||||||
|
ext.HTTPMethod.Set(tracer.sp, req.Method)
|
||||||
|
ext.HTTPUrl.Set(tracer.sp, req.URL.String())
|
||||||
|
|
||||||
|
carrier := opentracing.HTTPHeadersCarrier(req.Header)
|
||||||
|
tracer.sp.Tracer().Inject(tracer.sp.Context(), opentracing.HTTPHeaders, carrier)
|
||||||
|
resp, err := rt.RoundTrip(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
tracer.sp.Finish()
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
ext.HTTPStatusCode.Set(tracer.sp, uint16(resp.StatusCode))
|
||||||
|
if req.Method == "HEAD" {
|
||||||
|
tracer.sp.Finish()
|
||||||
|
} else {
|
||||||
|
resp.Body = closeTracker{resp.Body, tracer.sp}
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tracer holds tracing details for one HTTP request.
|
||||||
|
type Tracer struct {
|
||||||
|
tr opentracing.Tracer
|
||||||
|
root opentracing.Span
|
||||||
|
sp opentracing.Span
|
||||||
|
opts *clientOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) start(req *http.Request) opentracing.Span {
|
||||||
|
if h.root == nil {
|
||||||
|
parent := opentracing.SpanFromContext(req.Context())
|
||||||
|
var spanctx opentracing.SpanContext
|
||||||
|
if parent != nil {
|
||||||
|
spanctx = parent.Context()
|
||||||
|
}
|
||||||
|
opName := h.opts.opName
|
||||||
|
if opName == "" {
|
||||||
|
opName = "HTTP Client"
|
||||||
|
}
|
||||||
|
root := h.tr.StartSpan(opName, opentracing.ChildOf(spanctx))
|
||||||
|
h.root = root
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := h.root.Context()
|
||||||
|
h.sp = h.tr.StartSpan("HTTP "+req.Method, opentracing.ChildOf(ctx))
|
||||||
|
ext.SpanKindRPCClient.Set(h.sp)
|
||||||
|
ext.Component.Set(h.sp, "net/http")
|
||||||
|
|
||||||
|
return h.sp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish finishes the span of the traced request.
|
||||||
|
func (h *Tracer) Finish() {
|
||||||
|
if h.root != nil {
|
||||||
|
h.root.Finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Span returns the root span of the traced request. This function
|
||||||
|
// should only be called after the request has been executed.
|
||||||
|
func (h *Tracer) Span() opentracing.Span {
|
||||||
|
return h.root
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) clientTrace() *httptrace.ClientTrace {
|
||||||
|
return &httptrace.ClientTrace{
|
||||||
|
GetConn: h.getConn,
|
||||||
|
GotConn: h.gotConn,
|
||||||
|
PutIdleConn: h.putIdleConn,
|
||||||
|
GotFirstResponseByte: h.gotFirstResponseByte,
|
||||||
|
Got100Continue: h.got100Continue,
|
||||||
|
DNSStart: h.dnsStart,
|
||||||
|
DNSDone: h.dnsDone,
|
||||||
|
ConnectStart: h.connectStart,
|
||||||
|
ConnectDone: h.connectDone,
|
||||||
|
WroteHeaders: h.wroteHeaders,
|
||||||
|
Wait100Continue: h.wait100Continue,
|
||||||
|
WroteRequest: h.wroteRequest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) getConn(hostPort string) {
|
||||||
|
ext.HTTPUrl.Set(h.sp, hostPort)
|
||||||
|
h.sp.LogEvent("Get conn")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) gotConn(info httptrace.GotConnInfo) {
|
||||||
|
h.sp.SetTag("net/http.reused", info.Reused)
|
||||||
|
h.sp.SetTag("net/http.was_idle", info.WasIdle)
|
||||||
|
h.sp.LogEvent("Got conn")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) putIdleConn(error) {
|
||||||
|
h.sp.LogEvent("Put idle conn")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) gotFirstResponseByte() {
|
||||||
|
h.sp.LogEvent("Got first response byte")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) got100Continue() {
|
||||||
|
h.sp.LogEvent("Got 100 continue")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) dnsStart(info httptrace.DNSStartInfo) {
|
||||||
|
h.sp.LogEventWithPayload("DNS start", info.Host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) dnsDone(httptrace.DNSDoneInfo) {
|
||||||
|
h.sp.LogEvent("DNS done")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) connectStart(network, addr string) {
|
||||||
|
h.sp.LogEventWithPayload("Connect start", network+":"+addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) connectDone(network, addr string, err error) {
|
||||||
|
h.sp.LogEventWithPayload("Connect done", network+":"+addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) wroteHeaders() {
|
||||||
|
h.sp.LogEvent("Wrote headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) wait100Continue() {
|
||||||
|
h.sp.LogEvent("Wait 100 continue")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Tracer) wroteRequest(info httptrace.WroteRequestInfo) {
|
||||||
|
if info.Err != nil {
|
||||||
|
ext.Error.Set(h.sp, true)
|
||||||
|
}
|
||||||
|
h.sp.LogEvent("Wrote request")
|
||||||
|
}
|
3
vendor/github.com/opentracing-contrib/go-stdlib/nethttp/doc.go
generated
vendored
Normal file
3
vendor/github.com/opentracing-contrib/go-stdlib/nethttp/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// Package nethttp provides OpenTracing instrumentation for the
|
||||||
|
// net/http package.
|
||||||
|
package nethttp
|
80
vendor/github.com/opentracing-contrib/go-stdlib/nethttp/server.go
generated
vendored
Normal file
80
vendor/github.com/opentracing-contrib/go-stdlib/nethttp/server.go
generated
vendored
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package nethttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
opentracing "github.com/opentracing/opentracing-go"
|
||||||
|
"github.com/opentracing/opentracing-go/ext"
|
||||||
|
)
|
||||||
|
|
||||||
|
type statusCodeTracker struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
status int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *statusCodeTracker) WriteHeader(status int) {
|
||||||
|
w.status = status
|
||||||
|
w.ResponseWriter.WriteHeader(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
type mwOptions struct {
|
||||||
|
opNameFunc func(r *http.Request) string
|
||||||
|
}
|
||||||
|
|
||||||
|
// MWOption contols the behavior of the Middleware.
|
||||||
|
type MWOption func(*mwOptions)
|
||||||
|
|
||||||
|
// OperationNameFunc returns a MWOption that uses given function f
|
||||||
|
// to generate operation name for each server-side span.
|
||||||
|
func OperationNameFunc(f func(r *http.Request) string) MWOption {
|
||||||
|
return func(options *mwOptions) {
|
||||||
|
options.opNameFunc = f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middleware wraps an http.Handler and traces incoming requests.
|
||||||
|
// Additionally, it adds the span to the request's context.
|
||||||
|
//
|
||||||
|
// By default, the operation name of the spans is set to "HTTP {method}".
|
||||||
|
// This can be overriden with options.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// http.ListenAndServe("localhost:80", nethttp.Middleware(tracer, http.DefaultServeMux))
|
||||||
|
//
|
||||||
|
// The options allow fine tuning the behavior of the middleware.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// mw := nethttp.Middleware(
|
||||||
|
// tracer,
|
||||||
|
// http.DefaultServeMux,
|
||||||
|
// nethttp.OperationName(func(r *http.Request) string {
|
||||||
|
// return "HTTP " + r.Method + ":/api/customers"
|
||||||
|
// }),
|
||||||
|
// )
|
||||||
|
func Middleware(tr opentracing.Tracer, h http.Handler, options ...MWOption) http.Handler {
|
||||||
|
opts := mwOptions{
|
||||||
|
opNameFunc: func(r *http.Request) string {
|
||||||
|
return "HTTP " + r.Method
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(&opts)
|
||||||
|
}
|
||||||
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx, _ := tr.Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(r.Header))
|
||||||
|
sp := tr.StartSpan(opts.opNameFunc(r), ext.RPCServerOption(ctx))
|
||||||
|
ext.HTTPMethod.Set(sp, r.Method)
|
||||||
|
ext.HTTPUrl.Set(sp, r.URL.String())
|
||||||
|
ext.Component.Set(sp, "net/http")
|
||||||
|
w = &statusCodeTracker{w, 200}
|
||||||
|
r = r.WithContext(opentracing.ContextWithSpan(r.Context(), sp))
|
||||||
|
|
||||||
|
h.ServeHTTP(w, r)
|
||||||
|
|
||||||
|
ext.HTTPStatusCode.Set(sp, uint16(w.(*statusCodeTracker).status))
|
||||||
|
sp.Finish()
|
||||||
|
}
|
||||||
|
return http.HandlerFunc(fn)
|
||||||
|
}
|
14
vendor/github.com/opentracing/opentracing-go/CHANGELOG.md
generated
vendored
Normal file
14
vendor/github.com/opentracing/opentracing-go/CHANGELOG.md
generated
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Changes by Version
|
||||||
|
==================
|
||||||
|
|
||||||
|
1.1.0 (unreleased)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- Deprecate InitGlobalTracer() in favor of SetGlobalTracer()
|
||||||
|
|
||||||
|
|
||||||
|
1.0.0 (2016-09-26)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- This release implements OpenTracing Specification 1.0 (http://opentracing.io/spec)
|
||||||
|
|
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.
|
32
vendor/github.com/opentracing/opentracing-go/Makefile
generated
vendored
Normal file
32
vendor/github.com/opentracing/opentracing-go/Makefile
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
PACKAGES := . ./mocktracer/... ./ext/...
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := test-and-lint
|
||||||
|
|
||||||
|
.PHONE: test-and-lint
|
||||||
|
|
||||||
|
test-and-lint: test lint
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -v -cover ./...
|
||||||
|
|
||||||
|
cover:
|
||||||
|
@rm -rf cover-all.out
|
||||||
|
$(foreach pkg, $(PACKAGES), $(MAKE) cover-pkg PKG=$(pkg) || true;)
|
||||||
|
@grep mode: cover.out > coverage.out
|
||||||
|
@cat cover-all.out >> coverage.out
|
||||||
|
go tool cover -html=coverage.out -o cover.html
|
||||||
|
@rm -rf cover.out cover-all.out coverage.out
|
||||||
|
|
||||||
|
cover-pkg:
|
||||||
|
go test -coverprofile cover.out $(PKG)
|
||||||
|
@grep -v mode: cover.out >> cover-all.out
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint:
|
||||||
|
go fmt ./...
|
||||||
|
golint ./...
|
||||||
|
@# Run again with magic to exit non-zero if golint outputs anything.
|
||||||
|
@! (golint ./... | read dummy)
|
||||||
|
go vet ./...
|
||||||
|
|
147
vendor/github.com/opentracing/opentracing-go/README.md
generated
vendored
Normal file
147
vendor/github.com/opentracing/opentracing-go/README.md
generated
vendored
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
[](https://gitter.im/opentracing/public) [](https://travis-ci.org/opentracing/opentracing-go) [](http://godoc.org/github.com/opentracing/opentracing-go)
|
||||||
|
|
||||||
|
# OpenTracing API for Go
|
||||||
|
|
||||||
|
This package is a Go platform API for OpenTracing.
|
||||||
|
|
||||||
|
## Required Reading
|
||||||
|
|
||||||
|
In order to understand the Go platform API, one must first be familiar with the
|
||||||
|
[OpenTracing project](http://opentracing.io) and
|
||||||
|
[terminology](http://opentracing.io/documentation/pages/spec.html) more specifically.
|
||||||
|
|
||||||
|
## API overview for those adding instrumentation
|
||||||
|
|
||||||
|
Everyday consumers of this `opentracing` package really only need to worry
|
||||||
|
about a couple of key abstractions: the `StartSpan` function, the `Span`
|
||||||
|
interface, and binding a `Tracer` at `main()`-time. Here are code snippets
|
||||||
|
demonstrating some important use cases.
|
||||||
|
|
||||||
|
#### Singleton initialization
|
||||||
|
|
||||||
|
The simplest starting point is `./default_tracer.go`. As early as possible, call
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "github.com/opentracing/opentracing-go"
|
||||||
|
import ".../some_tracing_impl"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
opentracing.InitGlobalTracer(
|
||||||
|
// tracing impl specific:
|
||||||
|
some_tracing_impl.New(...),
|
||||||
|
)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Non-Singleton initialization
|
||||||
|
|
||||||
|
If you prefer direct control to singletons, manage ownership of the
|
||||||
|
`opentracing.Tracer` implementation explicitly.
|
||||||
|
|
||||||
|
#### Creating a Span given an existing Go `context.Context`
|
||||||
|
|
||||||
|
If you use `context.Context` in your application, OpenTracing's Go library will
|
||||||
|
happily rely on it for `Span` propagation. To start a new (blocking child)
|
||||||
|
`Span`, you can use `StartSpanFromContext`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func xyz(ctx context.Context, ...) {
|
||||||
|
...
|
||||||
|
span, ctx := opentracing.StartSpanFromContext(ctx, "operation_name")
|
||||||
|
defer span.Finish()
|
||||||
|
span.LogFields(
|
||||||
|
log.String("event", "soft error"),
|
||||||
|
log.String("type", "cache timeout"),
|
||||||
|
log.Int("waited.millis", 1500))
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Starting an empty trace by creating a "root span"
|
||||||
|
|
||||||
|
It's always possible to create a "root" `Span` with no parent or other causal
|
||||||
|
reference.
|
||||||
|
|
||||||
|
```go
|
||||||
|
func xyz() {
|
||||||
|
...
|
||||||
|
sp := opentracing.StartSpan("operation_name")
|
||||||
|
defer sp.Finish()
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Creating a (child) Span given an existing (parent) Span
|
||||||
|
|
||||||
|
```go
|
||||||
|
func xyz(parentSpan opentracing.Span, ...) {
|
||||||
|
...
|
||||||
|
sp := opentracing.StartSpan(
|
||||||
|
"operation_name",
|
||||||
|
opentracing.ChildOf(parentSpan.Context()))
|
||||||
|
defer sp.Finish()
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Serializing to the wire
|
||||||
|
|
||||||
|
```go
|
||||||
|
func makeSomeRequest(ctx context.Context) ... {
|
||||||
|
if span := opentracing.SpanFromContext(ctx); span != nil {
|
||||||
|
httpClient := &http.Client{}
|
||||||
|
httpReq, _ := http.NewRequest("GET", "http://myservice/", nil)
|
||||||
|
|
||||||
|
// Transmit the span's TraceContext as HTTP headers on our
|
||||||
|
// outbound request.
|
||||||
|
tracer.Inject(
|
||||||
|
span.Context(),
|
||||||
|
opentracing.HTTPHeaders,
|
||||||
|
opentracing.HTTPHeadersCarrier(httpReq.Header))
|
||||||
|
|
||||||
|
resp, err := httpClient.Do(httpReq)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Deserializing from the wire
|
||||||
|
|
||||||
|
```go
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
var serverSpan opentracing.Span
|
||||||
|
appSpecificOperationName := ...
|
||||||
|
wireContext, err := opentracing.GlobalTracer().Extract(
|
||||||
|
opentracing.HTTPHeaders,
|
||||||
|
opentracing.HTTPHeadersCarrier(req.Header))
|
||||||
|
if err != nil {
|
||||||
|
// Optionally record something about err here
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the span referring to the RPC client if available.
|
||||||
|
// If wireContext == nil, a root span will be created.
|
||||||
|
serverSpan = opentracing.StartSpan(
|
||||||
|
appSpecificOperationName,
|
||||||
|
ext.RPCServerOption(wireContext))
|
||||||
|
|
||||||
|
defer serverSpan.Finish()
|
||||||
|
|
||||||
|
ctx := opentracing.ContextWithSpan(context.Background(), serverSpan)
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Goroutine-safety
|
||||||
|
|
||||||
|
The entire public API is goroutine-safe and does not require external
|
||||||
|
synchronization.
|
||||||
|
|
||||||
|
## API pointers for those implementing a tracing system
|
||||||
|
|
||||||
|
Tracing system implementors may be able to reuse or copy-paste-modify the `basictracer` package, found [here](https://github.com/opentracing/basictracer-go). In particular, see `basictracer.New(...)`.
|
||||||
|
|
||||||
|
## API compatibility
|
||||||
|
|
||||||
|
For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and `opentracing-go` mature, backwards compatibility will become more of a priority.
|
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)
|
||||||
|
}
|
32
vendor/github.com/opentracing/opentracing-go/globaltracer.go
generated
vendored
Normal file
32
vendor/github.com/opentracing/opentracing-go/globaltracer.go
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package opentracing
|
||||||
|
|
||||||
|
var (
|
||||||
|
globalTracer Tracer = NoopTracer{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetGlobalTracer sets the [singleton] opentracing.Tracer returned by
|
||||||
|
// GlobalTracer(). Those who use GlobalTracer (rather than directly manage an
|
||||||
|
// opentracing.Tracer instance) should call SetGlobalTracer as early as
|
||||||
|
// possible in main(), prior to calling the `StartSpan` global func below.
|
||||||
|
// Prior to calling `SetGlobalTracer`, any Spans started via the `StartSpan`
|
||||||
|
// (etc) globals are noops.
|
||||||
|
func SetGlobalTracer(tracer Tracer) {
|
||||||
|
globalTracer = tracer
|
||||||
|
}
|
||||||
|
|
||||||
|
// GlobalTracer returns the global singleton `Tracer` implementation.
|
||||||
|
// Before `SetGlobalTracer()` 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...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitGlobalTracer is deprecated. Please use SetGlobalTracer.
|
||||||
|
func InitGlobalTracer(tracer Tracer) {
|
||||||
|
SetGlobalTracer(tracer)
|
||||||
|
}
|
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)
|
||||||
|
}
|
245
vendor/github.com/opentracing/opentracing-go/log/field.go
generated
vendored
Normal file
245
vendor/github.com/opentracing/opentracing-go/log/field.go
generated
vendored
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
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:
|
||||||
|
if err, ok := lf.interfaceVal.(error); ok {
|
||||||
|
visitor.EmitString(lf.key, err.Error())
|
||||||
|
} else {
|
||||||
|
visitor.EmitString(lf.key, "<nil>")
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
64
vendor/github.com/opentracing/opentracing-go/noop.go
generated
vendored
Normal file
64
vendor/github.com/opentracing/opentracing-go/noop.go
generated
vendored
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package opentracing
|
||||||
|
|
||||||
|
import "github.com/opentracing/opentracing-go/log"
|
||||||
|
|
||||||
|
// A NoopTracer is a trivial, minimum overhead implementation of Tracer
|
||||||
|
// for which all operations are no-ops.
|
||||||
|
//
|
||||||
|
// The primary use of this implementation is in libraries, such as RPC
|
||||||
|
// frameworks, that make tracing an optional feature controlled by the
|
||||||
|
// end user. A no-op implementation allows said libraries to use it
|
||||||
|
// as the default Tracer and to write instrumentation that does
|
||||||
|
// not need to keep checking if the tracer instance is nil.
|
||||||
|
//
|
||||||
|
// For the same reason, the NoopTracer is the default "global" tracer
|
||||||
|
// (see GlobalTracer and SetGlobalTracer functions).
|
||||||
|
//
|
||||||
|
// WARNING: NoopTracer does not support baggage propagation.
|
||||||
|
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)
|
||||||
|
}
|
50
vendor/github.com/prometheus/common/route/route.go
generated
vendored
50
vendor/github.com/prometheus/common/route/route.go
generated
vendored
|
@ -1,26 +1,12 @@
|
||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
mtx = sync.RWMutex{}
|
|
||||||
ctxts = map[*http.Request]context.Context{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Context returns the context for the request.
|
|
||||||
func Context(r *http.Request) context.Context {
|
|
||||||
mtx.RLock()
|
|
||||||
defer mtx.RUnlock()
|
|
||||||
return ctxts[r]
|
|
||||||
}
|
|
||||||
|
|
||||||
type param string
|
type param string
|
||||||
|
|
||||||
// Param returns param p for the context.
|
// Param returns param p for the context.
|
||||||
|
@ -33,59 +19,35 @@ func WithParam(ctx context.Context, p, v string) context.Context {
|
||||||
return context.WithValue(ctx, param(p), v)
|
return context.WithValue(ctx, param(p), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextFunc returns a new context for a request.
|
|
||||||
type ContextFunc func(r *http.Request) (context.Context, error)
|
|
||||||
|
|
||||||
// Router wraps httprouter.Router and adds support for prefixed sub-routers
|
// Router wraps httprouter.Router and adds support for prefixed sub-routers
|
||||||
// and per-request context injections.
|
// and per-request context injections.
|
||||||
type Router struct {
|
type Router struct {
|
||||||
rtr *httprouter.Router
|
rtr *httprouter.Router
|
||||||
prefix string
|
prefix string
|
||||||
ctxFn ContextFunc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Router.
|
// New returns a new Router.
|
||||||
func New(ctxFn ContextFunc) *Router {
|
func New() *Router {
|
||||||
if ctxFn == nil {
|
|
||||||
ctxFn = func(r *http.Request) (context.Context, error) {
|
|
||||||
return context.Background(), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &Router{
|
return &Router{
|
||||||
rtr: httprouter.New(),
|
rtr: httprouter.New(),
|
||||||
ctxFn: ctxFn,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithPrefix returns a router that prefixes all registered routes with prefix.
|
// WithPrefix returns a router that prefixes all registered routes with prefix.
|
||||||
func (r *Router) WithPrefix(prefix string) *Router {
|
func (r *Router) WithPrefix(prefix string) *Router {
|
||||||
return &Router{rtr: r.rtr, prefix: r.prefix + prefix, ctxFn: r.ctxFn}
|
return &Router{rtr: r.rtr, prefix: r.prefix + prefix}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle turns a HandlerFunc into an httprouter.Handle.
|
// handle turns a HandlerFunc into an httprouter.Handle.
|
||||||
func (r *Router) handle(h http.HandlerFunc) httprouter.Handle {
|
func (r *Router) handle(h http.HandlerFunc) httprouter.Handle {
|
||||||
return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
|
return func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
|
||||||
reqCtx, err := r.ctxFn(req)
|
ctx, cancel := context.WithCancel(req.Context())
|
||||||
if err != nil {
|
|
||||||
http.Error(w, fmt.Sprintf("Error creating request context: %v", err), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ctx, cancel := context.WithCancel(reqCtx)
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
for _, p := range params {
|
for _, p := range params {
|
||||||
ctx = context.WithValue(ctx, param(p.Key), p.Value)
|
ctx = context.WithValue(ctx, param(p.Key), p.Value)
|
||||||
}
|
}
|
||||||
|
h(w, req.WithContext(ctx))
|
||||||
mtx.Lock()
|
|
||||||
ctxts[req] = ctx
|
|
||||||
mtx.Unlock()
|
|
||||||
|
|
||||||
h(w, req)
|
|
||||||
|
|
||||||
mtx.Lock()
|
|
||||||
delete(ctxts, req)
|
|
||||||
mtx.Unlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +94,7 @@ func FileServe(dir string) http.HandlerFunc {
|
||||||
fs := http.FileServer(http.Dir(dir))
|
fs := http.FileServer(http.Dir(dir))
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
r.URL.Path = Param(Context(r), "filepath")
|
r.URL.Path = Param(r.Context(), "filepath")
|
||||||
fs.ServeHTTP(w, r)
|
fs.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
46
vendor/vendor.json
vendored
46
vendor/vendor.json
vendored
|
@ -504,6 +504,30 @@
|
||||||
"revision": "672033dedc09500ca4d340760d0b80b9c0b198bd",
|
"revision": "672033dedc09500ca4d340760d0b80b9c0b198bd",
|
||||||
"revisionTime": "2017-02-13T20:16:50Z"
|
"revisionTime": "2017-02-13T20:16:50Z"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "IndbEEL1mdqqg4IpvyvbtEMGoo8=",
|
||||||
|
"path": "github.com/opentracing-contrib/go-stdlib/nethttp",
|
||||||
|
"revision": "1de4cc2120e71f745a5810488bf64b29b6d7d9f6",
|
||||||
|
"revisionTime": "2017-01-13T01:31:10Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "lzPj2yJz4Dy6ev0O0L4PNVzplAw=",
|
||||||
|
"path": "github.com/opentracing/opentracing-go",
|
||||||
|
"revision": "6edb48674bd9467b8e91fda004f2bd7202d60ce4",
|
||||||
|
"revisionTime": "2017-02-06T22:16:52Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "+q64ZAwI2qF5goM1mLjav88NOYQ=",
|
||||||
|
"path": "github.com/opentracing/opentracing-go/ext",
|
||||||
|
"revision": "6edb48674bd9467b8e91fda004f2bd7202d60ce4",
|
||||||
|
"revisionTime": "2017-02-06T22:16:52Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "+rbKrafLHDnrQFgeWawo9tfZhV4=",
|
||||||
|
"path": "github.com/opentracing/opentracing-go/log",
|
||||||
|
"revision": "6edb48674bd9467b8e91fda004f2bd7202d60ce4",
|
||||||
|
"revisionTime": "2017-02-06T22:16:52Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "3YJklSuzSE1Rt8A+2dhiWSmf/fw=",
|
"checksumSHA1": "3YJklSuzSE1Rt8A+2dhiWSmf/fw=",
|
||||||
"origin": "k8s.io/client-go/1.5/vendor/github.com/pborman/uuid",
|
"origin": "k8s.io/client-go/1.5/vendor/github.com/pborman/uuid",
|
||||||
|
@ -533,14 +557,14 @@
|
||||||
{
|
{
|
||||||
"checksumSHA1": "Wtpzndm/+bdwwNU5PCTfb4oUhc8=",
|
"checksumSHA1": "Wtpzndm/+bdwwNU5PCTfb4oUhc8=",
|
||||||
"path": "github.com/prometheus/common/expfmt",
|
"path": "github.com/prometheus/common/expfmt",
|
||||||
"revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf",
|
"revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8",
|
||||||
"revisionTime": "2017-02-20T10:38:46Z"
|
"revisionTime": "2017-04-18T15:52:10Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=",
|
"checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=",
|
||||||
"path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
|
"path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
|
||||||
"revision": "dd2f054febf4a6c00f2343686efb775948a8bff4",
|
"revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8",
|
||||||
"revisionTime": "2017-01-08T23:12:12Z"
|
"revisionTime": "2017-04-18T15:52:10Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "vfkLfDs6hXtxdJNGdWQglsxFu40=",
|
"checksumSHA1": "vfkLfDs6hXtxdJNGdWQglsxFu40=",
|
||||||
|
@ -551,20 +575,20 @@
|
||||||
{
|
{
|
||||||
"checksumSHA1": "0LL9u9tfv1KPBjNEiMDP6q7lpog=",
|
"checksumSHA1": "0LL9u9tfv1KPBjNEiMDP6q7lpog=",
|
||||||
"path": "github.com/prometheus/common/model",
|
"path": "github.com/prometheus/common/model",
|
||||||
"revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf",
|
"revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8",
|
||||||
"revisionTime": "2017-02-20T10:38:46Z"
|
"revisionTime": "2017-04-18T15:52:10Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "ZbbESWBHHcPUJ/A5yrzKhTHuPc8=",
|
"checksumSHA1": "9aDxDuzZt1l7FQJ9qpn2kPcF7NU=",
|
||||||
"path": "github.com/prometheus/common/route",
|
"path": "github.com/prometheus/common/route",
|
||||||
"revision": "dd2f054febf4a6c00f2343686efb775948a8bff4",
|
"revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8",
|
||||||
"revisionTime": "2017-01-08T23:12:12Z"
|
"revisionTime": "2017-04-18T15:52:10Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=",
|
"checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=",
|
||||||
"path": "github.com/prometheus/common/version",
|
"path": "github.com/prometheus/common/version",
|
||||||
"revision": "dd2f054febf4a6c00f2343686efb775948a8bff4",
|
"revision": "9e0844febd9e2856f839c9cb974fbd676d1755a8",
|
||||||
"revisionTime": "2017-01-08T23:12:12Z"
|
"revisionTime": "2017-04-18T15:52:10Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "W218eJZPXJG783fUr/z6IaAZyes=",
|
"checksumSHA1": "W218eJZPXJG783fUr/z6IaAZyes=",
|
||||||
|
|
|
@ -103,8 +103,7 @@ type API struct {
|
||||||
targetRetriever targetRetriever
|
targetRetriever targetRetriever
|
||||||
alertmanagerRetriever alertmanagerRetriever
|
alertmanagerRetriever alertmanagerRetriever
|
||||||
|
|
||||||
context func(r *http.Request) context.Context
|
now func() model.Time
|
||||||
now func() model.Time
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAPI returns an initialized API type.
|
// NewAPI returns an initialized API type.
|
||||||
|
@ -114,8 +113,7 @@ func NewAPI(qe *promql.Engine, st local.Storage, tr targetRetriever, ar alertman
|
||||||
Storage: st,
|
Storage: st,
|
||||||
targetRetriever: tr,
|
targetRetriever: tr,
|
||||||
alertmanagerRetriever: ar,
|
alertmanagerRetriever: ar,
|
||||||
context: route.Context,
|
now: model.Now,
|
||||||
now: model.Now,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,7 +170,7 @@ func (api *API) query(r *http.Request) (interface{}, *apiError) {
|
||||||
ts = api.now()
|
ts = api.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := api.context(r)
|
ctx := r.Context()
|
||||||
if to := r.FormValue("timeout"); to != "" {
|
if to := r.FormValue("timeout"); to != "" {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
timeout, err := parseDuration(to)
|
timeout, err := parseDuration(to)
|
||||||
|
@ -238,7 +236,7 @@ func (api *API) queryRange(r *http.Request) (interface{}, *apiError) {
|
||||||
return nil, &apiError{errorBadData, err}
|
return nil, &apiError{errorBadData, err}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := api.context(r)
|
ctx := r.Context()
|
||||||
if to := r.FormValue("timeout"); to != "" {
|
if to := r.FormValue("timeout"); to != "" {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
timeout, err := parseDuration(to)
|
timeout, err := parseDuration(to)
|
||||||
|
@ -272,7 +270,7 @@ func (api *API) queryRange(r *http.Request) (interface{}, *apiError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) labelValues(r *http.Request) (interface{}, *apiError) {
|
func (api *API) labelValues(r *http.Request) (interface{}, *apiError) {
|
||||||
name := route.Param(api.context(r), "name")
|
name := route.Param(r.Context(), "name")
|
||||||
|
|
||||||
if !model.LabelNameRE.MatchString(name) {
|
if !model.LabelNameRE.MatchString(name) {
|
||||||
return nil, &apiError{errorBadData, fmt.Errorf("invalid label name: %q", name)}
|
return nil, &apiError{errorBadData, fmt.Errorf("invalid label name: %q", name)}
|
||||||
|
@ -283,7 +281,7 @@ func (api *API) labelValues(r *http.Request) (interface{}, *apiError) {
|
||||||
}
|
}
|
||||||
defer q.Close()
|
defer q.Close()
|
||||||
|
|
||||||
vals, err := q.LabelValuesForLabelName(api.context(r), model.LabelName(name))
|
vals, err := q.LabelValuesForLabelName(r.Context(), model.LabelName(name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &apiError{errorExec, err}
|
return nil, &apiError{errorExec, err}
|
||||||
}
|
}
|
||||||
|
@ -335,7 +333,7 @@ func (api *API) series(r *http.Request) (interface{}, *apiError) {
|
||||||
}
|
}
|
||||||
defer q.Close()
|
defer q.Close()
|
||||||
|
|
||||||
res, err := q.MetricsForLabelMatchers(api.context(r), start, end, matcherSets...)
|
res, err := q.MetricsForLabelMatchers(r.Context(), start, end, matcherSets...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &apiError{errorExec, err}
|
return nil, &apiError{errorExec, err}
|
||||||
}
|
}
|
||||||
|
|
|
@ -483,15 +483,12 @@ func TestEndpoints(t *testing.T) {
|
||||||
for p, v := range test.params {
|
for p, v := range test.params {
|
||||||
ctx = route.WithParam(ctx, p, v)
|
ctx = route.WithParam(ctx, p, v)
|
||||||
}
|
}
|
||||||
api.context = func(r *http.Request) context.Context {
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest("ANY", fmt.Sprintf("http://example.com?%s", test.query.Encode()), nil)
|
req, err := http.NewRequest("ANY", fmt.Sprintf("http://example.com?%s", test.query.Encode()), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
resp, apiErr := test.endpoint(req)
|
resp, apiErr := test.endpoint(req.WithContext(ctx))
|
||||||
if apiErr != nil {
|
if apiErr != nil {
|
||||||
if test.errType == errorNone {
|
if test.errType == errorNone {
|
||||||
t.Fatalf("Unexpected error: %s", apiErr)
|
t.Fatalf("Unexpected error: %s", apiErr)
|
||||||
|
@ -703,7 +700,7 @@ func TestParseDuration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOptionsMethod(t *testing.T) {
|
func TestOptionsMethod(t *testing.T) {
|
||||||
r := route.New(nil)
|
r := route.New()
|
||||||
api := &API{}
|
api := &API{}
|
||||||
api.Register(r)
|
api.Register(r)
|
||||||
|
|
||||||
|
|
16
web/web.go
16
web/web.go
|
@ -32,6 +32,8 @@ import (
|
||||||
pprof_runtime "runtime/pprof"
|
pprof_runtime "runtime/pprof"
|
||||||
template_text "text/template"
|
template_text "text/template"
|
||||||
|
|
||||||
|
"github.com/opentracing-contrib/go-stdlib/nethttp"
|
||||||
|
"github.com/opentracing/opentracing-go"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/common/log"
|
"github.com/prometheus/common/log"
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
|
@ -127,10 +129,7 @@ type Options struct {
|
||||||
|
|
||||||
// New initializes a new web Handler.
|
// New initializes a new web Handler.
|
||||||
func New(o *Options) *Handler {
|
func New(o *Options) *Handler {
|
||||||
router := route.New(func(r *http.Request) (context.Context, error) {
|
router := route.New()
|
||||||
return o.Context, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
cwd, err := os.Getwd()
|
cwd, err := os.Getwd()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -218,7 +217,7 @@ func New(o *Options) *Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveStaticAsset(w http.ResponseWriter, req *http.Request) {
|
func serveStaticAsset(w http.ResponseWriter, req *http.Request) {
|
||||||
fp := route.Param(route.Context(req), "filepath")
|
fp := route.Param(req.Context(), "filepath")
|
||||||
fp = filepath.Join("web/ui/static", fp)
|
fp = filepath.Join("web/ui/static", fp)
|
||||||
|
|
||||||
info, err := ui.AssetInfo(fp)
|
info, err := ui.AssetInfo(fp)
|
||||||
|
@ -257,9 +256,12 @@ func (h *Handler) Reload() <-chan chan error {
|
||||||
// Run serves the HTTP endpoints.
|
// Run serves the HTTP endpoints.
|
||||||
func (h *Handler) Run() {
|
func (h *Handler) Run() {
|
||||||
log.Infof("Listening on %s", h.options.ListenAddress)
|
log.Infof("Listening on %s", h.options.ListenAddress)
|
||||||
|
operationName := nethttp.OperationNameFunc(func(r *http.Request) string {
|
||||||
|
return fmt.Sprintf("%s %s", r.Method, r.URL.Path)
|
||||||
|
})
|
||||||
server := &http.Server{
|
server := &http.Server{
|
||||||
Addr: h.options.ListenAddress,
|
Addr: h.options.ListenAddress,
|
||||||
Handler: h.router,
|
Handler: nethttp.Middleware(opentracing.GlobalTracer(), h.router, operationName),
|
||||||
ErrorLog: log.NewErrorLogger(),
|
ErrorLog: log.NewErrorLogger(),
|
||||||
ReadTimeout: h.options.ReadTimeout,
|
ReadTimeout: h.options.ReadTimeout,
|
||||||
}
|
}
|
||||||
|
@ -289,7 +291,7 @@ func (h *Handler) alerts(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) consoles(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) consoles(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := route.Context(r)
|
ctx := r.Context()
|
||||||
name := route.Param(ctx, "filepath")
|
name := route.Param(ctx, "filepath")
|
||||||
|
|
||||||
file, err := http.Dir(h.options.ConsoleTemplatesPath).Open(name)
|
file, err := http.Dir(h.options.ConsoleTemplatesPath).Open(name)
|
||||||
|
|
Loading…
Reference in a new issue