vendor tsgo
This commit is contained in:
34
tools/tsgo/internal/project/logging/logcollector.go
Normal file
34
tools/tsgo/internal/project/logging/logcollector.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LogCollector interface {
|
||||
fmt.Stringer
|
||||
Logger
|
||||
}
|
||||
|
||||
type logCollector struct {
|
||||
logger
|
||||
builder *strings.Builder
|
||||
}
|
||||
|
||||
func (lc *logCollector) String() string {
|
||||
return lc.builder.String()
|
||||
}
|
||||
|
||||
func NewTestLogger() LogCollector {
|
||||
var builder strings.Builder
|
||||
return &logCollector{
|
||||
logger: logger{
|
||||
writer: &builder,
|
||||
prefix: func() string {
|
||||
return formatTime(time.Unix(1349085672, 0))
|
||||
},
|
||||
},
|
||||
builder: &builder,
|
||||
}
|
||||
}
|
||||
135
tools/tsgo/internal/project/logging/logger.go
Normal file
135
tools/tsgo/internal/project/logging/logger.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Logger interface {
|
||||
// Error logs an error message.
|
||||
Error(msg ...any)
|
||||
// Errorf logs a formatted error message.
|
||||
Errorf(format string, args ...any)
|
||||
// Warn logs a warning message.
|
||||
Warn(msg ...any)
|
||||
// Warnf logs a formatted warning message.
|
||||
Warnf(format string, args ...any)
|
||||
// Info logs an info message.
|
||||
Info(msg ...any)
|
||||
// Infof logs a formatted info message.
|
||||
Infof(format string, args ...any)
|
||||
// Log prints a line to the output writer with a header.
|
||||
Log(msg ...any)
|
||||
// Logf prints a formatted line to the output writer with a header.
|
||||
Logf(format string, args ...any)
|
||||
|
||||
// Verbose returns the logger instance if verbose logging is enabled, and otherwise returns nil.
|
||||
// A nil logger created with `logging.NewLogger` is safe to call methods on.
|
||||
Verbose() Logger
|
||||
// IsVerbose returns true if verbose logging is enabled, and false otherwise.
|
||||
IsVerbose() bool
|
||||
// SetVerbose sets the verbose logging flag.
|
||||
SetVerbose(verbose bool)
|
||||
}
|
||||
|
||||
var _ Logger = (*logger)(nil)
|
||||
|
||||
type logger struct {
|
||||
mu sync.Mutex
|
||||
verbose bool
|
||||
writer io.Writer
|
||||
prefix func() string
|
||||
}
|
||||
|
||||
func (l *logger) Log(msg ...any) {
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
fmt.Fprintln(l.writer, l.prefix(), fmt.Sprint(msg...))
|
||||
}
|
||||
|
||||
func (l *logger) Logf(format string, args ...any) {
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
fmt.Fprintf(l.writer, "%s %s\n", l.prefix(), fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (l *logger) Verbose() Logger {
|
||||
if l == nil {
|
||||
return nil
|
||||
}
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
if !l.verbose {
|
||||
return nil
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *logger) IsVerbose() bool {
|
||||
if l == nil {
|
||||
return false
|
||||
}
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
return l.verbose
|
||||
}
|
||||
|
||||
func (l *logger) SetVerbose(verbose bool) {
|
||||
if l == nil {
|
||||
return
|
||||
}
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
l.verbose = verbose
|
||||
}
|
||||
|
||||
func (l *logger) Error(msg ...any) {
|
||||
l.Log(msg...)
|
||||
}
|
||||
|
||||
func (l *logger) Errorf(format string, args ...any) {
|
||||
l.Logf(format, args...)
|
||||
}
|
||||
|
||||
func (l *logger) Warn(msg ...any) {
|
||||
l.Log(msg...)
|
||||
}
|
||||
|
||||
func (l *logger) Warnf(format string, args ...any) {
|
||||
l.Logf(format, args...)
|
||||
}
|
||||
|
||||
func (l *logger) Info(msg ...any) {
|
||||
l.Log(msg...)
|
||||
}
|
||||
|
||||
func (l *logger) Infof(format string, args ...any) {
|
||||
l.Logf(format, args...)
|
||||
}
|
||||
|
||||
func NewLogger(output io.Writer) Logger {
|
||||
return &logger{
|
||||
writer: output,
|
||||
prefix: func() string {
|
||||
return formatTime(time.Now())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// NewNopLogger returns a no-op Logger that discards all log messages.
|
||||
// It is safe to call any method on the returned Logger.
|
||||
func NewNopLogger() Logger {
|
||||
return (*logger)(nil)
|
||||
}
|
||||
|
||||
func formatTime(t time.Time) string {
|
||||
return fmt.Sprintf("[%s]", t.Format("15:04:05.000"))
|
||||
}
|
||||
163
tools/tsgo/internal/project/logging/logtree.go
Normal file
163
tools/tsgo/internal/project/logging/logtree.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
var seq atomic.Uint64
|
||||
|
||||
type logEntry struct {
|
||||
seq uint64
|
||||
time time.Time
|
||||
message string
|
||||
child *LogTree
|
||||
}
|
||||
|
||||
func newLogEntry(child *LogTree, message string) *logEntry {
|
||||
return &logEntry{
|
||||
seq: seq.Add(1),
|
||||
time: time.Now(),
|
||||
message: message,
|
||||
child: child,
|
||||
}
|
||||
}
|
||||
|
||||
var _ LogCollector = (*LogTree)(nil)
|
||||
|
||||
type LogTree struct {
|
||||
name string
|
||||
mu sync.Mutex
|
||||
logs []*logEntry
|
||||
root *LogTree
|
||||
level int
|
||||
verbose bool
|
||||
|
||||
// Only set on root
|
||||
count atomic.Int32
|
||||
stringLength atomic.Int32
|
||||
}
|
||||
|
||||
func NewLogTree(name string) *LogTree {
|
||||
lc := &LogTree{
|
||||
name: name,
|
||||
}
|
||||
lc.root = lc
|
||||
return lc
|
||||
}
|
||||
|
||||
func (c *LogTree) add(log *logEntry) {
|
||||
// indent + header + message + newline
|
||||
c.root.stringLength.Add(int32(c.level + 15 + len(log.message) + 1))
|
||||
c.root.count.Add(1)
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.logs = append(c.logs, log)
|
||||
}
|
||||
|
||||
func (c *LogTree) Log(message ...any) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
log := newLogEntry(nil, fmt.Sprint(message...))
|
||||
c.add(log)
|
||||
}
|
||||
|
||||
func (c *LogTree) Logf(format string, args ...any) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
log := newLogEntry(nil, fmt.Sprintf(format, args...))
|
||||
c.add(log)
|
||||
}
|
||||
|
||||
func (c *LogTree) IsVerbose() bool {
|
||||
return c.verbose
|
||||
}
|
||||
|
||||
func (c *LogTree) SetVerbose(verbose bool) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
c.verbose = verbose
|
||||
}
|
||||
|
||||
func (c *LogTree) Verbose() Logger {
|
||||
if c == nil || !c.verbose {
|
||||
return nil
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *LogTree) Error(msg ...any) {
|
||||
c.Log(msg...)
|
||||
}
|
||||
|
||||
func (c *LogTree) Errorf(format string, args ...any) {
|
||||
c.Logf(format, args...)
|
||||
}
|
||||
|
||||
func (c *LogTree) Warn(msg ...any) {
|
||||
c.Log(msg...)
|
||||
}
|
||||
|
||||
func (c *LogTree) Warnf(format string, args ...any) {
|
||||
c.Logf(format, args...)
|
||||
}
|
||||
|
||||
func (c *LogTree) Info(msg ...any) {
|
||||
c.Log(msg...)
|
||||
}
|
||||
|
||||
func (c *LogTree) Infof(format string, args ...any) {
|
||||
c.Logf(format, args...)
|
||||
}
|
||||
|
||||
func (c *LogTree) Embed(logs *LogTree) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
count := logs.count.Load()
|
||||
c.root.stringLength.Add(logs.stringLength.Load() + count*int32(c.level))
|
||||
c.root.count.Add(count)
|
||||
log := newLogEntry(logs, logs.name)
|
||||
c.add(log)
|
||||
}
|
||||
|
||||
func (c *LogTree) Fork(message string) *LogTree {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
child := &LogTree{level: c.level + 1, root: c.root, verbose: c.verbose}
|
||||
log := newLogEntry(child, message)
|
||||
c.add(log)
|
||||
return child
|
||||
}
|
||||
|
||||
func (c *LogTree) String() string {
|
||||
if c.root != c {
|
||||
panic("can only call String on root LogTree")
|
||||
}
|
||||
var builder strings.Builder
|
||||
header := fmt.Sprintf("======== %s ========\n", c.name)
|
||||
builder.Grow(int(c.stringLength.Load()) + len(header))
|
||||
builder.WriteString(header)
|
||||
c.writeLogsRecursive(&builder, "")
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
func (c *LogTree) writeLogsRecursive(builder *strings.Builder, indent string) {
|
||||
for _, log := range c.logs {
|
||||
builder.WriteString(indent)
|
||||
builder.WriteString(formatTime(log.time))
|
||||
builder.WriteString(" ")
|
||||
builder.WriteString(log.message)
|
||||
builder.WriteString("\n")
|
||||
if log.child != nil {
|
||||
log.child.writeLogsRecursive(builder, indent+"\t")
|
||||
}
|
||||
}
|
||||
}
|
||||
19
tools/tsgo/internal/project/logging/logtree_test.go
Normal file
19
tools/tsgo/internal/project/logging/logtree_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Verify LogTree implements the expected interface
|
||||
type testLogger interface {
|
||||
Log(msg ...any)
|
||||
}
|
||||
|
||||
func TestLogTreeImplementsLogger(t *testing.T) {
|
||||
t.Parallel()
|
||||
var _ testLogger = &LogTree{}
|
||||
}
|
||||
|
||||
func TestLogTree(t *testing.T) {
|
||||
t.Parallel()
|
||||
}
|
||||
Reference in New Issue
Block a user