Skip to content

Commit

Permalink
Inject logger using context
Browse files Browse the repository at this point in the history
  • Loading branch information
gandarez committed Nov 6, 2024
1 parent e9a9451 commit a3cb116
Show file tree
Hide file tree
Showing 145 changed files with 2,630 additions and 1,906 deletions.
21 changes: 12 additions & 9 deletions cmd/api/api.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package api

import (
"context"
"fmt"
"strings"

Expand All @@ -13,31 +14,33 @@ import (

// NewClient initializes a new api client with all options following the
// passed in parameters.
func NewClient(params paramscmd.API) (*api.Client, error) {
func NewClient(ctx context.Context, params paramscmd.API) (*api.Client, error) {
withAuth, err := api.WithAuth(api.BasicAuth{
Secret: params.Key,
})
if err != nil {
return nil, fmt.Errorf("failed to set up auth option on api client: %w", err)
}

return newClient(params, withAuth)
return newClient(ctx, params, withAuth)
}

// NewClientWithoutAuth initializes a new api client with all options following the
// passed in parameters and disabled authentication.
func NewClientWithoutAuth(params paramscmd.API) (*api.Client, error) {
return newClient(params)
func NewClientWithoutAuth(ctx context.Context, params paramscmd.API) (*api.Client, error) {
return newClient(ctx, params)
}

// newClient contains the logic of client initialization, except auth initialization.
func newClient(params paramscmd.API, opts ...api.Option) (*api.Client, error) {
func newClient(ctx context.Context, params paramscmd.API, opts ...api.Option) (*api.Client, error) {
opts = append(opts, api.WithTimeout(params.Timeout))
opts = append(opts, api.WithHostname(strings.TrimSpace(params.Hostname)))

logger := log.Extract(ctx)

tz, err := timezone()
if err != nil {
log.Debugf("failed to detect local timezone: %s", err)
logger.Debugf("failed to detect local timezone: %s", err)

Check warning on line 43 in cmd/api/api.go

View check run for this annotation

Codecov / codecov/patch

cmd/api/api.go#L43

Added line #L43 was not covered by tests
} else {
opts = append(opts, api.WithTimezone(strings.TrimSpace(tz)))
}
Expand All @@ -54,7 +57,7 @@ func newClient(params paramscmd.API, opts ...api.Option) (*api.Client, error) {

opts = append(opts, withSSLCert)
} else if !params.DisableSSLVerify {
opts = append(opts, api.WithSSLCertPool(api.CACerts()))
opts = append(opts, api.WithSSLCertPool(api.CACerts(ctx)))
}

if params.ProxyURL != "" {
Expand All @@ -66,7 +69,7 @@ func newClient(params paramscmd.API, opts ...api.Option) (*api.Client, error) {
opts = append(opts, withProxy)

if strings.Contains(params.ProxyURL, `\\`) {
withNTLMRetry, err := api.WithNTLMRequestRetry(params.ProxyURL)
withNTLMRetry, err := api.WithNTLMRequestRetry(ctx, params.ProxyURL)

Check warning on line 72 in cmd/api/api.go

View check run for this annotation

Codecov / codecov/patch

cmd/api/api.go#L72

Added line #L72 was not covered by tests
if err != nil {
return nil, fmt.Errorf("failed to set up ntlm request retry option on api client: %w", err)
}
Expand All @@ -75,7 +78,7 @@ func newClient(params paramscmd.API, opts ...api.Option) (*api.Client, error) {
}
}

opts = append(opts, api.WithUserAgent(params.Plugin))
opts = append(opts, api.WithUserAgent(ctx, params.Plugin))

return api.NewClient(params.URL, opts...), nil
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/configread/configread.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configread

import (
"context"
"errors"
"fmt"
"strings"
Expand All @@ -18,7 +19,7 @@ type Params struct {
}

// Run prints the value for the given config key.
func Run(v *viper.Viper) (int, error) {
func Run(_ context.Context, v *viper.Viper) (int, error) {
output, err := Read(v)
if err != nil {

Check warning on line 24 in cmd/configread/configread.go

View check run for this annotation

Codecov / codecov/patch

cmd/configread/configread.go#L22-L24

Added lines #L22 - L24 were not covered by tests
return exitcode.ErrConfigFileRead, fmt.Errorf(
Expand Down
11 changes: 6 additions & 5 deletions cmd/configwrite/configwrite.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configwrite

import (
"context"
"errors"
"fmt"
"strings"
Expand All @@ -19,16 +20,16 @@ type Params struct {
}

// Run loads wakatime config file and call Write().
func Run(v *viper.Viper) (int, error) {
w, err := ini.NewWriter(v, ini.FilePath)
func Run(ctx context.Context, v *viper.Viper) (int, error) {
w, err := ini.NewWriter(ctx, v, ini.FilePath)
if err != nil {
return exitcode.ErrConfigFileParse, fmt.Errorf(
"failed to parse config file: %s",
err,
)
}

if err := Write(v, w); err != nil {
if err := Write(ctx, v, w); err != nil {

Check warning on line 32 in cmd/configwrite/configwrite.go

View check run for this annotation

Codecov / codecov/patch

cmd/configwrite/configwrite.go#L32

Added line #L32 was not covered by tests
return exitcode.ErrGeneric, fmt.Errorf(
"failed to write to config file: %s",
err,
Expand All @@ -39,13 +40,13 @@ func Run(v *viper.Viper) (int, error) {
}

// Write writes value(s) to given config key(s) and persist on disk.
func Write(v *viper.Viper, w ini.Writer) error {
func Write(ctx context.Context, v *viper.Viper, w ini.Writer) error {
params, err := LoadParams(v)
if err != nil {
return fmt.Errorf("failed to load command parameters: %w", err)
}

return w.Write(params.Section, params.KeyValue)
return w.Write(ctx, params.Section, params.KeyValue)
}

// LoadParams loads needed data from the configuration file.
Expand Down
19 changes: 11 additions & 8 deletions cmd/configwrite/configwrite_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configwrite_test

import (
"context"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -72,8 +73,10 @@ func TestWrite(t *testing.T) {

defer tmpFile.Close()

ctx := context.Background()

v := viper.New()
ini, err := ini.NewWriter(v, func(vp *viper.Viper) (string, error) {
ini, err := ini.NewWriter(ctx, v, func(_ context.Context, vp *viper.Viper) (string, error) {
assert.Equal(t, v, vp)
return tmpFile.Name(), nil
})
Expand All @@ -82,7 +85,7 @@ func TestWrite(t *testing.T) {
v.Set("config-section", "settings")
v.Set("config-write", map[string]string{"debug": "false"})

err = configwrite.Write(v, ini)
err = configwrite.Write(ctx, v, ini)
require.NoError(t, err)

err = ini.File.Reload()
Expand Down Expand Up @@ -117,7 +120,7 @@ func TestWriteErr(t *testing.T) {
v.Set("config-section", test.Section)
v.Set("config-write", test.Value)

err := configwrite.Write(v, w)
err := configwrite.Write(context.Background(), v, w)
require.Error(t, err)

assert.Equal(
Expand All @@ -133,7 +136,7 @@ func TestWriteErr(t *testing.T) {
func TestWriteSaveErr(t *testing.T) {
v := viper.New()
w := &mockWriter{
WriteFn: func(section string, keyValue map[string]string) error {
WriteFn: func(_ context.Context, section string, keyValue map[string]string) error {
assert.Equal(t, "settings", section)
assert.Equal(t, map[string]string{"debug": "false"}, keyValue)

Expand All @@ -144,14 +147,14 @@ func TestWriteSaveErr(t *testing.T) {
v.Set("config-section", "settings")
v.Set("config-write", map[string]string{"debug": "false"})

err := configwrite.Write(v, w)
err := configwrite.Write(context.Background(), v, w)
assert.Error(t, err)
}

type mockWriter struct {
WriteFn func(section string, keyValue map[string]string) error
WriteFn func(ctx context.Context, section string, keyValue map[string]string) error
}

func (m *mockWriter) Write(section string, keyValue map[string]string) error {
return m.WriteFn(section, keyValue)
func (m *mockWriter) Write(ctx context.Context, section string, keyValue map[string]string) error {
return m.WriteFn(ctx, section, keyValue)
}
23 changes: 13 additions & 10 deletions cmd/fileexperts/fileexperts.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fileexperts

import (
"context"
"fmt"

apicmd "github.com/wakatime/wakatime-cli/cmd/api"
Expand All @@ -18,8 +19,8 @@ import (
)

// Run executes the file-experts command.
func Run(v *viper.Viper) (int, error) {
output, err := FileExperts(v)
func Run(ctx context.Context, v *viper.Viper) (int, error) {
output, err := FileExperts(ctx, v)

Check warning on line 23 in cmd/fileexperts/fileexperts.go

View check run for this annotation

Codecov / codecov/patch

cmd/fileexperts/fileexperts.go#L22-L23

Added lines #L22 - L23 were not covered by tests
if err != nil {
if errwaka, ok := err.(wakaerror.Error); ok {
return errwaka.ExitCode(), fmt.Errorf("file experts fetch failed: %s", errwaka.Message())
Expand All @@ -31,29 +32,31 @@ func Run(v *viper.Viper) (int, error) {
)
}

log.Debugln("successfully fetched file experts")
logger := log.Extract(ctx)
logger.Debugln("successfully fetched file experts")

Check warning on line 37 in cmd/fileexperts/fileexperts.go

View check run for this annotation

Codecov / codecov/patch

cmd/fileexperts/fileexperts.go#L35-L37

Added lines #L35 - L37 were not covered by tests
fmt.Println(output)

return exitcode.Success, nil
}

// FileExperts returns a rendered file experts of todays coding activity.
func FileExperts(v *viper.Viper) (string, error) {
params, err := LoadParams(v)
func FileExperts(ctx context.Context, v *viper.Viper) (string, error) {
params, err := LoadParams(ctx, v)
if err != nil {
return "", fmt.Errorf("failed to load command parameters: %w", err)
}

handleOpts := initHandleOptions(params)

apiClient, err := apicmd.NewClientWithoutAuth(params.API)
apiClient, err := apicmd.NewClientWithoutAuth(ctx, params.API)
if err != nil {
return "", fmt.Errorf("failed to initialize api client: %w", err)
}

handle := fileexperts.NewHandle(apiClient, handleOpts...)

results, err := handle([]heartbeat.Heartbeat{{Entity: params.Heartbeat.Entity}})
results, err := handle(ctx, []heartbeat.Heartbeat{{Entity: params.Heartbeat.Entity}})
if err != nil {
return "", err
}
Expand All @@ -75,17 +78,17 @@ func FileExperts(v *viper.Viper) (string, error) {

// LoadParams loads file-expert config params from viper.Viper instance. Returns ErrAuth
// if failed to retrieve api key.
func LoadParams(v *viper.Viper) (paramscmd.Params, error) {
func LoadParams(ctx context.Context, v *viper.Viper) (paramscmd.Params, error) {
if v == nil {
return paramscmd.Params{}, fmt.Errorf("viper instance unset")
}

heartbeatParams, err := paramscmd.LoadHeartbeatParams(v)
heartbeatParams, err := paramscmd.LoadHeartbeatParams(ctx, v)
if err != nil {
return paramscmd.Params{}, fmt.Errorf("failed to load heartbeat params: %s", err)
}

apiParams, err := paramscmd.LoadAPIParams(v)
apiParams, err := paramscmd.LoadAPIParams(ctx, v)
if err != nil {
return paramscmd.Params{}, fmt.Errorf("failed to load API parameters: %w", err)
}
Expand Down
39 changes: 17 additions & 22 deletions cmd/fileexperts/fileexperts_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fileexperts_test

import (
"context"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -86,9 +87,8 @@ func TestFileExperts(t *testing.T) {
v.Set("plugin", plugin)
v.Set("project", "wakatime-cli")
v.Set("entity", "testdata/main.go")
v.Set("file-experts", true)

output, err := fileexperts.FileExperts(v)
output, err := fileexperts.FileExperts(context.Background(), v)
require.NoError(t, err)

assert.Equal(t, "You: 40 mins | Karl: 21 mins", output)
Expand All @@ -97,33 +97,31 @@ func TestFileExperts(t *testing.T) {
}

func TestFileExperts_NonExistingEntity(t *testing.T) {
tmpDir := t.TempDir()
ctx := context.Background()

logFile, err := os.CreateTemp(tmpDir, "")
logFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer logFile.Close()

v := viper.New()
v.Set("key", "00000000-0000-4000-8000-000000000000")
v.Set("api-url", "https://example.org")
v.Set("entity", "nonexisting")
v.Set("file-experts", true)
v.Set("key", "00000000-0000-4000-8000-000000000000")
v.Set("log-file", logFile.Name())
v.Set("verbose", true)

cmd.SetupLogging(v)
logger, err := cmd.SetupLogging(ctx, v)
require.NoError(t, err)

defer func() {
if file, ok := log.Output().(*os.File); ok {
_ = file.Sync()
file.Close()
} else if handler, ok := log.Output().(io.Closer); ok {
handler.Close()
}
}()
defer logger.Flush()

ctx = log.ToContext(ctx, logger)

_, err = fileexperts.FileExperts(ctx, v)
require.NoError(t, err)

_, err = fileexperts.FileExperts(v)
err = logFile.Sync()
require.NoError(t, err)

output, err := io.ReadAll(logFile)
Expand All @@ -148,9 +146,8 @@ func TestFileExperts_ErrApi(t *testing.T) {
v.Set("key", "00000000-0000-4000-8000-000000000000")
v.Set("api-url", testServerURL)
v.Set("entity", "testdata/main.go")
v.Set("file-experts", true)

_, err := fileexperts.FileExperts(v)
_, err := fileexperts.FileExperts(context.Background(), v)
require.Error(t, err)

var errapi api.Err
Expand Down Expand Up @@ -183,9 +180,8 @@ func TestFileExperts_ErrAuth(t *testing.T) {
v.Set("key", "00000000-0000-4000-8000-000000000000")
v.Set("api-url", testServerURL)
v.Set("entity", "testdata/main.go")
v.Set("file-experts", true)

_, err := fileexperts.FileExperts(v)
_, err := fileexperts.FileExperts(context.Background(), v)
require.Error(t, err)

var errauth api.ErrAuth
Expand Down Expand Up @@ -217,9 +213,8 @@ func TestFileExperts_ErrBadRequest(t *testing.T) {
v.Set("key", "00000000-0000-4000-8000-000000000000")
v.Set("api-url", testServerURL)
v.Set("entity", "testdata/main.go")
v.Set("file-experts", true)

_, err := fileexperts.FileExperts(v)
_, err := fileexperts.FileExperts(context.Background(), v)
require.Error(t, err)

var errbadRequest api.ErrBadRequest
Expand Down
Loading

0 comments on commit a3cb116

Please sign in to comment.