[ Cmii ] [ Octopus ] - add all image tag back up; add socks5 proxy
This commit is contained in:
211
socks5_txthinking/old_tcp_tailscale/logger.go
Normal file
211
socks5_txthinking/old_tcp_tailscale/logger.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package old_tcp_tailscale // Copyright (c) Tailscale Inc & AUTHORS
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
)
|
||||
|
||||
// Logf is the basic Tailscale logger type: a printf-like func.
|
||||
// Like log.Printf, the format need not end in a newline.
|
||||
// Logf functions must be safe for concurrent use.
|
||||
type Logf func(format string, args ...any)
|
||||
|
||||
// A Context is a context.Context that should contain a custom log function, obtainable from FromContext.
|
||||
// If no log function is present, FromContext will return log.Printf.
|
||||
// To construct a Context, use Add
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
type Context context.Context
|
||||
|
||||
// jenc is a json.Encode + bytes.Buffer pair wired up to be reused in a pool.
|
||||
type jenc struct {
|
||||
buf bytes.Buffer
|
||||
enc *json.Encoder
|
||||
}
|
||||
|
||||
var jencPool = &sync.Pool{New: func() any {
|
||||
je := new(jenc)
|
||||
je.enc = json.NewEncoder(&je.buf)
|
||||
return je
|
||||
}}
|
||||
|
||||
// JSON marshals v as JSON and writes it to logf formatted with the annotation to make logtail
|
||||
// treat it as a structured log.
|
||||
//
|
||||
// The recType is the record type and becomes the key of the wrapper
|
||||
// JSON object that is logged. That is, if recType is "foo" and v is
|
||||
// 123, the value logged is {"foo":123}.
|
||||
//
|
||||
// Do not use recType "logtail", "v", "text", or "metrics", with any case.
|
||||
// Those are reserved for the logging system.
|
||||
//
|
||||
// The level can be from 0 to 9. Levels from 1 to 9 are included in
|
||||
// the logged JSON object, like {"foo":123,"v":2}.
|
||||
func (logf Logf) JSON(level int, recType string, v any) {
|
||||
je := jencPool.Get().(*jenc)
|
||||
defer jencPool.Put(je)
|
||||
je.buf.Reset()
|
||||
je.buf.WriteByte('{')
|
||||
je.enc.Encode(recType)
|
||||
je.buf.Truncate(je.buf.Len() - 1) // remove newline from prior Encode
|
||||
je.buf.WriteByte(':')
|
||||
if err := je.enc.Encode(v); err != nil {
|
||||
logf("[unexpected]: failed to encode structured JSON log record of type %q / %T: %v", recType, v, err)
|
||||
return
|
||||
}
|
||||
je.buf.Truncate(je.buf.Len() - 1) // remove newline from prior Encode
|
||||
je.buf.WriteByte('}')
|
||||
// Magic prefix recognized by logtail:
|
||||
logf("[v\x00JSON]%d%s", level%10, je.buf.Bytes())
|
||||
|
||||
}
|
||||
|
||||
// WithPrefix wraps f, prefixing each format with the provided prefix.
|
||||
func WithPrefix(f Logf, prefix string) Logf {
|
||||
return func(format string, args ...any) {
|
||||
f(prefix+format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// FuncWriter returns an io.Writer that writes to f.
|
||||
func FuncWriter(f Logf) io.Writer {
|
||||
return funcWriter{f}
|
||||
}
|
||||
|
||||
// StdLogger returns a standard library logger from a Logf.
|
||||
func StdLogger(f Logf) *log.Logger {
|
||||
return log.New(FuncWriter(f), "", 0)
|
||||
}
|
||||
|
||||
type funcWriter struct{ f Logf }
|
||||
|
||||
func (w funcWriter) Write(p []byte) (int, error) {
|
||||
w.f("%s", p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// Discard is a Logf that throws away the logs given to it.
|
||||
func Discard(string, ...any) {}
|
||||
|
||||
// LogOnChange logs a given line only if line != lastLine, or if maxInterval has passed
|
||||
// since the last time this identical line was logged.
|
||||
func LogOnChange(logf Logf, maxInterval time.Duration, timeNow func() time.Time) Logf {
|
||||
var (
|
||||
mu sync.Mutex
|
||||
sLastLogged string
|
||||
tLastLogged = timeNow()
|
||||
)
|
||||
|
||||
return func(format string, args ...any) {
|
||||
s := fmt.Sprintf(format, args...)
|
||||
|
||||
mu.Lock()
|
||||
if s == sLastLogged && timeNow().Sub(tLastLogged) < maxInterval {
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
sLastLogged = s
|
||||
tLastLogged = timeNow()
|
||||
mu.Unlock()
|
||||
|
||||
// Re-stringify it (instead of using "%s", s) so something like "%s"
|
||||
// doesn't end up getting rate-limited. (And can't use 's' as the pattern,
|
||||
// as it might contain formatting directives.)
|
||||
logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// ArgWriter is a fmt.Formatter that can be passed to any Logf func to
|
||||
// efficiently write to a %v argument without allocations.
|
||||
type ArgWriter func(*bufio.Writer)
|
||||
|
||||
func (fn ArgWriter) Format(f fmt.State, _ rune) {
|
||||
bw := argBufioPool.Get().(*bufio.Writer)
|
||||
bw.Reset(f)
|
||||
fn(bw)
|
||||
bw.Flush()
|
||||
argBufioPool.Put(bw)
|
||||
}
|
||||
|
||||
var argBufioPool = &sync.Pool{New: func() any { return bufio.NewWriterSize(io.Discard, 1024) }}
|
||||
|
||||
// Filtered returns a Logf that silently swallows some log lines.
|
||||
// Each inbound format and args is evaluated and printed to a string s.
|
||||
// The original format and args are passed to logf if and only if allow(s) returns true.
|
||||
func Filtered(logf Logf, allow func(s string) bool) Logf {
|
||||
return func(format string, args ...any) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
if !allow(msg) {
|
||||
return
|
||||
}
|
||||
logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// LogfCloser wraps logf to create a logger that can be closed.
|
||||
// Calling close makes all future calls to newLogf into no-ops.
|
||||
func LogfCloser(logf Logf) (newLogf Logf, close func()) {
|
||||
var (
|
||||
mu sync.Mutex
|
||||
closed bool
|
||||
)
|
||||
close = func() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
closed = true
|
||||
}
|
||||
newLogf = func(msg string, args ...any) {
|
||||
mu.Lock()
|
||||
if closed {
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
mu.Unlock()
|
||||
logf(msg, args...)
|
||||
}
|
||||
return newLogf, close
|
||||
}
|
||||
|
||||
// AsJSON returns a formatter that formats v as JSON. The value is suitable to
|
||||
// passing to a regular %v printf argument. (%s is not required)
|
||||
//
|
||||
// If json.Marshal returns an error, the output is "%%!JSON-ERROR:" followed by
|
||||
// the error string.
|
||||
func AsJSON(v any) fmt.Formatter {
|
||||
return asJSONResult{v}
|
||||
}
|
||||
|
||||
type asJSONResult struct{ v any }
|
||||
|
||||
func (a asJSONResult) Format(s fmt.State, verb rune) {
|
||||
v, err := json.Marshal(a.v)
|
||||
if err != nil {
|
||||
fmt.Fprintf(s, "%%!JSON-ERROR:%v", err)
|
||||
return
|
||||
}
|
||||
s.Write(v)
|
||||
}
|
||||
|
||||
// TBLogger is the testing.TB subset needed by TestLogger.
|
||||
type TBLogger interface {
|
||||
Helper()
|
||||
Logf(format string, args ...any)
|
||||
}
|
||||
|
||||
// TestLogger returns a logger that logs to tb.Logf
|
||||
// with a prefix to make it easier to distinguish spam
|
||||
// from explicit test failures.
|
||||
func TestLogger(tb TBLogger) Logf {
|
||||
return func(format string, args ...any) {
|
||||
tb.Helper()
|
||||
tb.Logf(" ... "+format, args...)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user