Skip to content

Commit d86e719

Browse files
authored
chore(logging): normalize debug logging (#23)
1 parent b6b3de6 commit d86e719

6 files changed

Lines changed: 53 additions & 13 deletions

File tree

cmd/cencli/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func run() int {
6464
// Build client and app services (optional to allow config/init before auth)
6565
sdkCtx, sdkCancel := context.WithTimeout(context.Background(), 5*time.Second)
6666
defer sdkCancel()
67-
sdkClient, err := client.NewCensysSDK(sdkCtx, ds, cfg.Timeouts.HTTP, cfg.RetryStrategy)
67+
sdkClient, err := client.NewCensysSDK(sdkCtx, ds, cfg.Timeouts.HTTP, cfg.RetryStrategy, cfg.Debug)
6868
if err != nil {
6969
if errors.Is(err, authdom.ErrAuthNotFound) {
7070
// user hasn't configured enough to initialize the client

internal/pkg/clients/censys/censys.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"log/slog"
78
"runtime"
89
"time"
910

@@ -13,6 +14,7 @@ import (
1314
"github.com/censys/cencli/internal/pkg/cenclierrors"
1415
clienthttp "github.com/censys/cencli/internal/pkg/clients/http"
1516
authdom "github.com/censys/cencli/internal/pkg/domain/auth"
17+
applog "github.com/censys/cencli/internal/pkg/log"
1618
"github.com/censys/cencli/internal/store"
1719
"github.com/censys/cencli/internal/version"
1820
)
@@ -30,6 +32,7 @@ type censysSDK struct {
3032
client *censys.SDK
3133
retryStrategy config.RetryStrategy
3234
hasOrgID bool
35+
logger *slog.Logger
3336
}
3437

3538
func (c *censysSDK) HasOrgID() bool {
@@ -51,9 +54,16 @@ func NewCensysSDK(
5154
ds store.Store,
5255
httpRequestTimeout time.Duration,
5356
retryStrategy config.RetryStrategy,
57+
debug bool,
5458
) (Client, error) {
59+
// Create logger for HTTP and retry debugging (only logs when debug=true)
60+
var logger *slog.Logger
61+
if debug {
62+
logger = applog.New(debug, nil)
63+
}
64+
5565
sdkOpts := []censys.SDKOption{
56-
censys.WithClient(clienthttp.New(httpRequestTimeout, buildUserAgent())),
66+
censys.WithClient(clienthttp.New(httpRequestTimeout, buildUserAgent(), logger)),
5767
}
5868

5969
storedPAT, err := ds.GetLastUsedAuthByName(ctx, config.AuthName)
@@ -78,6 +88,7 @@ func NewCensysSDK(
7888
client: censys.New(sdkOpts...),
7989
retryStrategy: retryStrategy,
8090
hasOrgID: hasOrgID,
91+
logger: logger,
8192
}
8293

8394
return &censysSDKImpl{
@@ -125,6 +136,13 @@ func (c *censysSDK) executeWithRetry(ctx context.Context, operationFn func() Cli
125136
}
126137

127138
delay := calculateRetryDelay(baseDelay, c.retryStrategy.MaxDelay, c.retryStrategy.Backoff, attempt)
139+
if c.logger != nil {
140+
var statusCode int64
141+
if lastErr.StatusCode().IsPresent() {
142+
statusCode = lastErr.StatusCode().MustGet()
143+
}
144+
c.logger.Debug("retrying request", "attempt", attempt, "max_attempts", maxAttempts, "status", statusCode, "delay", delay)
145+
}
128146
timer := time.NewTimer(delay)
129147
select {
130148
case <-timer.C:

internal/pkg/clients/censys/censys_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestNewCensysSDK(t *testing.T) {
3939
LastUsedAt: time.Now(),
4040
}, nil)
4141

42-
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{})
42+
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{}, false)
4343
require.NoError(t, err)
4444
assert.NotNil(t, client)
4545
assert.True(t, client.HasOrgID())
@@ -59,7 +59,7 @@ func TestNewCensysSDK(t *testing.T) {
5959

6060
mockStore.EXPECT().GetLastUsedGlobalByName(ctx, config.OrgIDGlobalName).Return((*store.ValueForGlobal)(nil), store.ErrGlobalNotFound)
6161

62-
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{})
62+
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{}, false)
6363
require.NoError(t, err)
6464
assert.NotNil(t, client)
6565
assert.False(t, client.HasOrgID())
@@ -73,7 +73,7 @@ func TestNewCensysSDK(t *testing.T) {
7373

7474
mockStore.EXPECT().GetLastUsedAuthByName(ctx, config.AuthName).Return((*store.ValueForAuth)(nil), authdom.ErrAuthNotFound)
7575

76-
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{})
76+
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{}, false)
7777
assert.Error(t, err)
7878
assert.Nil(t, client)
7979
assert.True(t, errors.Is(err, authdom.ErrAuthNotFound))
@@ -87,7 +87,7 @@ func TestNewCensysSDK(t *testing.T) {
8787

8888
mockStore.EXPECT().GetLastUsedAuthByName(ctx, config.AuthName).Return((*store.ValueForAuth)(nil), errors.New("db error"))
8989

90-
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{})
90+
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{}, false)
9191
assert.Error(t, err)
9292
assert.Nil(t, client)
9393
assert.Contains(t, err.Error(), "failed to get last used auth")
@@ -107,7 +107,7 @@ func TestNewCensysSDK(t *testing.T) {
107107

108108
mockStore.EXPECT().GetLastUsedGlobalByName(ctx, config.OrgIDGlobalName).Return((*store.ValueForGlobal)(nil), errors.New("db error"))
109109

110-
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{})
110+
client, err := NewCensysSDK(ctx, mockStore, 0, config.RetryStrategy{}, false)
111111
assert.Error(t, err)
112112
assert.Nil(t, client)
113113
assert.Contains(t, err.Error(), "failed to get last used orgID")

internal/pkg/clients/http/http.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package http
22

33
import (
4+
"log/slog"
45
"net"
56
"net/http"
67
"time"
@@ -10,7 +11,9 @@ type Client struct {
1011
http.Client
1112
}
1213

13-
func New(requestTimeout time.Duration, userAgent string) *Client {
14+
// New creates an HTTP client configured for CLI usage.
15+
// If logger is non-nil, requests and responses will be logged at Debug level.
16+
func New(requestTimeout time.Duration, userAgent string, logger *slog.Logger) *Client {
1417
// Custom base transport tuned for CLI usage
1518
base := &http.Transport{
1619
Proxy: http.ProxyFromEnvironment,
@@ -31,6 +34,7 @@ func New(requestTimeout time.Duration, userAgent string) *Client {
3134
Transport: &roundTripper{
3235
RoundTripper: base,
3336
userAgent: userAgent,
37+
logger: logger,
3438
},
3539
Timeout: requestTimeout,
3640
},
@@ -40,6 +44,7 @@ func New(requestTimeout time.Duration, userAgent string) *Client {
4044
type roundTripper struct {
4145
http.RoundTripper
4246
userAgent string
47+
logger *slog.Logger
4348
}
4449

4550
func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
@@ -49,5 +54,22 @@ func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
4954
} else {
5055
req.Header.Set("User-Agent", existingUserAgent+" "+r.userAgent)
5156
}
52-
return r.RoundTripper.RoundTrip(req)
57+
58+
if r.logger != nil {
59+
r.logger.Debug("http request", "method", req.Method, "url", req.URL.String())
60+
}
61+
62+
start := time.Now()
63+
resp, err := r.RoundTripper.RoundTrip(req)
64+
duration := time.Since(start)
65+
66+
if r.logger != nil {
67+
if err != nil {
68+
r.logger.Debug("http error", "method", req.Method, "url", req.URL.String(), "error", err, "duration", duration)
69+
} else {
70+
r.logger.Debug("http response", "method", req.Method, "url", req.URL.String(), "status", resp.StatusCode, "duration", duration)
71+
}
72+
}
73+
74+
return resp, err
5375
}

internal/pkg/clients/http/http_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestUserAgentInjection_NoExisting(t *testing.T) {
2020
}))
2121
defer server.Close()
2222

23-
client := New(0, "cencli-test/0.1")
23+
client := New(0, "cencli-test/0.1", nil)
2424
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
2525
if err != nil {
2626
t.Fatalf("failed to create request: %v", err)
@@ -45,7 +45,7 @@ func TestUserAgentInjection_AppendsExisting(t *testing.T) {
4545
}))
4646
defer server.Close()
4747

48-
client := New(0, "cencli-test/0.1")
48+
client := New(0, "cencli-test/0.1", nil)
4949
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
5050
if err != nil {
5151
t.Fatalf("failed to create request: %v", err)
@@ -95,7 +95,7 @@ func TestUserAgentRoundTripper_AppendsOrSets(t *testing.T) {
9595
}
9696

9797
func TestNew_SetsUserAgent_AndNoDefaultTimeout(t *testing.T) {
98-
c := New(0, "cencli/ua")
98+
c := New(0, "cencli/ua", nil)
9999
if c.Timeout != 0 {
100100
t.Fatalf("expected timeout 0 (disabled), got %v", c.Timeout)
101101
}

internal/pkg/log/log.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ func New(debug bool, out io.Writer) *slog.Logger {
1616
if debug {
1717
level = slog.LevelDebug
1818
}
19-
handler := slog.NewJSONHandler(out, &slog.HandlerOptions{Level: level})
19+
handler := slog.NewTextHandler(out, &slog.HandlerOptions{Level: level})
2020
return slog.New(handler)
2121
}

0 commit comments

Comments
 (0)