Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
400
vendor/github.com/ipfs/go-log/v2/setup.go
generated
vendored
Normal file
400
vendor/github.com/ipfs/go-log/v2/setup.go
generated
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var config Config
|
||||
|
||||
func init() {
|
||||
SetupLogging(configFromEnv())
|
||||
}
|
||||
|
||||
// Logging environment variables
|
||||
const (
|
||||
// IPFS_* prefixed env vars kept for backwards compatibility
|
||||
// for this release. They will not be available in the next
|
||||
// release.
|
||||
//
|
||||
// GOLOG_* env vars take precedences over IPFS_* env vars.
|
||||
envIPFSLogging = "IPFS_LOGGING"
|
||||
envIPFSLoggingFmt = "IPFS_LOGGING_FMT"
|
||||
|
||||
envLogging = "GOLOG_LOG_LEVEL"
|
||||
envLoggingFmt = "GOLOG_LOG_FMT"
|
||||
|
||||
envLoggingFile = "GOLOG_FILE" // /path/to/file
|
||||
envLoggingURL = "GOLOG_URL" // url that will be processed by sink in the zap
|
||||
|
||||
envLoggingOutput = "GOLOG_OUTPUT" // possible values: stdout|stderr|file combine multiple values with '+'
|
||||
envLoggingLabels = "GOLOG_LOG_LABELS" // comma-separated key-value pairs, i.e. "app=example_app,dc=sjc-1"
|
||||
)
|
||||
|
||||
type LogFormat int
|
||||
|
||||
const (
|
||||
ColorizedOutput LogFormat = iota
|
||||
PlaintextOutput
|
||||
JSONOutput
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
// Format overrides the format of the log output. Defaults to ColorizedOutput
|
||||
Format LogFormat
|
||||
|
||||
// Level is the default minimum enabled logging level.
|
||||
Level LogLevel
|
||||
|
||||
// SubsystemLevels are the default levels per-subsystem. When unspecified, defaults to Level.
|
||||
SubsystemLevels map[string]LogLevel
|
||||
|
||||
// Stderr indicates whether logs should be written to stderr.
|
||||
Stderr bool
|
||||
|
||||
// Stdout indicates whether logs should be written to stdout.
|
||||
Stdout bool
|
||||
|
||||
// File is a path to a file that logs will be written to.
|
||||
File string
|
||||
|
||||
// URL with schema supported by zap. Use zap.RegisterSink
|
||||
URL string
|
||||
|
||||
// Labels is a set of key-values to apply to all loggers
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// ErrNoSuchLogger is returned when the util pkg is asked for a non existant logger
|
||||
var ErrNoSuchLogger = errors.New("error: No such logger")
|
||||
|
||||
var loggerMutex sync.RWMutex // guards access to global logger state
|
||||
|
||||
// loggers is the set of loggers in the system
|
||||
var loggers = make(map[string]*zap.SugaredLogger)
|
||||
var levels = make(map[string]zap.AtomicLevel)
|
||||
|
||||
// primaryFormat is the format of the primary core used for logging
|
||||
var primaryFormat LogFormat = ColorizedOutput
|
||||
|
||||
// defaultLevel is the default log level
|
||||
var defaultLevel LogLevel = LevelError
|
||||
|
||||
// primaryCore is the primary logging core
|
||||
var primaryCore zapcore.Core
|
||||
|
||||
// loggerCore is the base for all loggers created by this package
|
||||
var loggerCore = &lockedMultiCore{}
|
||||
|
||||
// GetConfig returns a copy of the saved config. It can be inspected, modified,
|
||||
// and re-applied using a subsequent call to SetupLogging().
|
||||
func GetConfig() Config {
|
||||
return config
|
||||
}
|
||||
|
||||
// SetupLogging will initialize the logger backend and set the flags.
|
||||
// TODO calling this in `init` pushes all configuration to env variables
|
||||
// - move it out of `init`? then we need to change all the code (js-ipfs, go-ipfs) to call this explicitly
|
||||
// - have it look for a config file? need to define what that is
|
||||
func SetupLogging(cfg Config) {
|
||||
loggerMutex.Lock()
|
||||
defer loggerMutex.Unlock()
|
||||
|
||||
config = cfg
|
||||
|
||||
primaryFormat = cfg.Format
|
||||
defaultLevel = cfg.Level
|
||||
|
||||
outputPaths := []string{}
|
||||
|
||||
if cfg.Stderr {
|
||||
outputPaths = append(outputPaths, "stderr")
|
||||
}
|
||||
if cfg.Stdout {
|
||||
outputPaths = append(outputPaths, "stdout")
|
||||
}
|
||||
|
||||
// check if we log to a file
|
||||
if len(cfg.File) > 0 {
|
||||
if path, err := normalizePath(cfg.File); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to resolve log path '%q', logging to %s\n", cfg.File, outputPaths)
|
||||
} else {
|
||||
outputPaths = append(outputPaths, path)
|
||||
}
|
||||
}
|
||||
if len(cfg.URL) > 0 {
|
||||
outputPaths = append(outputPaths, cfg.URL)
|
||||
}
|
||||
|
||||
ws, _, err := zap.Open(outputPaths...)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("unable to open logging output: %v", err))
|
||||
}
|
||||
|
||||
newPrimaryCore := newCore(primaryFormat, ws, LevelDebug) // the main core needs to log everything.
|
||||
|
||||
for k, v := range cfg.Labels {
|
||||
newPrimaryCore = newPrimaryCore.With([]zap.Field{zap.String(k, v)})
|
||||
}
|
||||
|
||||
setPrimaryCore(newPrimaryCore)
|
||||
setAllLoggers(defaultLevel)
|
||||
|
||||
for name, level := range cfg.SubsystemLevels {
|
||||
if leveler, ok := levels[name]; ok {
|
||||
leveler.SetLevel(zapcore.Level(level))
|
||||
} else {
|
||||
levels[name] = zap.NewAtomicLevelAt(zapcore.Level(level))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetPrimaryCore changes the primary logging core. If the SetupLogging was
|
||||
// called then the previously configured core will be replaced.
|
||||
func SetPrimaryCore(core zapcore.Core) {
|
||||
loggerMutex.Lock()
|
||||
defer loggerMutex.Unlock()
|
||||
|
||||
setPrimaryCore(core)
|
||||
}
|
||||
|
||||
func setPrimaryCore(core zapcore.Core) {
|
||||
if primaryCore != nil {
|
||||
loggerCore.ReplaceCore(primaryCore, core)
|
||||
} else {
|
||||
loggerCore.AddCore(core)
|
||||
}
|
||||
primaryCore = core
|
||||
}
|
||||
|
||||
// SetDebugLogging calls SetAllLoggers with logging.DEBUG
|
||||
func SetDebugLogging() {
|
||||
SetAllLoggers(LevelDebug)
|
||||
}
|
||||
|
||||
// SetAllLoggers changes the logging level of all loggers to lvl
|
||||
func SetAllLoggers(lvl LogLevel) {
|
||||
loggerMutex.RLock()
|
||||
defer loggerMutex.RUnlock()
|
||||
|
||||
setAllLoggers(lvl)
|
||||
}
|
||||
|
||||
func setAllLoggers(lvl LogLevel) {
|
||||
for _, l := range levels {
|
||||
l.SetLevel(zapcore.Level(lvl))
|
||||
}
|
||||
}
|
||||
|
||||
// SetLogLevel changes the log level of a specific subsystem
|
||||
// name=="*" changes all subsystems
|
||||
func SetLogLevel(name, level string) error {
|
||||
lvl, err := LevelFromString(level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// wildcard, change all
|
||||
if name == "*" {
|
||||
SetAllLoggers(lvl)
|
||||
return nil
|
||||
}
|
||||
|
||||
loggerMutex.RLock()
|
||||
defer loggerMutex.RUnlock()
|
||||
|
||||
// Check if we have a logger by that name
|
||||
if _, ok := levels[name]; !ok {
|
||||
return ErrNoSuchLogger
|
||||
}
|
||||
|
||||
levels[name].SetLevel(zapcore.Level(lvl))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetLogLevelRegex sets all loggers to level `l` that match expression `e`.
|
||||
// An error is returned if `e` fails to compile.
|
||||
func SetLogLevelRegex(e, l string) error {
|
||||
lvl, err := LevelFromString(l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rem, err := regexp.Compile(e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
loggerMutex.Lock()
|
||||
defer loggerMutex.Unlock()
|
||||
for name := range loggers {
|
||||
if rem.MatchString(name) {
|
||||
levels[name].SetLevel(zapcore.Level(lvl))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSubsystems returns a slice containing the
|
||||
// names of the current loggers
|
||||
func GetSubsystems() []string {
|
||||
loggerMutex.RLock()
|
||||
defer loggerMutex.RUnlock()
|
||||
subs := make([]string, 0, len(loggers))
|
||||
|
||||
for k := range loggers {
|
||||
subs = append(subs, k)
|
||||
}
|
||||
return subs
|
||||
}
|
||||
|
||||
func getLogger(name string) *zap.SugaredLogger {
|
||||
loggerMutex.Lock()
|
||||
defer loggerMutex.Unlock()
|
||||
log, ok := loggers[name]
|
||||
if !ok {
|
||||
level, ok := levels[name]
|
||||
if !ok {
|
||||
level = zap.NewAtomicLevelAt(zapcore.Level(defaultLevel))
|
||||
levels[name] = level
|
||||
}
|
||||
log = zap.New(loggerCore).
|
||||
WithOptions(
|
||||
zap.IncreaseLevel(level),
|
||||
zap.AddCaller(),
|
||||
).
|
||||
Named(name).
|
||||
Sugar()
|
||||
|
||||
loggers[name] = log
|
||||
}
|
||||
|
||||
return log
|
||||
}
|
||||
|
||||
// configFromEnv returns a Config with defaults populated using environment variables.
|
||||
func configFromEnv() Config {
|
||||
cfg := Config{
|
||||
Format: ColorizedOutput,
|
||||
Stderr: true,
|
||||
Level: LevelError,
|
||||
SubsystemLevels: map[string]LogLevel{},
|
||||
Labels: map[string]string{},
|
||||
}
|
||||
|
||||
format := os.Getenv(envLoggingFmt)
|
||||
if format == "" {
|
||||
format = os.Getenv(envIPFSLoggingFmt)
|
||||
}
|
||||
|
||||
var noExplicitFormat bool
|
||||
|
||||
switch format {
|
||||
case "color":
|
||||
cfg.Format = ColorizedOutput
|
||||
case "nocolor":
|
||||
cfg.Format = PlaintextOutput
|
||||
case "json":
|
||||
cfg.Format = JSONOutput
|
||||
default:
|
||||
if format != "" {
|
||||
fmt.Fprintf(os.Stderr, "ignoring unrecognized log format '%s'\n", format)
|
||||
}
|
||||
noExplicitFormat = true
|
||||
}
|
||||
|
||||
lvl := os.Getenv(envLogging)
|
||||
if lvl == "" {
|
||||
lvl = os.Getenv(envIPFSLogging)
|
||||
}
|
||||
if lvl != "" {
|
||||
for _, kvs := range strings.Split(lvl, ",") {
|
||||
kv := strings.SplitN(kvs, "=", 2)
|
||||
lvl, err := LevelFromString(kv[len(kv)-1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error setting log level %q: %s\n", kvs, err)
|
||||
continue
|
||||
}
|
||||
switch len(kv) {
|
||||
case 1:
|
||||
cfg.Level = lvl
|
||||
case 2:
|
||||
cfg.SubsystemLevels[kv[0]] = lvl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg.File = os.Getenv(envLoggingFile)
|
||||
// Disable stderr logging when a file is specified
|
||||
// https://github.com/ipfs/go-log/issues/83
|
||||
if cfg.File != "" {
|
||||
cfg.Stderr = false
|
||||
}
|
||||
|
||||
cfg.URL = os.Getenv(envLoggingURL)
|
||||
output := os.Getenv(envLoggingOutput)
|
||||
outputOptions := strings.Split(output, "+")
|
||||
for _, opt := range outputOptions {
|
||||
switch opt {
|
||||
case "stdout":
|
||||
cfg.Stdout = true
|
||||
case "stderr":
|
||||
cfg.Stderr = true
|
||||
case "file":
|
||||
if cfg.File == "" {
|
||||
fmt.Fprint(os.Stderr, "please specify a GOLOG_FILE value to write to")
|
||||
}
|
||||
case "url":
|
||||
if cfg.URL == "" {
|
||||
fmt.Fprint(os.Stderr, "please specify a GOLOG_URL value to write to")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that neither of the requested Std* nor the file are TTYs
|
||||
// At this stage (configFromEnv) we do not have a uniform list to examine yet
|
||||
if noExplicitFormat &&
|
||||
!(cfg.Stdout && isTerm(os.Stdout)) &&
|
||||
!(cfg.Stderr && isTerm(os.Stderr)) &&
|
||||
// check this last: expensive
|
||||
!(cfg.File != "" && pathIsTerm(cfg.File)) {
|
||||
cfg.Format = PlaintextOutput
|
||||
}
|
||||
|
||||
labels := os.Getenv(envLoggingLabels)
|
||||
if labels != "" {
|
||||
labelKVs := strings.Split(labels, ",")
|
||||
for _, label := range labelKVs {
|
||||
kv := strings.Split(label, "=")
|
||||
if len(kv) != 2 {
|
||||
fmt.Fprint(os.Stderr, "invalid label k=v: ", label)
|
||||
continue
|
||||
}
|
||||
cfg.Labels[kv[0]] = kv[1]
|
||||
}
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func isTerm(f *os.File) bool {
|
||||
return isatty.IsTerminal(f.Fd()) || isatty.IsCygwinTerminal(f.Fd())
|
||||
}
|
||||
|
||||
func pathIsTerm(p string) bool {
|
||||
// !!!no!!! O_CREAT, if we fail - we fail
|
||||
f, err := os.OpenFile(p, os.O_WRONLY, 0)
|
||||
if f != nil {
|
||||
defer f.Close() // nolint:errcheck
|
||||
}
|
||||
return err == nil && isTerm(f)
|
||||
}
|
||||
Reference in New Issue
Block a user