Skip to content

Commit

Permalink
Merge pull request #458 from snyk/refactor/observability-utilities
Browse files Browse the repository at this point in the history
refactor: observability utilities [IDE-175]
  • Loading branch information
teodora-sandu authored Mar 13, 2024
2 parents b545692 + 15b6cf4 commit cd9e82b
Show file tree
Hide file tree
Showing 18 changed files with 235 additions and 86 deletions.
8 changes: 6 additions & 2 deletions application/di/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"runtime"
"sync"

codeClientObservability "github.com/snyk/code-client-go/observability"

"github.com/snyk/snyk-ls/infrastructure/cli/cli_constants"

"github.com/adrg/xdg"
Expand Down Expand Up @@ -72,6 +74,7 @@ var codeActionService *codeaction.CodeActionsService
var fileWatcher *watcher.FileWatcher
var initMutex = &sync.Mutex{}
var notifier notification.Notifier
var codeInstrumentor codeClientObservability.Instrumentor

func Init() {
initMutex.Lock()
Expand Down Expand Up @@ -135,8 +138,9 @@ func initInfrastructure() {
snykCli = cli.NewExtensionExecutor()
}

snykCodeClient = code.NewHTTPRepository(instrumentor, errorReporter, networkAccess.GetHttpClient)
snykCodeBundleUploader = code.NewBundler(snykCodeClient, instrumentor)
codeInstrumentor = code.NewCodeInstrumentor()
snykCodeClient = code.NewSnykCodeHTTPClient(codeInstrumentor, errorReporter, networkAccess.GetHttpClient)
snykCodeBundleUploader = code.NewBundler(snykCodeClient, codeInstrumentor)
infrastructureAsCodeScanner = iac.New(instrumentor, errorReporter, analytics, snykCli)
openSourceScanner = oss.NewCLIScanner(instrumentor, errorReporter, analytics, snykCli, learnService, notifier, c)
scanNotifier, _ = appNotification.NewScanNotifier(notifier)
Expand Down
3 changes: 2 additions & 1 deletion application/di/test_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ func TestInit(t *testing.T) {
)
fakeClient := &code.FakeSnykCodeClient{}
snykCodeClient = fakeClient
snykCodeBundleUploader = code.NewBundler(snykCodeClient, instrumentor)
codeInstrumentor = code.NewCodeInstrumentor()
snykCodeBundleUploader = code.NewBundler(snykCodeClient, codeInstrumentor)
scanNotifier, _ = appNotification.NewScanNotifier(notifier)
// mock Learn Service
learnMock := mock_learn.NewMockService(gomock.NewController(t))
Expand Down
3 changes: 1 addition & 2 deletions domain/ide/command/code_fix_diffs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/require"

"github.com/snyk/snyk-ls/domain/observability/performance"
"github.com/snyk/snyk-ls/domain/snyk"
"github.com/snyk/snyk-ls/infrastructure/code"
"github.com/snyk/snyk-ls/infrastructure/snyk_api"
Expand All @@ -50,7 +49,7 @@ func Test_codeFixDiffs_Execute(t *testing.T) {
runtime.GOOS == "windows" {
t.Skip("Skipping test on windows")
}
instrumentor := performance.NewInstrumentor()
instrumentor := code.NewCodeInstrumentor()
snykCodeClient := &code.FakeSnykCodeClient{
UnifiedDiffSuggestions: []code.AutofixUnifiedDiffSuggestion{
{
Expand Down
10 changes: 10 additions & 0 deletions domain/observability/performance/noop_span.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ type NoopSpan struct {
FinishTime int64
}

func NewNoopSpan(ctx context.Context, operation string, txName string, started bool, finished bool) *NoopSpan {
return &NoopSpan{
Operation: operation,
TxName: txName,
Started: started,
Finished: finished,
ctx: ctx,
}
}

func (n *NoopSpan) GetDurationMs() int64 { return n.FinishTime - n.StartTime }

func (n *NoopSpan) Finish() {
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/segmentio/analytics-go v3.1.0+incompatible
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/snyk/code-client-go v0.0.0-20240313112756-810feaf079cc
github.com/snyk/go-application-framework v0.0.0-20240111143643-fa847b8a9a3b
github.com/sourcegraph/go-lsp v0.0.0-20200429204803-219e11d77f5d
github.com/stretchr/testify v1.8.4
Expand All @@ -43,7 +44,6 @@ require (
github.com/jcmturner/goidentity/v6 v6.0.1 // indirect
github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/snyk/code-client-go v0.0.0-20240307112310-c7f3dbe6e197 // indirect
github.com/snyk/go-httpauth v0.0.0-20231117135515-eb445fea7530 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
Expand Down Expand Up @@ -92,3 +92,4 @@ require (
)

//replace github.com/snyk/go-application-framework => ../go-application-framework
//replace github.com/snyk/code-client-go => ../code-client-go
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/snyk/code-client-go v0.0.0-20240307112310-c7f3dbe6e197 h1:OkEvk6W5nu1nmNDGpzvIeNtB6WRWdkcWw+TuCVQkM84=
github.com/snyk/code-client-go v0.0.0-20240307112310-c7f3dbe6e197/go.mod h1:rQsizM39PmM9IVS+sYFdiky7qlreczjfwJLWcQZOU5w=
github.com/snyk/code-client-go v0.0.0-20240313112756-810feaf079cc h1:kLgqsOkjD5nX/JfGH73HZp+m9w/OGrcSXaBY+pCqnuU=
github.com/snyk/code-client-go v0.0.0-20240313112756-810feaf079cc/go.mod h1:rQsizM39PmM9IVS+sYFdiky7qlreczjfwJLWcQZOU5w=
github.com/snyk/go-application-framework v0.0.0-20240111143643-fa847b8a9a3b h1:8fFjcaUZpjLV06AtIqtB7QRMYBH/5dxv2CJp319q2Gs=
github.com/snyk/go-application-framework v0.0.0-20240111143643-fa847b8a9a3b/go.mod h1:Yz/qxFyfhf0xbA+z8Vzr5IM9IDG+BS+2PiGaP1yAsEw=
github.com/snyk/go-httpauth v0.0.0-20231117135515-eb445fea7530 h1:s9PHNkL6ueYRiAKNfd8OVxlUOqU3qY0VDbgCD1f6WQY=
Expand Down
4 changes: 2 additions & 2 deletions infrastructure/code/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import (
"time"

"github.com/rs/zerolog/log"
codeClientObservability "github.com/snyk/code-client-go/observability"

"github.com/snyk/snyk-ls/application/config"
"github.com/snyk/snyk-ls/domain/ide/notification"
"github.com/snyk/snyk-ls/domain/observability/error_reporting"
"github.com/snyk/snyk-ls/domain/observability/performance"
"github.com/snyk/snyk-ls/domain/snyk"
"github.com/snyk/snyk-ls/internal/progress"
)
Expand All @@ -38,7 +38,7 @@ type Bundle struct {
BundleHash string
UploadBatches []*UploadBatch
Files map[string]BundleFile
instrumentor performance.Instrumentor
instrumentor codeClientObservability.Instrumentor
errorReporter error_reporting.ErrorReporter
requestId string
missingFiles []string
Expand Down
6 changes: 3 additions & 3 deletions infrastructure/code/bundle_uploader.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (

"github.com/puzpuzpuz/xsync"
"github.com/rs/zerolog/log"
codeClientObservability "github.com/snyk/code-client-go/observability"

"github.com/snyk/snyk-ls/domain/observability/performance"
"github.com/snyk/snyk-ls/internal/progress"
"github.com/snyk/snyk-ls/internal/util"
)
Expand All @@ -33,10 +33,10 @@ type BundleUploader struct {
SnykCode SnykCodeClient
supportedExtensions *xsync.MapOf[string, bool]
supportedConfigFiles *xsync.MapOf[string, bool]
instrumentor performance.Instrumentor
instrumentor codeClientObservability.Instrumentor
}

func NewBundler(SnykCode SnykCodeClient, instrumentor performance.Instrumentor) *BundleUploader {
func NewBundler(SnykCode SnykCodeClient, instrumentor codeClientObservability.Instrumentor) *BundleUploader {
return &BundleUploader{
SnykCode: SnykCode,
instrumentor: instrumentor,
Expand Down
9 changes: 4 additions & 5 deletions infrastructure/code/bundle_uploader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/adrg/xdg"
"github.com/stretchr/testify/assert"

"github.com/snyk/snyk-ls/domain/observability/performance"
"github.com/snyk/snyk-ls/internal/util"
)

Expand All @@ -38,7 +37,7 @@ func Test_Bundler_Upload(t *testing.T) {

t.Run("adds files to bundle", func(t *testing.T) {
snykCodeService := &FakeSnykCodeClient{}
var bundleUploader = BundleUploader{SnykCode: snykCodeService, instrumentor: performance.NewInstrumentor()}
var bundleUploader = BundleUploader{SnykCode: snykCodeService, instrumentor: NewCodeInstrumentor()}
documentURI, bundleFile := createTempFileInDir(t, "bundleDoc.java", 10, temporaryDir)
bundleFileMap := map[string]BundleFile{}
bundleFileMap[documentURI] = bundleFile
Expand All @@ -53,7 +52,7 @@ func Test_Bundler_Upload(t *testing.T) {

t.Run("when loads of files breaks down in 4MB bundles", func(t *testing.T) {
snykCodeService := &FakeSnykCodeClient{}
var bundler = BundleUploader{SnykCode: snykCodeService, instrumentor: performance.NewInstrumentor()}
var bundler = BundleUploader{SnykCode: snykCodeService, instrumentor: NewCodeInstrumentor()}

bundleFileMap := map[string]BundleFile{}
var missingFiles []string
Expand Down Expand Up @@ -93,7 +92,7 @@ func createTempFileInDir(t *testing.T, name string, size int, temporaryDir strin
func Test_IsSupportedLanguage(t *testing.T) {
const unsupportedFile = "C:\\some\\path\\Test.rs"
snykCodeMock := &FakeSnykCodeClient{}
bundler := NewBundler(snykCodeMock, performance.NewInstrumentor())
bundler := NewBundler(snykCodeMock, NewCodeInstrumentor())

t.Run("should return true for supported languages", func(t *testing.T) {
path := "C:\\some\\path\\Test.java"
Expand Down Expand Up @@ -129,7 +128,7 @@ func Test_IsSupported_ConfigFile(t *testing.T) {
snykCodeMock := &FakeSnykCodeClient{
ConfigFiles: configFilesFromFiltersEndpoint,
}
bundler := NewBundler(snykCodeMock, performance.NewInstrumentor())
bundler := NewBundler(snykCodeMock, NewCodeInstrumentor())
dir, _ := os.Getwd()

t.Run("should return true for supported config files", func(t *testing.T) {
Expand Down
51 changes: 13 additions & 38 deletions infrastructure/code/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/puzpuzpuz/xsync"
"github.com/rs/zerolog/log"

codeClientObservability "github.com/snyk/code-client-go/observability"

"github.com/snyk/snyk-ls/application/config"
"github.com/snyk/snyk-ls/domain/ide/notification"
"github.com/snyk/snyk-ls/domain/observability/error_reporting"
Expand All @@ -37,18 +39,11 @@ import (
"github.com/snyk/snyk-ls/infrastructure/filefilter"
"github.com/snyk/snyk-ls/infrastructure/learn"
"github.com/snyk/snyk-ls/infrastructure/snyk_api"
"github.com/snyk/snyk-ls/internal/float"
"github.com/snyk/snyk-ls/internal/product"
"github.com/snyk/snyk-ls/internal/progress"
"github.com/snyk/snyk-ls/internal/uri"
)

type ScanMetrics struct {
lastScanStartTime time.Time
lastScanDurationInSeconds float64
lastScanFileCount int
}

type ScanStatus struct {
// finished channel is closed once the scan has finished
finished chan bool
Expand All @@ -72,7 +67,7 @@ type Scanner struct {
BundleUploader *BundleUploader
SnykApiClient snyk_api.SnykApiClient
errorReporter error_reporting.ErrorReporter
analytics ux2.Analytics
analytics codeClientObservability.Analytics
changedFilesMutex sync.Mutex
scanStatusMutex sync.Mutex
runningScans map[string]*ScanStatus
Expand All @@ -94,11 +89,12 @@ func New(bundleUploader *BundleUploader,
learnService learn.Service,
notifier notification.Notifier,
) *Scanner {
codeAnalytics := NewCodeAnalytics(analytics)
sc := &Scanner{
BundleUploader: bundleUploader,
SnykApiClient: apiClient,
errorReporter: reporter,
analytics: analytics,
analytics: codeAnalytics,
runningScans: map[string]*ScanStatus{},
changedPaths: map[string]map[string]bool{},
fileFilters: xsync.NewMapOf[*filefilter.FileFilter](),
Expand Down Expand Up @@ -236,20 +232,18 @@ func (sc *Scanner) waitForScanToFinish(scanStatus *ScanStatus, folderPath string
return false
}

func (sc *Scanner) newMetrics(scanStartTime time.Time) *ScanMetrics {
func (sc *Scanner) newMetrics(scanStartTime time.Time) codeClientObservability.ScanMetrics {
if scanStartTime.IsZero() {
scanStartTime = time.Now()
}

return &ScanMetrics{
lastScanStartTime: scanStartTime,
}
return codeClientObservability.NewScanMetrics(scanStartTime, 0)
}

func (sc *Scanner) UploadAndAnalyze(ctx context.Context,
files <-chan string,
path string,
scanMetrics *ScanMetrics,
scanMetrics codeClientObservability.ScanMetrics,
changedFiles map[string]bool,
) (issues []snyk.Issue, err error) {
if ctx.Err() != nil {
Expand Down Expand Up @@ -277,7 +271,8 @@ func (sc *Scanner) UploadAndAnalyze(ctx context.Context,
return issues, nil
}
}
scanMetrics.lastScanFileCount = len(bundle.Files)

scanMetrics.SetLastScanFileCount(len(bundle.Files))

uploadedBundle, err := sc.BundleUploader.Upload(span.Context(), bundle, bundle.Files)
// TODO LSP error handling should be pushed UP to the LSP layer
Expand All @@ -304,7 +299,7 @@ func (sc *Scanner) UploadAndAnalyze(ctx context.Context,
log.Info().Msg("Canceling Code scan - Code scanner received cancellation signal")
return []snyk.Issue{}, nil
}
sc.trackResult(err == nil, scanMetrics)
sc.analytics.TrackScan(err == nil, scanMetrics)
return issues, err
}

Expand Down Expand Up @@ -442,9 +437,9 @@ func (sc *Scanner) UploadAndAnalyzeWithIgnores(
}, nil
}

func (sc *Scanner) handleCreationAndUploadError(path string, err error, msg string, scanMetrics *ScanMetrics) {
func (sc *Scanner) handleCreationAndUploadError(path string, err error, msg string, scanMetrics codeClientObservability.ScanMetrics) {
sc.errorReporter.CaptureErrorAndReportAsIssue(path, errors.Wrap(err, msg))
sc.trackResult(err == nil, scanMetrics)
sc.analytics.TrackScan(err == nil, scanMetrics)
}

type noFilesError struct{}
Expand Down Expand Up @@ -542,26 +537,6 @@ type UploadStatus struct {
TotalFiles int
}

func (sc *Scanner) trackResult(success bool, scanMetrics *ScanMetrics) {
var result ux2.Result
if success {
result = ux2.Success
} else {
result = ux2.Error
}

duration := time.Since(scanMetrics.lastScanStartTime)
scanMetrics.lastScanDurationInSeconds = float.ToFixed(duration.Seconds(), 2)
sc.analytics.AnalysisIsReady(
ux2.AnalysisIsReadyProperties{
AnalysisType: ux2.CodeSecurity,
Result: result,
FileCount: scanMetrics.lastScanFileCount,
DurationInSeconds: scanMetrics.lastScanDurationInSeconds,
},
)
}

func (sc *Scanner) useIgnoresFlow() bool {
response, err := sc.SnykApiClient.FeatureFlagStatus(snyk_api.FeatureFlagSnykCodeConsistentIgnores)
if err != nil {
Expand Down
52 changes: 52 additions & 0 deletions infrastructure/code/code_analytics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* © 2024 Snyk Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package code

import (
codeClientObservability "github.com/snyk/code-client-go/observability"

ux2 "github.com/snyk/snyk-ls/domain/observability/ux"
"github.com/snyk/snyk-ls/internal/float"
)

type CodeAnalytics struct {
analytics ux2.Analytics
}

func NewCodeAnalytics(analytics ux2.Analytics) CodeAnalytics {
return CodeAnalytics{analytics: analytics}
}
func (sc CodeAnalytics) TrackScan(success bool, scanMetrics codeClientObservability.ScanMetrics) {
var result ux2.Result
if success {
result = ux2.Success
} else {
result = ux2.Error
}

duration := scanMetrics.GetDuration()
lastScanDurationInSeconds := float.ToFixed(duration.Seconds(), 2)
lastScanFileCount := scanMetrics.GetLastScanFileCount()
sc.analytics.AnalysisIsReady(
ux2.AnalysisIsReadyProperties{
AnalysisType: ux2.CodeSecurity,
Result: result,
FileCount: lastScanFileCount,
DurationInSeconds: lastScanDurationInSeconds,
},
)
}
Loading

0 comments on commit cd9e82b

Please sign in to comment.