Skip to content

Commit

Permalink
test: remove sql need on most ledger tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gfyrag authored and flemzord committed May 12, 2023
1 parent e40c005 commit 4ea669f
Show file tree
Hide file tree
Showing 64 changed files with 2,631 additions and 4,336 deletions.
18 changes: 2 additions & 16 deletions cmd/internal/analytics.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package internal

import (
"context"
"time"

"github.com/Masterminds/semver/v3"
Expand All @@ -28,17 +27,7 @@ func InitAnalyticsFlags(cmd *cobra.Command, defaultWriteKey string) {

func NewAnalyticsModule(v *viper.Viper, version string) fx.Option {
if v.GetBool(telemetryEnabledFlag) {
applicationId := viper.GetString(telemetryApplicationIdFlag)
var appIdProviderModule fx.Option
if applicationId == "" {
appIdProviderModule = fx.Provide(analytics.FromStorageAppIdProvider)
} else {
appIdProviderModule = fx.Provide(func() analytics.AppIdProvider {
return analytics.AppIdProviderFn(func(ctx context.Context) (string, error) {
return applicationId, nil
})
})
}
applicationID := viper.GetString(telemetryApplicationIdFlag)
writeKey := viper.GetString(telemetryWriteKeyFlag)
interval := viper.GetDuration(telemetryHeartbeatIntervalFlag)
if writeKey == "" {
Expand All @@ -56,10 +45,7 @@ func NewAnalyticsModule(v *viper.Viper, version string) fx.Option {
l.Infof("telemetry enabled but version '%s' is not semver, skip", version)
})
} else {
return fx.Options(
appIdProviderModule,
analytics.NewHeartbeatModule(version, writeKey, interval),
)
return analytics.NewHeartbeatModule(version, writeKey, applicationID, interval)
}
}
}
Expand Down
54 changes: 0 additions & 54 deletions cmd/internal/analytics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@ package internal

import (
"context"
"net/http"
"reflect"
"testing"
"time"

"github.com/formancehq/ledger/pkg/ledgertesting"
"github.com/formancehq/ledger/pkg/storage"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
"go.uber.org/fx"
"gopkg.in/segmentio/analytics-go.v3"
)

func TestAnalyticsFlags(t *testing.T) {
Expand Down Expand Up @@ -80,56 +76,6 @@ func TestAnalyticsFlags(t *testing.T) {
}
}

func TestAnalyticsModule(t *testing.T) {
v := viper.GetViper()
v.Set(telemetryEnabledFlag, true)
v.Set(telemetryWriteKeyFlag, "XXX")
v.Set(telemetryApplicationIdFlag, "appId")
v.Set(telemetryHeartbeatIntervalFlag, 10*time.Second)

handled := make(chan struct{})

module := NewAnalyticsModule(v, "1.0.0")
app := fx.New(
module,
fx.NopLogger,
fx.Provide(func(lc fx.Lifecycle) (storage.Driver, error) {
driver := ledgertesting.StorageDriver(t)
lc.Append(fx.Hook{
OnStart: driver.Initialize,
OnStop: func(ctx context.Context) error {
return driver.Close(ctx)
},
})
return driver, nil
}),
fx.Replace(analytics.Config{
BatchSize: 1,
Transport: roundTripperFn(func(req *http.Request) (*http.Response, error) {
select {
case <-handled:
// Nothing to do, the chan has already been closed
default:
close(handled)
}
return &http.Response{
StatusCode: http.StatusOK,
}, nil
}),
}))
require.NoError(t, app.Start(context.Background()))
defer func() {
require.NoError(t, app.Stop(context.Background()))
}()

select {
case <-time.After(time.Second):
require.Fail(t, "Timeout waiting first stats from analytics module")
case <-handled:
}

}

func TestAnalyticsModuleDisabled(t *testing.T) {
v := viper.GetViper()
v.Set(telemetryEnabledFlag, false)
Expand Down
7 changes: 0 additions & 7 deletions cmd/internal/utils.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package internal

import (
"net/http"
"os"
"strings"
)
Expand All @@ -14,9 +13,3 @@ func setEnvVar(key, value string) func() {
os.Setenv(flag, oldEnv)
}
}

type roundTripperFn func(req *http.Request) (*http.Response, error)

func (fn roundTripperFn) RoundTrip(req *http.Request) (*http.Response, error) {
return fn(req)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/formancehq/stack/libs/go-libs v0.0.0-20230222164357-55840b21a337
github.com/go-chi/chi/v5 v5.0.8
github.com/go-chi/cors v1.2.1
github.com/golang/mock v1.4.4
github.com/google/uuid v1.3.0
github.com/jackc/pgx/v5 v5.3.0
github.com/lib/pq v1.10.7
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down
148 changes: 148 additions & 0 deletions pkg/analytics/analytics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package analytics

import (
"context"
"crypto/sha256"
"encoding/base64"
"runtime"
"time"

"github.com/formancehq/ledger/pkg/core"
"github.com/formancehq/stack/libs/go-libs/logging"
"github.com/pbnjay/memory"
"gopkg.in/segmentio/analytics-go.v3"
)

const (
ApplicationStats = "Application stats"

VersionProperty = "version"
AccountsProperty = "accounts"
TransactionsProperty = "transactions"
LedgersProperty = "ledgers"
OSProperty = "os"
ArchProperty = "arch"
TimeZoneProperty = "tz"
CPUCountProperty = "cpuCount"
TotalMemoryProperty = "totalMemory"
)

type heartbeat struct {
version string
interval time.Duration
client analytics.Client
stopChan chan chan struct{}
backend Backend
}

func (m *heartbeat) Run(ctx context.Context) error {

enqueue := func() {
err := m.enqueue(ctx)
if err != nil {
logging.FromContext(ctx).WithFields(map[string]interface{}{
"error": err,
}).Error("enqueuing analytics")
}
}

enqueue()
for {
select {
case ch := <-m.stopChan:
ch <- struct{}{}
return nil
case <-ctx.Done():
return ctx.Err()
case <-time.After(m.interval):
enqueue()
}
}
}

func (m *heartbeat) Stop(ctx context.Context) error {
ch := make(chan struct{})
m.stopChan <- ch
select {
case <-ctx.Done():
return ctx.Err()
case <-ch:
return nil
}
}

func (m *heartbeat) enqueue(ctx context.Context) error {

appID, err := m.backend.AppID(ctx)
if err != nil {
return err
}

tz, _ := core.Now().Local().Zone()

properties := analytics.NewProperties().
Set(VersionProperty, m.version).
Set(OSProperty, runtime.GOOS).
Set(ArchProperty, runtime.GOARCH).
Set(TimeZoneProperty, tz).
Set(CPUCountProperty, runtime.NumCPU()).
Set(TotalMemoryProperty, memory.TotalMemory()/1024/1024)

ledgers, err := m.backend.ListLedgers(ctx)
if err != nil {
return err
}

ledgersProperty := map[string]any{}

for _, l := range ledgers {
stats := map[string]any{}
if err := func() error {
store, _, err := m.backend.GetLedgerStore(ctx, l, false)
if err != nil {
return err
}

transactions, err := store.CountTransactions(ctx)
if err != nil {
return err
}

accounts, err := store.CountAccounts(ctx)
if err != nil {
return err
}
stats[TransactionsProperty] = transactions
stats[AccountsProperty] = accounts

return nil
}(); err != nil {
return err
}

digest := sha256.New()
digest.Write([]byte(l))
ledgerHash := base64.RawURLEncoding.EncodeToString(digest.Sum(nil))

ledgersProperty[ledgerHash] = stats
}
if len(ledgersProperty) > 0 {
properties.Set(LedgersProperty, ledgersProperty)
}

return m.client.Enqueue(&analytics.Track{
AnonymousId: appID,
Event: ApplicationStats,
Properties: properties,
})
}

func newHeartbeat(backend Backend, client analytics.Client, version string, interval time.Duration) *heartbeat {
return &heartbeat{
version: version,
interval: interval,
client: client,
backend: backend,
stopChan: make(chan chan struct{}, 1),
}
}
Loading

0 comments on commit 4ea669f

Please sign in to comment.