Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(client): add debug struct logging #304

Merged
merged 10 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion client/cmd/trdl/command/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const (
`{{$visibleFlags := visibleFlags .Flags}}` +
`{{$explicitlyExposedFlags := exposed .}}` +
`{{$optionsCmdFor := optionsCmdFor .}}` +
`{{$usageLine := usageLine .}}`
`{{$usageLine := usageLine .}}` +
`{{$versionLine := versionLine .}}`

// SectionAliases is the help template section that displays command aliases.
SectionAliases = `{{if gt .Aliases 0}}Aliases:
Expand Down Expand Up @@ -45,6 +46,10 @@ const (
// SectionTipsHelp is the help template section that displays the '--help' hint.
SectionTipsHelp = `{{if .HasSubCommands}}Use "{{$rootCmd}} <command> --help" for more information about a given command.
{{end}}`

// SectionVersion is the help template section that displays the command's version.
SectionVersion = `
{{ $versionLine }}`
)

// MainHelpTemplate if the template for 'help' used by most commands.
Expand All @@ -63,6 +68,7 @@ func MainUsageTemplate() string {
SectionFlags,
SectionUsage,
SectionTipsHelp,
SectionVersion,
}
return strings.TrimRightFunc(strings.Join(sections, ""), unicode.IsSpace)
}
6 changes: 6 additions & 0 deletions client/cmd/trdl/command/templater.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/werf/logboek"
"github.com/werf/logboek/pkg/types"
"github.com/werf/trdl/client/pkg/trdl"
)

type FlagExposer interface {
Expand Down Expand Up @@ -82,6 +83,7 @@ func (t *templater) templateFuncs(exposedFlags ...string) template.FuncMap {
"isRootCmd": t.isRootCmd,
"optionsCmdFor": t.optionsCmdFor,
"usageLine": t.usageLine,
"versionLine": t.versionLine,
"exposed": func(c *cobra.Command) *flag.FlagSet {
exposed := flag.NewFlagSet("exposed", flag.ContinueOnError)
if len(exposedFlags) > 0 {
Expand Down Expand Up @@ -186,6 +188,10 @@ func UsageLine(c *cobra.Command) string {
return usage
}

func (t *templater) versionLine(c *cobra.Command) string {
return fmt.Sprintf("Version: %s\n", trdl.Version)
}

func FlagsUsages(f *flag.FlagSet) string {
x := new(bytes.Buffer)

Expand Down
19 changes: 18 additions & 1 deletion client/cmd/trdl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ import (
"github.com/gookit/color"
"github.com/spf13/cobra"

"github.com/werf/common-go/pkg/util"
"github.com/werf/trdl/client/cmd/trdl/command"
"github.com/werf/trdl/client/pkg/logger"
)

var homeDir string
var (
homeDir string
debug bool
)

func main() {
if err := rootCmd().Execute(); err != nil {
Expand All @@ -26,6 +31,16 @@ func rootCmd() *cobra.Command {
Long: "The universal package manager for delivering your software updates securely from a TUF repository (more details on https://trdl.dev)",
SilenceUsage: true,
SilenceErrors: true,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
logLevel := "info"
if debug {
logLevel = "debug"
}
logger.GlobalLogger = logger.SetupGlobalLogger(logger.LoggerOptions{
Level: logLevel,
LogFormat: "text",
})
},
CompletionOptions: cobra.CompletionOptions{
DisableDefaultCmd: true,
},
Expand All @@ -34,6 +49,8 @@ func rootCmd() *cobra.Command {
rootCmd.SetHelpCommand(&cobra.Command{Hidden: true})
SetupHomeDir(rootCmd)

rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", util.GetBoolEnvironmentDefaultFalse("TRDL_DEBUG"), "Enable debug output (default $TRDL_DEBUG or false)")

groups := &command.Groups{}
*groups = append(*groups, command.Groups{
{
Expand Down
102 changes: 102 additions & 0 deletions client/pkg/logger/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package logger

import (
"log/slog"
"os"
)

var GlobalLogger *Logger

type LoggerInterface interface {
Debug(msg string, args ...any)
Error(msg string, args ...any)
Info(msg string, args ...any)
Warn(msg string, args ...any)
With(args ...any) LoggerInterface
}

type Logger struct {
LoggerInterface
}

type LoggerOptions struct {
Level string
LogFormat string
}

func SetupGlobalLogger(opts LoggerOptions) *Logger {
return NewLogger(&SlogWrapper{
logger: NewSlogLogger(SlogOptions{
Handler: slogHandler(opts.LogFormat, slogLevel(opts.Level)),
}),
})
}

func NewLogger(l LoggerInterface) *Logger {
return &Logger{LoggerInterface: l}
}

type SlogOptions struct {
Handler slog.Handler
}

func NewSlogLogger(opts SlogOptions) *slog.Logger {
return slog.New(opts.Handler)
}

type SlogWrapper struct {
logger *slog.Logger
}

func (s *SlogWrapper) Debug(msg string, args ...any) {
s.logger.Debug(msg, args...)
}

func (s *SlogWrapper) Error(msg string, args ...any) {
s.logger.Error(msg, args...)
}

func (s *SlogWrapper) Info(msg string, args ...any) {
s.logger.Info(msg, args...)
}

func (s *SlogWrapper) Warn(msg string, args ...any) {
s.logger.Warn(msg, args...)
}

func (s *SlogWrapper) With(args ...any) LoggerInterface {
return &SlogWrapper{
logger: s.logger.With(args...),
}
}

func (l *Logger) With(args ...any) *Logger {
return &Logger{LoggerInterface: l.LoggerInterface.With(args...)}
}

func slogLevel(l string) slog.Level {
switch l {
case "debug":
return slog.LevelDebug
case "info":
return slog.LevelInfo
case "warn":
return slog.LevelWarn
case "error":
return slog.LevelError
default:
return slog.LevelInfo
}
}

func slogHandler(format string, level slog.Level) slog.Handler {
options := &slog.HandlerOptions{
Level: level,
}
switch format {
case "json":
return slog.NewJSONHandler(os.Stdout, options)
default:
return slog.NewTextHandler(os.Stdout, options)
}
}
11 changes: 10 additions & 1 deletion client/pkg/tuf/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tuf

import (
"fmt"
"net/http"
"os"
"time"

Expand All @@ -11,6 +12,7 @@ import (

"github.com/werf/lockgate"
"github.com/werf/lockgate/pkg/file_locker"
"github.com/werf/trdl/client/pkg/logger"
"github.com/werf/trdl/client/pkg/util"
)

Expand Down Expand Up @@ -85,7 +87,14 @@ func (c *Client) initTufClient() error {
}
}

remote, err := tufClient.HTTPRemoteStore(c.repoUrl, nil, nil)
var remote tufClient.RemoteStore
httpClient := &http.Client{
Transport: &TracingTransport{
Transport: http.DefaultTransport,
Logger: *logger.GlobalLogger,
},
}
remote, err = tufClient.HTTPRemoteStore(c.repoUrl, nil, httpClient)
if err != nil {
return fmt.Errorf("unable to init http remote store: %w", err)
}
Expand Down
58 changes: 58 additions & 0 deletions client/pkg/tuf/trace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package tuf

import (
"net/http"
"net/http/httptrace"
"time"

"github.com/werf/trdl/client/pkg/logger"
)

type TracingTransport struct {
Transport http.RoundTripper
Logger logger.Logger
}

func (t *TracingTransport) RoundTrip(req *http.Request) (*http.Response, error) {
log := t.Logger.With("source", "tuf-client")
startTime := time.Now()

log.Debug("Request started",
"method", req.Method,
"url", req.URL.String(),
)

trace := &httptrace.ClientTrace{
DNSDone: func(info httptrace.DNSDoneInfo) {
log.Debug("DNS lookup done", "host", info.Addrs)
},
ConnectDone: func(network, addr string, err error) {
if err != nil {
log.Debug("Failed to connect",
"host", addr,
"error", err,
)
return
}
log.Debug("Connected", "address", addr)
},
}

req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))

resp, err := t.Transport.RoundTrip(req)
if err != nil {
log.Debug("Failed to send request",
"url", req.URL.String(),
"error", err,
)
return nil, err
}

log.Debug("Request completed",
"status", resp.Status,
"duration", time.Since(startTime).Seconds(),
)

return resp, nil
}
40 changes: 22 additions & 18 deletions docs/_data/sidebars/_cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,42 @@
# DO NOT EDIT!

cli: &cli

- title: Overview
url: /reference/cli/overview.html

- title: Configuration commands
f:
- title: trdl add
url: /reference/cli/trdl_add.html

- title: trdl remove
url: /reference/cli/trdl_remove.html
- title: trdl add
url: /reference/cli/trdl_add.html

- title: trdl list
url: /reference/cli/trdl_list.html
- title: trdl remove
url: /reference/cli/trdl_remove.html

- title: trdl set-default-channel
url: /reference/cli/trdl_set_default_channel.html
- title: trdl list
url: /reference/cli/trdl_list.html

- title: trdl set-default-channel
url: /reference/cli/trdl_set_default_channel.html

- title: Main commands
f:
- title: trdl use
url: /reference/cli/trdl_use.html

- title: trdl use
url: /reference/cli/trdl_use.html

- title: Advanced commands
f:
- title: trdl update
url: /reference/cli/trdl_update.html

- title: trdl exec
url: /reference/cli/trdl_exec.html
- title: trdl update
url: /reference/cli/trdl_update.html

- title: trdl exec
url: /reference/cli/trdl_exec.html

- title: trdl dir-path
url: /reference/cli/trdl_dir_path.html
- title: trdl dir-path
url: /reference/cli/trdl_dir_path.html

- title: trdl bin-path
url: /reference/cli/trdl_bin_path.html
- title: trdl bin-path
url: /reference/cli/trdl_bin_path.html
Loading
Loading