rclone/vendor/github.com/spacemonkeygo/monkit/v3/span.go
2020-05-12 15:56:50 +00:00

147 lines
3.3 KiB
Go

// Copyright (C) 2015 Space Monkey, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package monkit
import (
"fmt"
"sort"
"time"
)
type ctxKey int
const (
spanKey ctxKey = iota
)
// Annotation represents an arbitrary name and value string pair
type Annotation struct {
Name string
Value string
}
func (s *Span) addChild(child *Span) {
s.mtx.Lock()
s.children.Add(child)
done := s.done
s.mtx.Unlock()
if done {
child.orphan()
}
}
func (s *Span) removeChild(child *Span) {
s.mtx.Lock()
s.children.Remove(child)
s.mtx.Unlock()
}
func (s *Span) orphan() {
s.mtx.Lock()
if !s.done && !s.orphaned {
s.orphaned = true
s.f.scope.r.orphanedSpan(s)
}
s.mtx.Unlock()
}
// Duration returns the current amount of time the Span has been running
func (s *Span) Duration() time.Duration {
return time.Since(s.start)
}
// Start returns the time the Span started.
func (s *Span) Start() time.Time {
return s.start
}
// Value implements context.Context
func (s *Span) Value(key interface{}) interface{} {
if key == spanKey {
return s
}
return s.Context.Value(key)
}
// String implements context.Context
func (s *Span) String() string {
// TODO: for working with Contexts
return fmt.Sprintf("%v.WithSpan()", s.Context)
}
// Children returns all known running child Spans.
func (s *Span) Children(cb func(s *Span)) {
found := map[*Span]bool{}
var sorter []*Span
s.mtx.Lock()
s.children.Iterate(func(s *Span) {
if !found[s] {
found[s] = true
sorter = append(sorter, s)
}
})
s.mtx.Unlock()
sort.Sort(spanSorter(sorter))
for _, s := range sorter {
cb(s)
}
}
// Args returns the list of strings associated with the args given to the
// Task that created this Span.
func (s *Span) Args() (rv []string) {
rv = make([]string, 0, len(s.args))
for _, arg := range s.args {
rv = append(rv, fmt.Sprintf("%#v", arg))
}
return rv
}
// Id returns the Span id.
func (s *Span) Id() int64 { return s.id }
// Func returns the Func that kicked off this Span.
func (s *Span) Func() *Func { return s.f }
// Trace returns the Trace this Span is associated with.
func (s *Span) Trace() *Trace { return s.trace }
// Parent returns the Parent Span.
func (s *Span) Parent() *Span { return s.parent }
// Annotations returns any added annotations created through the Span Annotate
// method
func (s *Span) Annotations() []Annotation {
s.mtx.Lock()
annotations := s.annotations // okay cause we only ever append to this slice
s.mtx.Unlock()
return append([]Annotation(nil), annotations...)
}
// Annotate adds an annotation to the existing Span.
func (s *Span) Annotate(name, val string) {
s.mtx.Lock()
s.annotations = append(s.annotations, Annotation{Name: name, Value: val})
s.mtx.Unlock()
}
// Orphaned returns true if the Parent span ended before this Span did.
func (s *Span) Orphaned() (rv bool) {
s.mtx.Lock()
rv = s.orphaned
s.mtx.Unlock()
return rv
}