git-lfs/vendor/github.com/rubyist/tracerx/tracerx.go

152 lines
3.9 KiB
Go
Raw Normal View History

2014-10-04 16:59:35 +00:00
// Package tracerx implements a simple tracer function that uses environment
// variables to control the output. It is a generalized package inspired by
// git's GIT_TRACE mechanism.
//
// By default, tracerx will look for the TRACERX_TRACE environment variable.
// The default can by changed by setting the DefaultKey.
//
// The values control where the tracing is output as follows:
// unset, 0, or "false": no output
// 1, 2: stderr
// absolute path: output will be written to the file
// 3 - 10: output will be written to that file descriptor
//
// By default, messages will be prefixed with "trace: ". This prefix can be
// modified by setting Prefix.
//
// Each key can have an associated performance key, e.g. TRACERX_TRACE_PERFORMANCE.
// If this key is 1 or "true" performance output will be written to the same output
// as the tracing output.
2014-10-04 16:59:35 +00:00
package tracerx
import (
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
2014-10-04 16:59:35 +00:00
)
var (
DefaultKey = "TRACERX"
Prefix = "trace: "
tracers map[string]*tracer
tracerLock sync.Mutex
)
type tracer struct {
enabled bool
performance bool
w io.Writer
2014-10-04 16:59:35 +00:00
}
// Printf writes a trace message for the DefaultKey
func Printf(format string, args ...interface{}) {
PrintfKey(DefaultKey, format, args...)
}
// PrintfKey writes a trace message for the given key
func PrintfKey(key, format string, args ...interface{}) {
tracer := getTracer(key)
2014-10-04 16:59:35 +00:00
if tracer.enabled {
fmt.Fprintf(tracer.w, Prefix+format+"\n", args...)
return
}
}
// PerformanceSince writes out the time since the given time, if
// tracing for the default key is enabled and the performance key is set
func PerformanceSince(what string, t time.Time) {
PerformanceSinceKey(DefaultKey, what, t)
}
// PerformanceSince writes out the time since the given time, if
// tracing for the given key is enabled and the performance key is set
func PerformanceSinceKey(key, what string, t time.Time) {
tracer := getTracer(key)
2015-05-28 17:41:28 +00:00
if tracer.performance {
since := time.Since(t)
fmt.Fprintf(tracer.w, "performance %s: %.9f s\n", what, since.Seconds())
}
}
2014-10-04 16:59:35 +00:00
// Disable will disable tracing for the given key, regardless of
// the environment variable
func Disable(key string) {
uppedKey := strings.ToUpper(key)
if tracer, ok := tracers[uppedKey]; ok {
tracer.enabled = false
}
}
// Enable will enable tracing for the given key, regardless of
// the environment variable
func Enable(key string) {
uppedKey := strings.ToUpper(key)
if tracer, ok := tracers[uppedKey]; ok {
tracer.enabled = true
}
}
func getTracer(key string) *tracer {
uppedKey := strings.ToUpper(key)
2014-11-02 20:34:57 +00:00
tracerLock.Lock()
tracer, ok := tracers[uppedKey]
if !ok {
tracer = initializeTracer(uppedKey)
}
2014-11-02 20:34:57 +00:00
tracerLock.Unlock()
return tracer
}
2014-10-04 16:59:35 +00:00
func initializeTracer(key string) *tracer {
if tracer, ok := tracers[key]; ok {
return tracer // Someone else initialized while we were blocked
2014-10-04 16:59:35 +00:00
}
tracer := &tracer{false, false, os.Stderr}
2014-10-04 16:59:35 +00:00
tracers[key] = tracer
perf := os.Getenv(fmt.Sprintf("%s_TRACE_PERFORMANCE", key))
if perf == "1" || strings.ToLower(perf) == "true" {
tracer.performance = true
}
2015-06-02 15:15:02 +00:00
trace := os.Getenv(fmt.Sprintf("%s_TRACE", key))
2014-10-04 16:59:35 +00:00
fd, err := strconv.Atoi(trace)
if err != nil {
// Not a number, it could be a path for a log file
if filepath.IsAbs(trace) {
tracerOut, err := os.OpenFile(trace, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not open '%s' for tracing: %s\nDefaulting to tracing on stderr...\n", trace, err)
tracerOut = os.Stderr
}
tracer.w = tracerOut
tracer.enabled = true
} else if strings.ToLower(trace) == "true" {
tracer.enabled = true
}
} else {
switch fd {
case 0:
case 1, 2:
tracer.enabled = true
default:
tracer.w = os.NewFile(uintptr(fd), "trace")
tracer.enabled = true
}
}
return tracer
}
func init() {
tracers = make(map[string]*tracer, 0)
}