Skip to content

Commit

Permalink
refactor: logger and docs (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
teodora-sandu authored Mar 19, 2024
1 parent fce22d6 commit 34b1814
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 41 deletions.
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ git --version
go version
```

Also make sure to install the tools required for development by running `make generate`.

## Setting up

Clone this repository with git.
Expand All @@ -41,6 +43,12 @@ To run the tests run:
make test
```

If writing unit tests, use the mocks generated by [GoMock](https://github.com/golang/mock) by running `make generate`.

If writing `pact` or integration tests, use the test implementations in [./internal/util/testutil](./internal/util/testutil).

If you've changed any of the interfaces you may need to re-run `make generate` to generate the mocks again.

## Code ownership

For current ownership assignments, see: [CODEOWNERS](./.github/CODEOWNERS).
Expand Down
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,69 @@
# code-client-go

A library that exposes scanning capabilities for Snyk Code that can be used in the [Snyk CLI](https://github.com/snyk/cli) as well as Snyk IDE plugins using the [Snyk Language Server](https://github.com/snyk/snyk-ls).

## Installation

```shell script
$ go get github.com/snyk/code-client-go
```

## Usage

### HTTP Client

Use the HTTP client to make HTTP requests with configured retriable codes and authorisation headers for Snyk Rest APIs.

```go
engine := workflow.NewDefaultWorkFlowEngine()
httpClient := http.NewHTTPClient(engine, engine.GetNetworkAccess().GetHttpClient, codeInstrumentor, codeErrorReporter)
```

The HTTP client exposes a `DoCall` function.


### Snyk Code Client

Use the Snyk Code Client to make calls to the DeepCode API using the `httpClient` HTTP client created above.


```go
engine := workflow.NewDefaultWorkFlowEngine()
snykCode := deepcode.NewSnykCodeClient(engine, httpClient, testutil.NewTestInstrumentor())
```

The Snyk Code Client exposes the following functions:
- `GetFilters`
- `CreateBundle`
- `ExtendBundle`

### Bundle Manager

Use the Bundle Manager to create bundles using the `snykCode` Snyk Code Client created above and then to extend it by uploading more files to it.

```go
bundleManager := bundle.NewBundleManager(snykCode, testutil.NewTestInstrumentor(), testutil.NewTestCodeInstrumentor())
```

The Bundle Manager exposes the following functions:
- `Create`
- `Upload`

### Code Scanner

Use the Code Scanner to trigger a scan for a Snyk Code workspace using the Bundle Manager created above:

```go
codeScanner := codeclient.NewCodeScanner(
bundleManager,
testutil.NewTestInstrumentor(),
testutil.NewTestCodeInstrumentor(),
testutils.NewTestAnalytics(),
)
```

The Code Scanner exposes a `UploadAndAnalyze` function.

### Observability

Under [./observability](./observability) we have defined some observability interfaces which allows consumers of the library to inject their own observability implementations as long as they follow the defined interfaces.
22 changes: 17 additions & 5 deletions bundle/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ package bundle

import (
"context"

"github.com/rs/zerolog/log"
"github.com/rs/zerolog"

"github.com/snyk/code-client-go/deepcode"
"github.com/snyk/code-client-go/observability"
)

//go:generate mockgen -destination=mocks/deepCodeBundle.go -source=deepCodeBundle.go -package mocks
//go:generate mockgen -destination=mocks/bundle.go -source=bundle.go -package mocks
type Bundle interface {
UploadBatch(ctx context.Context, host string, batch *Batch) error
GetBundleHash() string
Expand All @@ -39,6 +38,7 @@ type deepCodeBundle struct {
SnykCode deepcode.SnykCodeClient
instrumentor observability.Instrumentor
errorReporter observability.ErrorReporter
logger *zerolog.Logger
requestId string
rootPath string
files map[string]deepcode.BundleFile
Expand All @@ -48,11 +48,23 @@ type deepCodeBundle struct {
limitToFiles []string
}

func NewBundle(snykCode deepcode.SnykCodeClient, instrumentor observability.Instrumentor, errorReporter observability.ErrorReporter, bundleHash string, requestId string, rootPath string, files map[string]deepcode.BundleFile, limitToFiles []string, missingFiles []string) *deepCodeBundle {
func NewBundle(
snykCode deepcode.SnykCodeClient,
instrumentor observability.Instrumentor,
errorReporter observability.ErrorReporter,
logger *zerolog.Logger,
bundleHash string,
requestId string,
rootPath string,
files map[string]deepcode.BundleFile,
limitToFiles []string,
missingFiles []string,
) *deepCodeBundle {
return &deepCodeBundle{
SnykCode: snykCode,
instrumentor: instrumentor,
errorReporter: errorReporter,
logger: logger,
bundleHash: bundleHash,
requestId: requestId,
rootPath: rootPath,
Expand Down Expand Up @@ -96,7 +108,7 @@ func (b *deepCodeBundle) extendBundle(ctx context.Context, host string, uploadBa
var err error
if uploadBatch.hasContent() {
b.bundleHash, b.missingFiles, err = b.SnykCode.ExtendBundle(ctx, host, b.bundleHash, uploadBatch.documents, []string{})
log.Debug().Str("requestId", b.requestId).Interface("MissingFiles", b.missingFiles).Msg("extended deepCodeBundle on backend")
b.logger.Debug().Str("requestId", b.requestId).Interface("MissingFiles", b.missingFiles).Msg("extended deepCodeBundle on backend")
}

return err
Expand Down
22 changes: 15 additions & 7 deletions bundle/bundle_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ package bundle

import (
"context"
"github.com/rs/zerolog"
"github.com/snyk/go-application-framework/pkg/workflow"
"os"
"path/filepath"

"github.com/puzpuzpuz/xsync"
"github.com/rs/zerolog/log"

"github.com/snyk/code-client-go/deepcode"
"github.com/snyk/code-client-go/internal/util"
"github.com/snyk/code-client-go/observability"
Expand All @@ -34,6 +34,7 @@ type bundleManager struct {
SnykCode deepcode.SnykCodeClient
instrumentor observability.Instrumentor
errorReporter observability.ErrorReporter
logger *zerolog.Logger
supportedExtensions *xsync.MapOf[string, bool]
supportedConfigFiles *xsync.MapOf[string, bool]
}
Expand All @@ -56,11 +57,17 @@ type BundleManager interface {
) (Bundle, error)
}

func NewBundleManager(SnykCode deepcode.SnykCodeClient, instrumentor observability.Instrumentor, errorReporter observability.ErrorReporter) *bundleManager {
func NewBundleManager(
engine workflow.Engine,
SnykCode deepcode.SnykCodeClient,
instrumentor observability.Instrumentor,
errorReporter observability.ErrorReporter,
) *bundleManager {
return &bundleManager{
SnykCode: SnykCode,
instrumentor: instrumentor,
errorReporter: errorReporter,
logger: engine.GetLogger(),
supportedExtensions: xsync.NewMapOf[bool](),
supportedConfigFiles: xsync.NewMapOf[bool](),
}
Expand Down Expand Up @@ -96,7 +103,7 @@ func (b *bundleManager) Create(ctx context.Context,
var fileContent []byte
fileContent, err = os.ReadFile(absoluteFilePath)
if err != nil {
log.Error().Err(err).Str("filePath", absoluteFilePath).Msg("could not load content of file")
b.logger.Error().Err(err).Str("filePath", absoluteFilePath).Msg("could not load content of file")
continue
}

Expand Down Expand Up @@ -133,6 +140,7 @@ func (b *bundleManager) Create(ctx context.Context,
b.SnykCode,
b.instrumentor,
b.errorReporter,
b.logger,
bundleHash,
requestId,
rootPath,
Expand Down Expand Up @@ -193,10 +201,10 @@ func (b *bundleManager) groupInBatches(
file := files[filePath]
var fileContent = []byte(file.Content)
if batch.canFitFile(filePath, fileContent) {
log.Trace().Str("path", filePath).Int("size", len(fileContent)).Msgf("added to deepCodeBundle #%v", len(batches))
b.logger.Trace().Str("path", filePath).Int("size", len(fileContent)).Msgf("added to deepCodeBundle #%v", len(batches))
batch.documents[filePath] = file
} else {
log.Trace().Str("path", filePath).Int("size", len(fileContent)).Msgf("created new deepCodeBundle - %v bundles in this upload so far", len(batches))
b.logger.Trace().Str("path", filePath).Int("size", len(fileContent)).Msgf("created new deepCodeBundle - %v bundles in this upload so far", len(batches))
newUploadBatch := NewBatch(map[string]deepcode.BundleFile{})
newUploadBatch.documents[filePath] = file
batches = append(batches, newUploadBatch)
Expand All @@ -210,7 +218,7 @@ func (b *bundleManager) IsSupported(ctx context.Context, host string, file strin
if b.supportedExtensions.Size() == 0 && b.supportedConfigFiles.Size() == 0 {
filters, err := b.SnykCode.GetFilters(ctx, host)
if err != nil {
log.Error().Err(err).Msg("could not get filters")
b.logger.Error().Err(err).Msg("could not get filters")
return false, err
}

Expand Down
34 changes: 19 additions & 15 deletions bundle/bundle_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ package bundle_test
import (
"bytes"
"context"
deepcode2 "github.com/snyk/code-client-go/deepcode"
mocks2 "github.com/snyk/code-client-go/deepcode/mocks"
"github.com/rs/zerolog"
"os"
"path/filepath"
"strings"
"testing"

"github.com/golang/mock/gomock"
"github.com/snyk/code-client-go/observability/mocks"
"github.com/snyk/go-application-framework/pkg/workflow"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/snyk/code-client-go/bundle"
deepcode2 "github.com/snyk/code-client-go/deepcode"
mocks2 "github.com/snyk/code-client-go/deepcode/mocks"
"github.com/snyk/code-client-go/internal/util"
"github.com/snyk/code-client-go/observability/mocks"
)

func Test_Create(t *testing.T) {
Expand Down Expand Up @@ -60,7 +62,7 @@ func Test_Create(t *testing.T) {
err := os.WriteFile(file, []byte(data), 0600)
require.NoError(t, err)

var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundle, err := bundleManager.Create(context.Background(),
"testHost",
"testRequestId",
Expand Down Expand Up @@ -93,7 +95,7 @@ func Test_Create(t *testing.T) {
err := os.WriteFile(file, []byte(data), 0600)
require.NoError(t, err)

var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundle, err := bundleManager.Create(context.Background(),
"testHost",
"testRequestId",
Expand Down Expand Up @@ -131,7 +133,7 @@ func Test_Create(t *testing.T) {
)
require.NoError(t, err)

var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundle, err := bundleManager.Create(context.Background(),
"testHost",
"testRequestId",
Expand Down Expand Up @@ -168,7 +170,7 @@ func Test_Create(t *testing.T) {
},
)
require.NoError(t, err)
var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundle, err := bundleManager.Create(context.Background(),
"testHost",
"testRequestId",
Expand Down Expand Up @@ -202,7 +204,7 @@ func Test_Create(t *testing.T) {
err := os.WriteFile(file, []byte("some content so the file won't be skipped"), 0600)
assert.Nil(t, err)

var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundle, err := bundleManager.Create(context.Background(),
"testHost",
"testRequestId",
Expand Down Expand Up @@ -251,7 +253,7 @@ func Test_Create(t *testing.T) {
require.NoError(t, err)
}

var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundle, err := bundleManager.Create(context.Background(),
"testHost",
"testRequestId",
Expand All @@ -271,6 +273,8 @@ func Test_Upload(t *testing.T) {
_ = os.RemoveAll(temporaryDir)
})

logger := zerolog.Nop()

t.Run("adds files to deepCodeBundle", func(t *testing.T) {
ctrl := gomock.NewController(t)
mockSpan := mocks.NewMockSpan(ctrl)
Expand All @@ -282,14 +286,14 @@ func Test_Upload(t *testing.T) {
mockInstrumentor.EXPECT().Finish(gomock.Any()).Times(2)
mockErrorReporter := mocks.NewMockErrorReporter(ctrl)

var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
documentURI, bundleFile := createTempFileInDir(t, "bundleDoc.java", 10, temporaryDir)
bundleFileMap := map[string]deepcode2.BundleFile{}
bundleFileMap[documentURI] = bundleFile

_, err := bundleManager.Upload(context.Background(),
"testHost",
bundle.NewBundle(mockSnykCodeClient, mockInstrumentor, mockErrorReporter, "bundleHash", "testRequestId", "", bundleFileMap, []string{}, []string{documentURI}),
bundle.NewBundle(mockSnykCodeClient, mockInstrumentor, mockErrorReporter, &logger, "bundleHash", "testRequestId", "", bundleFileMap, []string{}, []string{documentURI}),
bundleFileMap)
assert.NoError(t, err)
})
Expand All @@ -305,7 +309,7 @@ func Test_Upload(t *testing.T) {
mockInstrumentor.EXPECT().StartSpan(gomock.Any(), gomock.Any()).Return(mockSpan).Times(2)
mockInstrumentor.EXPECT().Finish(gomock.Any()).Times(2)
mockErrorReporter := mocks.NewMockErrorReporter(ctrl)
var bundleManager = bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
var bundleManager = bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)

bundleFileMap := map[string]deepcode2.BundleFile{}
var missingFiles []string
Expand All @@ -327,7 +331,7 @@ func Test_Upload(t *testing.T) {

_, err := bundleManager.Upload(context.Background(),
"testHost",
bundle.NewBundle(mockSnykCodeClient, mockInstrumentor, mockErrorReporter, "bundleHash", "testRequestId", "", bundleFileMap, []string{}, missingFiles),
bundle.NewBundle(mockSnykCodeClient, mockInstrumentor, mockErrorReporter, &logger, "bundleHash", "testRequestId", "", bundleFileMap, []string{}, missingFiles),
bundleFileMap)
assert.Nil(t, err)
})
Expand All @@ -349,7 +353,7 @@ func Test_IsSupported_Extensions(t *testing.T) {
}, nil)
mockInstrumentor := mocks.NewMockInstrumentor(ctrl)
mockErrorReporter := mocks.NewMockErrorReporter(ctrl)
bundler := bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundler := bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)

t.Run("should return true for supported languages", func(t *testing.T) {
supported, _ := bundler.IsSupported(context.Background(), "testHost", "C:\\some\\path\\Test.java")
Expand Down Expand Up @@ -388,7 +392,7 @@ func Test_IsSupported_ConfigFiles(t *testing.T) {
}, nil)
mockInstrumentor := mocks.NewMockInstrumentor(ctrl)
mockErrorReporter := mocks.NewMockErrorReporter(ctrl)
bundler := bundle.NewBundleManager(mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
bundler := bundle.NewBundleManager(workflow.NewDefaultWorkFlowEngine(), mockSnykCodeClient, mockInstrumentor, mockErrorReporter)
dir, _ := os.Getwd()

t.Run("should return true for supported config files", func(t *testing.T) {
Expand Down
Loading

0 comments on commit 34b1814

Please sign in to comment.