mirror of
https://github.com/regclient/regclient.git
synced 2025-04-18 22:44:00 +03:00
Feat: Switch regbot to slog
This also consolidated the trace logging level to a single definition. Signed-off-by: Brandon Mitchell <git@bmitch.net>
This commit is contained in:
parent
6aa3ff18d9
commit
3756788d13
@ -7,30 +7,24 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/regclient/regclient/internal/godbg"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
log := &logrus.Logger{
|
||||
Out: os.Stderr,
|
||||
Formatter: new(logrus.TextFormatter),
|
||||
Hooks: make(logrus.LevelHooks),
|
||||
Level: logrus.InfoLevel,
|
||||
}
|
||||
|
||||
rootTopCmd, rootOpts := NewRootCmd()
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-sig
|
||||
log.WithFields(logrus.Fields{}).Debug("Interrupt received, stopping")
|
||||
rootOpts.log.Debug("Interrupt received, stopping")
|
||||
// clean shutdown
|
||||
cancel()
|
||||
}()
|
||||
godbg.SignalTrace()
|
||||
|
||||
rootTopCmd := NewRootCmd(log)
|
||||
if err := rootTopCmd.ExecuteContext(ctx); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -12,7 +13,6 @@ import (
|
||||
|
||||
"github.com/olareg/olareg"
|
||||
oConfig "github.com/olareg/olareg/config"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/regclient/regclient"
|
||||
"github.com/regclient/regclient/config"
|
||||
@ -164,14 +164,9 @@ defaults:
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
rootOpts := rootCmd{
|
||||
dryRun: tt.dryrun,
|
||||
conf: conf,
|
||||
log: &logrus.Logger{
|
||||
Out: os.Stderr,
|
||||
Formatter: new(logrus.TextFormatter),
|
||||
Hooks: make(logrus.LevelHooks),
|
||||
Level: logrus.InfoLevel,
|
||||
},
|
||||
dryRun: tt.dryrun,
|
||||
conf: conf,
|
||||
log: slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo})),
|
||||
rc: rc,
|
||||
throttle: pq,
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/regclient/regclient"
|
||||
@ -16,6 +18,7 @@ import (
|
||||
"github.com/regclient/regclient/internal/version"
|
||||
"github.com/regclient/regclient/pkg/template"
|
||||
"github.com/regclient/regclient/scheme/reg"
|
||||
"github.com/regclient/regclient/types"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -31,15 +34,15 @@ type rootCmd struct {
|
||||
verbosity string
|
||||
logopts []string
|
||||
format string // for Go template formatting of various commands
|
||||
log *logrus.Logger
|
||||
log *slog.Logger
|
||||
conf *Config
|
||||
rc *regclient.RegClient
|
||||
throttle *pqueue.Queue[struct{}]
|
||||
}
|
||||
|
||||
func NewRootCmd(log *logrus.Logger) *cobra.Command {
|
||||
func NewRootCmd() (*cobra.Command, *rootCmd) {
|
||||
rootOpts := rootCmd{
|
||||
log: log,
|
||||
log: slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo})),
|
||||
}
|
||||
var rootTopCmd = &cobra.Command{
|
||||
Use: "regbot <cmd>",
|
||||
@ -74,7 +77,7 @@ returns after the last script completes.`,
|
||||
|
||||
rootTopCmd.PersistentFlags().StringVarP(&rootOpts.confFile, "config", "c", "", "Config file")
|
||||
rootTopCmd.PersistentFlags().BoolVarP(&rootOpts.dryRun, "dry-run", "", false, "Dry Run, skip all external actions")
|
||||
rootTopCmd.PersistentFlags().StringVarP(&rootOpts.verbosity, "verbosity", "v", logrus.InfoLevel.String(), "Log level (debug, info, warn, error, fatal, panic)")
|
||||
rootTopCmd.PersistentFlags().StringVarP(&rootOpts.verbosity, "verbosity", "v", slog.LevelInfo.String(), "Log level (debug, info, warn, error, fatal, panic)")
|
||||
rootTopCmd.PersistentFlags().StringArrayVar(&rootOpts.logopts, "logopt", []string{}, "Log options")
|
||||
versionCmd.Flags().StringVarP(&rootOpts.format, "format", "", "{{printPretty .}}", "Format output with go template syntax")
|
||||
|
||||
@ -87,21 +90,31 @@ returns after the last script completes.`,
|
||||
rootTopCmd.AddCommand(versionCmd)
|
||||
|
||||
rootTopCmd.PersistentPreRunE = rootOpts.rootPreRun
|
||||
return rootTopCmd
|
||||
return rootTopCmd, &rootOpts
|
||||
}
|
||||
|
||||
func (rootOpts *rootCmd) rootPreRun(cmd *cobra.Command, args []string) error {
|
||||
lvl, err := logrus.ParseLevel(rootOpts.verbosity)
|
||||
var lvl slog.Level
|
||||
err := lvl.UnmarshalText([]byte(rootOpts.verbosity))
|
||||
if err != nil {
|
||||
return err
|
||||
// handle custom levels
|
||||
if rootOpts.verbosity == strings.ToLower("trace") {
|
||||
lvl = types.LevelTrace
|
||||
} else {
|
||||
return fmt.Errorf("unable to parse verbosity %s: %v", rootOpts.verbosity, err)
|
||||
}
|
||||
}
|
||||
rootOpts.log.SetLevel(lvl)
|
||||
rootOpts.log.Formatter = &logrus.TextFormatter{FullTimestamp: true}
|
||||
formatJSON := false
|
||||
for _, opt := range rootOpts.logopts {
|
||||
if opt == "json" {
|
||||
rootOpts.log.Formatter = new(logrus.JSONFormatter)
|
||||
formatJSON = true
|
||||
}
|
||||
}
|
||||
if formatJSON {
|
||||
rootOpts.log = slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: lvl}))
|
||||
} else {
|
||||
rootOpts.log = slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: lvl}))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -165,14 +178,12 @@ func (rootOpts *rootCmd) runServer(cmd *cobra.Command, args []string) error {
|
||||
sched = "@every " + s.Interval.String()
|
||||
}
|
||||
if sched != "" {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"name": s.Name,
|
||||
"sched": sched,
|
||||
}).Debug("Scheduled task")
|
||||
rootOpts.log.Debug("Scheduled task",
|
||||
slog.String("name", s.Name),
|
||||
slog.String("sched", sched))
|
||||
_, errCron := c.AddFunc(sched, func() {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"name": s.Name,
|
||||
}).Debug("Running task")
|
||||
rootOpts.log.Debug("Running task",
|
||||
slog.String("name", s.Name))
|
||||
wg.Add(1)
|
||||
defer wg.Done()
|
||||
err := rootOpts.process(ctx, s)
|
||||
@ -181,19 +192,17 @@ func (rootOpts *rootCmd) runServer(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
})
|
||||
if errCron != nil {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"name": s.Name,
|
||||
"sched": sched,
|
||||
"err": errCron,
|
||||
}).Error("Failed to schedule cron")
|
||||
rootOpts.log.Error("Failed to schedule cron",
|
||||
slog.String("name", s.Name),
|
||||
slog.String("sched", sched),
|
||||
slog.String("err", errCron.Error()))
|
||||
if mainErr != nil {
|
||||
mainErr = errCron
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"name": s.Name,
|
||||
}).Error("No schedule or interval found, ignoring")
|
||||
rootOpts.log.Error("No schedule or interval found, ignoring",
|
||||
slog.String("name", s.Name))
|
||||
}
|
||||
}
|
||||
c.Start()
|
||||
@ -202,10 +211,10 @@ func (rootOpts *rootCmd) runServer(cmd *cobra.Command, args []string) error {
|
||||
if done != nil {
|
||||
<-done
|
||||
}
|
||||
rootOpts.log.WithFields(logrus.Fields{}).Info("Stopping server")
|
||||
rootOpts.log.Info("Stopping server")
|
||||
// clean shutdown
|
||||
c.Stop()
|
||||
rootOpts.log.WithFields(logrus.Fields{}).Debug("Waiting on running tasks")
|
||||
rootOpts.log.Debug("Waiting on running tasks")
|
||||
wg.Wait()
|
||||
return mainErr
|
||||
}
|
||||
@ -235,13 +244,12 @@ func (rootOpts *rootCmd) loadConf() error {
|
||||
if concurrent <= 0 {
|
||||
concurrent = 1
|
||||
}
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"concurrent": concurrent,
|
||||
}).Debug("Configuring parallel settings")
|
||||
rootOpts.log.Debug("Configuring parallel settings",
|
||||
slog.Int("concurrent", concurrent))
|
||||
rootOpts.throttle = pqueue.New(pqueue.Opts[struct{}]{Max: concurrent})
|
||||
// set the regclient, loading docker creds unless disabled, and inject logins from config file
|
||||
rcOpts := []regclient.Opt{
|
||||
regclient.WithLog(rootOpts.log),
|
||||
regclient.WithSlog(rootOpts.log),
|
||||
}
|
||||
if rootOpts.conf.Defaults.BlobLimit != 0 {
|
||||
rcOpts = append(rcOpts, regclient.WithRegOpts(reg.WithBlobLimit(rootOpts.conf.Defaults.BlobLimit)))
|
||||
@ -262,9 +270,8 @@ func (rootOpts *rootCmd) loadConf() error {
|
||||
rcHosts := []config.Host{}
|
||||
for _, host := range rootOpts.conf.Creds {
|
||||
if host.Scheme != "" {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"name": host.Name,
|
||||
}).Warn("Scheme is deprecated, for http set TLS to disabled")
|
||||
rootOpts.log.Warn("Scheme is deprecated, for http set TLS to disabled",
|
||||
slog.String("name", host.Name))
|
||||
}
|
||||
rcHosts = append(rcHosts, host)
|
||||
}
|
||||
@ -277,9 +284,8 @@ func (rootOpts *rootCmd) loadConf() error {
|
||||
|
||||
// process a sync step
|
||||
func (rootOpts *rootCmd) process(ctx context.Context, s ConfigScript) error {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"script": s.Name,
|
||||
}).Debug("Starting script")
|
||||
rootOpts.log.Debug("Starting script",
|
||||
slog.String("script", s.Name))
|
||||
// add a timeout to the context
|
||||
if s.Timeout > 0 {
|
||||
ctxTimeout, cancel := context.WithTimeout(ctx, s.Timeout)
|
||||
@ -289,7 +295,7 @@ func (rootOpts *rootCmd) process(ctx context.Context, s ConfigScript) error {
|
||||
sbOpts := []sandbox.Opt{
|
||||
sandbox.WithContext(ctx),
|
||||
sandbox.WithRegClient(rootOpts.rc),
|
||||
sandbox.WithLog(rootOpts.log),
|
||||
sandbox.WithSlog(rootOpts.log),
|
||||
sandbox.WithThrottle(rootOpts.throttle),
|
||||
}
|
||||
if rootOpts.dryRun {
|
||||
@ -299,15 +305,12 @@ func (rootOpts *rootCmd) process(ctx context.Context, s ConfigScript) error {
|
||||
defer sb.Close()
|
||||
err := sb.RunScript(s.Script)
|
||||
if err != nil {
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"script": s.Name,
|
||||
"error": err,
|
||||
}).Warn("Error running script")
|
||||
rootOpts.log.Warn("Error running script",
|
||||
slog.String("script", s.Name),
|
||||
slog.String("error", err.Error()))
|
||||
return ErrScriptFailed
|
||||
}
|
||||
rootOpts.log.WithFields(logrus.Fields{
|
||||
"script": s.Name,
|
||||
}).Debug("Finished script")
|
||||
|
||||
rootOpts.log.Debug("Finished script",
|
||||
slog.String("script", s.Name))
|
||||
return nil
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
// crypto libraries included for go-digest
|
||||
@ -11,7 +12,6 @@ import (
|
||||
_ "crypto/sha512"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/sirupsen/logrus"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
|
||||
"github.com/regclient/regclient/types/blob"
|
||||
@ -108,11 +108,10 @@ func (s *Sandbox) blobGet(ls *lua.LState) int {
|
||||
if ls.GetTop() >= 2 {
|
||||
d = ls.CheckString(2)
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"ref": r.r.CommonName(),
|
||||
"digest": d,
|
||||
}).Debug("Retrieve blob")
|
||||
s.log.Debug("Retrieve blob",
|
||||
slog.String("script", s.name),
|
||||
slog.String("ref", r.r.CommonName()),
|
||||
slog.String("digest", d))
|
||||
b, err := s.rc.BlobGet(s.ctx, r.r, descriptor.Descriptor{Digest: digest.Digest(d)})
|
||||
if err != nil {
|
||||
ls.RaiseError("Failed retrieving \"%s\" blob \"%s\": %v", r.r.CommonName(), d, err)
|
||||
@ -136,11 +135,10 @@ func (s *Sandbox) blobHead(ls *lua.LState) int {
|
||||
if ls.GetTop() >= 2 {
|
||||
d = ls.CheckString(2)
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"ref": r.r.CommonName(),
|
||||
"digest": d,
|
||||
}).Debug("Retrieve blob")
|
||||
s.log.Debug("Retrieve blob",
|
||||
slog.String("script", s.name),
|
||||
slog.String("ref", r.r.CommonName()),
|
||||
slog.String("digest", d))
|
||||
b, err := s.rc.BlobHead(s.ctx, r.r, descriptor.Descriptor{Digest: digest.Digest(d)})
|
||||
if err != nil {
|
||||
ls.RaiseError("Failed retrieving \"%s\" blob \"%s\": %v", r.r.CommonName(), d, err)
|
||||
@ -161,10 +159,9 @@ func (s *Sandbox) blobPut(ls *lua.LState) int {
|
||||
}
|
||||
r := s.checkReference(ls, 1)
|
||||
var d digest.Digest
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"ref": r.r.CommonName(),
|
||||
}).Debug("Put blob")
|
||||
s.log.Debug("Put blob",
|
||||
slog.String("script", s.name),
|
||||
slog.String("ref", r.r.CommonName()))
|
||||
|
||||
if ls.GetTop() < 2 {
|
||||
ls.ArgError(2, "blob content expected")
|
||||
|
@ -3,10 +3,10 @@ package sandbox
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
|
||||
"github.com/regclient/regclient"
|
||||
@ -84,10 +84,9 @@ func (s *Sandbox) configGet(ls *lua.LState) int {
|
||||
}
|
||||
defer done()
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": m.r.CommonName(),
|
||||
}).Debug("Retrieve image config")
|
||||
s.log.Debug("Retrieve image config",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", m.r.CommonName()))
|
||||
mi, ok := m.m.(manifest.Imager)
|
||||
if !ok {
|
||||
ls.RaiseError("Image methods are not available for manifest")
|
||||
@ -209,15 +208,15 @@ func (s *Sandbox) imageCopy(ls *lua.LState) int {
|
||||
}
|
||||
defer done()
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"source": src.r.CommonName(),
|
||||
"target": tgt.r.CommonName(),
|
||||
"digestTags": lOpts.DigestTags,
|
||||
"forceRecursive": lOpts.ForceRecursive,
|
||||
"includeExternal": lOpts.IncludeExternal,
|
||||
"dry-run": s.dryRun,
|
||||
}).Info("Copy image")
|
||||
s.log.Info("Copy image",
|
||||
slog.String("script", s.name),
|
||||
slog.String("source", src.r.CommonName()),
|
||||
slog.String("target", tgt.r.CommonName()),
|
||||
slog.Bool("digestTags", lOpts.DigestTags),
|
||||
slog.Bool("forceRecursive", lOpts.ForceRecursive),
|
||||
slog.Bool("includeExternal", lOpts.IncludeExternal),
|
||||
slog.Bool("dry-run", s.dryRun),
|
||||
)
|
||||
if s.dryRun {
|
||||
return 0
|
||||
}
|
||||
@ -341,13 +340,12 @@ func (s *Sandbox) imageRateLimitWait(ls *lua.LState) int {
|
||||
return 1
|
||||
}
|
||||
// delay for freq (until timeout reached), and then retry
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": r.r.CommonName(),
|
||||
"current": rl.Remain,
|
||||
"target": limit,
|
||||
"delay": freq.String(),
|
||||
}).Info("Delaying for ratelimit")
|
||||
s.log.Info("Delaying for ratelimit",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", r.r.CommonName()),
|
||||
slog.Int("current", rl.Remain),
|
||||
slog.Int("target", limit),
|
||||
slog.String("delay", freq.String()))
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ls.Push(lua.LBool(false))
|
||||
|
@ -2,9 +2,9 @@ package sandbox
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"reflect"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
|
||||
"github.com/regclient/regclient/cmd/regbot/internal/go2lua"
|
||||
@ -107,11 +107,10 @@ func (s *Sandbox) manifestDelete(ls *lua.LState) int {
|
||||
d := m.m.GetDescriptor()
|
||||
r.Digest = d.Digest.String()
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": r.CommonName(),
|
||||
"dry-run": s.dryRun,
|
||||
}).Info("Delete manifest")
|
||||
s.log.Info("Delete manifest",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", r.CommonName()),
|
||||
slog.Bool("dry-run", s.dryRun))
|
||||
if s.dryRun {
|
||||
return 0
|
||||
}
|
||||
@ -192,12 +191,11 @@ func (s *Sandbox) manifestGetWithOpts(ls *lua.LState, list bool) int {
|
||||
if !list && ls.GetTop() == 2 {
|
||||
plat = ls.CheckString(2)
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": r.r.CommonName(),
|
||||
"list": list,
|
||||
"platform": plat,
|
||||
}).Debug("Retrieve manifest")
|
||||
s.log.Debug("Retrieve manifest",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", r.r.CommonName()),
|
||||
slog.Any("list", list),
|
||||
slog.String("platform", plat))
|
||||
m, err := s.rcManifestGet(r.r, list, plat)
|
||||
if err != nil {
|
||||
ls.RaiseError("Failed retrieving \"%s\" manifest: %v", r.r.CommonName(), err)
|
||||
@ -218,10 +216,9 @@ func (s *Sandbox) manifestHead(ls *lua.LState) int {
|
||||
}
|
||||
r := s.checkReference(ls, 1)
|
||||
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": r.r.CommonName(),
|
||||
}).Debug("Retrieve manifest with head")
|
||||
s.log.Debug("Retrieve manifest with head",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", r.r.CommonName()))
|
||||
|
||||
m, err := s.rc.ManifestHead(s.ctx, r.r)
|
||||
if err != nil {
|
||||
@ -249,10 +246,9 @@ func (s *Sandbox) manifestJSON(ls *lua.LState) int {
|
||||
func (s *Sandbox) manifestPut(ls *lua.LState) int {
|
||||
sbm := s.checkManifest(ls, 1, true, false)
|
||||
r := s.checkReference(ls, 2)
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": r.r.CommonName(),
|
||||
}).Debug("Put manifest")
|
||||
s.log.Debug("Put manifest",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", r.r.CommonName()))
|
||||
|
||||
m, err := manifest.New(manifest.WithOrig(sbm.m.GetOrig()))
|
||||
if err != nil {
|
||||
@ -282,10 +278,9 @@ func (s *Sandbox) rcManifestGet(r ref.Ref, list bool, pStr string) (manifest.Man
|
||||
if pStr != "" {
|
||||
plat, err = platform.Parse(pStr)
|
||||
if err != nil {
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"platform": pStr,
|
||||
"err": err,
|
||||
}).Warn("Could not parse platform")
|
||||
s.log.Warn("Could not parse platform",
|
||||
slog.String("platform", pStr),
|
||||
slog.String("err", err.Error()))
|
||||
}
|
||||
}
|
||||
if plat.OS == "" {
|
||||
|
@ -2,8 +2,8 @@ package sandbox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
|
||||
"github.com/regclient/regclient/cmd/regbot/internal/go2lua"
|
||||
@ -49,11 +49,10 @@ func (s *Sandbox) repoLs(ls *lua.LState) int {
|
||||
optsArgs = append(optsArgs, scheme.WithRepoLast(opts.Last))
|
||||
}
|
||||
}
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"host": host,
|
||||
"opts": opts,
|
||||
}).Debug("Listing repositories")
|
||||
s.log.Debug("Listing repositories",
|
||||
slog.String("script", s.name),
|
||||
slog.String("host", host),
|
||||
slog.Any("opts", opts))
|
||||
repoList, err := s.rc.RepoList(s.ctx, host, optsArgs...)
|
||||
if err != nil {
|
||||
ls.RaiseError("Failed retrieving repo list: %v", err)
|
||||
|
@ -3,8 +3,9 @@ package sandbox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
|
||||
"github.com/regclient/regclient"
|
||||
@ -26,7 +27,7 @@ const (
|
||||
type Sandbox struct {
|
||||
name string
|
||||
ctx context.Context
|
||||
log *logrus.Logger
|
||||
log *slog.Logger
|
||||
ls *lua.LState
|
||||
rc *regclient.RegClient
|
||||
throttle *pqueue.Queue[struct{}]
|
||||
@ -66,7 +67,7 @@ func New(name string, opts ...Opt) *Sandbox {
|
||||
s.ctx = context.Background()
|
||||
}
|
||||
if s.log == nil {
|
||||
s.log = &logrus.Logger{}
|
||||
s.log = slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo}))
|
||||
}
|
||||
if s.rc == nil {
|
||||
s.rc = regclient.New()
|
||||
@ -98,8 +99,8 @@ func WithDryRun() Opt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithLog specifies a logrus logger
|
||||
func WithLog(log *logrus.Logger) Opt {
|
||||
// WithSlog specifies a slog logger
|
||||
func WithSlog(log *slog.Logger) Opt {
|
||||
return func(s *Sandbox) {
|
||||
s.log = log
|
||||
}
|
||||
@ -134,10 +135,9 @@ func (s *Sandbox) setupMod(name string, funcs map[string]lua.LGFunction, tables
|
||||
func (s *Sandbox) RunScript(script string) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"error": r,
|
||||
}).Error("Runtime error from script")
|
||||
s.log.Error("Runtime error from script",
|
||||
slog.String("script", s.name),
|
||||
slog.Any("error", r))
|
||||
err = ErrScriptFailed
|
||||
}
|
||||
}()
|
||||
@ -151,10 +151,9 @@ func (s *Sandbox) Close() {
|
||||
|
||||
func (s *Sandbox) sandboxLog(ls *lua.LState) int {
|
||||
msg := ls.CheckString(1)
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"message": msg,
|
||||
}).Info("User script message")
|
||||
s.log.Info("User script message",
|
||||
slog.String("script", s.name),
|
||||
slog.String("message", msg))
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
package sandbox
|
||||
|
||||
import (
|
||||
"github.com/sirupsen/logrus"
|
||||
"log/slog"
|
||||
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
)
|
||||
|
||||
@ -26,11 +27,10 @@ func (s *Sandbox) tagDelete(ls *lua.LState) int {
|
||||
ls.RaiseError("Context error: %v", err)
|
||||
}
|
||||
r := s.checkReference(ls, 1)
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"image": r.r.CommonName(),
|
||||
"dry-run": s.dryRun,
|
||||
}).Info("Delete tag")
|
||||
s.log.Info("Delete tag",
|
||||
slog.String("script", s.name),
|
||||
slog.String("image", r.r.CommonName()),
|
||||
slog.Bool("dry-run", s.dryRun))
|
||||
if s.dryRun {
|
||||
return 0
|
||||
}
|
||||
@ -51,10 +51,9 @@ func (s *Sandbox) tagLs(ls *lua.LState) int {
|
||||
ls.RaiseError("Context error: %v", err)
|
||||
}
|
||||
r := s.checkReference(ls, 1)
|
||||
s.log.WithFields(logrus.Fields{
|
||||
"script": s.name,
|
||||
"repo": r.r.CommonName(),
|
||||
}).Debug("Listing tags")
|
||||
s.log.Debug("Listing tags",
|
||||
slog.String("script", s.name),
|
||||
slog.String("repo", r.r.CommonName()))
|
||||
tl, err := s.rc.TagList(s.ctx, r.r)
|
||||
if err != nil {
|
||||
ls.RaiseError("Failed retrieving tag list: %v", err)
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"github.com/regclient/regclient/internal/auth"
|
||||
"github.com/regclient/regclient/internal/pqueue"
|
||||
"github.com/regclient/regclient/internal/reqmeta"
|
||||
"github.com/regclient/regclient/types"
|
||||
"github.com/regclient/regclient/types/errs"
|
||||
"github.com/regclient/regclient/types/warning"
|
||||
)
|
||||
@ -875,7 +876,7 @@ func (wt *wrapTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
warning.Handle(req.Context(), wt.c.slog, match[1])
|
||||
}
|
||||
}
|
||||
wt.c.slog.Log(req.Context(), slog.LevelDebug-4, "reg http request",
|
||||
wt.c.slog.Log(req.Context(), types.LevelTrace, "reg http request",
|
||||
slog.String("req-method", req.Method),
|
||||
slog.String("req-url", req.URL.String()),
|
||||
slog.Any("req-headers", reqHead),
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/regclient/regclient/types"
|
||||
)
|
||||
|
||||
func Logrus(logger *logrus.Logger) *logrusHandler {
|
||||
@ -93,7 +95,7 @@ func (h *logrusHandler) clone() *logrusHandler {
|
||||
}
|
||||
|
||||
var logrusToSlog = map[logrus.Level]slog.Level{
|
||||
logrus.TraceLevel: slog.LevelDebug - 4,
|
||||
logrus.TraceLevel: types.LevelTrace,
|
||||
logrus.DebugLevel: slog.LevelDebug,
|
||||
logrus.InfoLevel: slog.LevelInfo,
|
||||
logrus.WarnLevel: slog.LevelWarn,
|
||||
@ -103,7 +105,7 @@ var logrusToSlog = map[logrus.Level]slog.Level{
|
||||
}
|
||||
|
||||
func slogToLogrus(level slog.Level) logrus.Level {
|
||||
if level <= slog.LevelDebug-4 {
|
||||
if level <= types.LevelTrace {
|
||||
return logrus.TraceLevel
|
||||
} else if level <= slog.LevelDebug {
|
||||
return logrus.DebugLevel
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/regclient/regclient/types"
|
||||
)
|
||||
|
||||
func TestLogrus(t *testing.T) {
|
||||
@ -20,7 +22,7 @@ func TestLogrus(t *testing.T) {
|
||||
{
|
||||
name: "trace",
|
||||
logrusLevel: logrus.TraceLevel,
|
||||
slogLevel: slog.LevelDebug - 4,
|
||||
slogLevel: types.LevelTrace,
|
||||
},
|
||||
{
|
||||
name: "debug",
|
||||
@ -70,15 +72,15 @@ func TestLogrus(t *testing.T) {
|
||||
slogLogger.Warn("test warn with formatted attributes",
|
||||
slog.Group("child2", slog.String("attr-c1", "c1"), slog.Int("attr-c2", 2)),
|
||||
slog.String("attr7", "value7"), slog.Int("attr8", 8))
|
||||
slogLogger.Log(ctx, slog.LevelDebug-4, "test trace message", "attr9", "value9")
|
||||
slogLogger.Log(ctx, types.LevelTrace, "test trace message", "attr9", "value9")
|
||||
// check output for logs and check if enabled based on logging level
|
||||
logs := out.String()
|
||||
t.Logf("all logs:\n%s", logs)
|
||||
if strings.Contains(logs, "test trace message") {
|
||||
if tc.slogLevel > slog.LevelDebug-4 {
|
||||
if tc.slogLevel > types.LevelTrace {
|
||||
t.Errorf("trace message seen")
|
||||
}
|
||||
} else if tc.slogLevel <= slog.LevelDebug-4 {
|
||||
} else if tc.slogLevel <= types.LevelTrace {
|
||||
t.Errorf("trace message not seen")
|
||||
}
|
||||
if strings.Contains(logs, "test debug message") {
|
||||
|
8
types/slog.go
Normal file
8
types/slog.go
Normal file
@ -0,0 +1,8 @@
|
||||
package types
|
||||
|
||||
import "log/slog"
|
||||
|
||||
const (
|
||||
// LevelTrace is used for tracing network requests.
|
||||
LevelTrace = slog.LevelDebug - 4
|
||||
)
|
Loading…
x
Reference in New Issue
Block a user