/
frame.go
130 lines (110 loc) · 2.41 KB
/
frame.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2013 The Go Circuit Project
// Use of this source code is governed by the license for
// The Go Circuit Project, found in the LICENSE file.
//
// Authors:
// 2013 Petar Maymounkov <p@gocircuit.org>
// Package trace implements an ad-hoc tracing system
package trace
import (
"bytes"
"fmt"
"log"
"os"
"reflect"
"unicode/utf8"
)
var _log = log.New(os.Stderr, "", log.LstdFlags|log.Llongfile)
// Framed is an object that has a Frame
type Framed interface {
Frame() Frame
}
// Frame …
type Frame interface {
Refine(sub ...string) Frame
Bind(interface{})
Println(v ...interface{})
Print(v ...interface{})
Printf(format string, v ...interface{})
String() string
Chain() []string
}
// frame implements Frame
type frame struct {
ptr uintptr
chain
}
func NewFrame(s ...string) Frame {
return &frame{chain: chain(s)}
}
func (f *frame) Refine(sub ...string) Frame {
c := make(chain, len(f.chain), len(f.chain)+len(sub))
copy(c, f.chain)
c = append(c, sub...)
return &frame{chain: c}
}
func (f *frame) Bind(v interface{}) {
if f.ptr != 0 {
panic("duplicate binding")
}
f.ptr = reflect.ValueOf(v).Pointer()
}
func justify(s string, l int) string {
var w bytes.Buffer
n := utf8.RuneCountInString(s)
for i := 0; i < max(0, l-n); i++ {
w.WriteRune('·')
}
w.WriteString(s)
return string(w.Bytes())
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
func (f *frame) String() string {
return fmt.Sprintf("(0x%010x) %s", f.ptr, f.chain.String())
}
func (f *frame) Println(v ...interface{}) {
if os.Getenv("TELE_NOTRACE") != "" {
return
}
_log.Output(2, fmt.Sprintln(append([]interface{}{f.String()}, v...)...))
}
func (f *frame) Print(v ...interface{}) {
if os.Getenv("TELE_NOTRACE") != "" {
return
}
_log.Output(2, fmt.Sprint(append([]interface{}{f.String()}, v...)...))
}
func (f *frame) Printf(format string, v ...interface{}) {
if os.Getenv("TELE_NOTRACE") != "" {
return
}
_log.Output(2, fmt.Sprintf("%s "+format, append([]interface{}{f.String()}, v...)...))
}
func (f *frame) Chain() []string {
return []string(f.chain)
}
// chain is an ordered sequence of strings with a String method
type chain []string
func (c chain) String() string {
var w bytes.Buffer
w.WriteString("(")
for i, s := range c {
if i > 0 {
w.WriteString("·")
}
w.WriteString(s)
}
w.WriteString(")")
return string(w.Bytes())
}