Skip to content

Commit

Permalink
refactor: Fix custom tx status metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
boecklim committed Nov 20, 2024
1 parent 176835c commit 08472be
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 31 deletions.
2 changes: 1 addition & 1 deletion cmd/arc/services/metamorph.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func StartMetamorph(logger *slog.Logger, arcConfig *config.ArcConfig, cacheStore
metamorph.WithSubmittedTxsChan(submittedTxsChan),
metamorph.WithProcessStatusUpdatesInterval(mtmConfig.ProcessStatusUpdateInterval),
metamorph.WithCallbackSender(callbacker),
metamorph.WithStatTimeLimits(mtmConfig.Stats.NotSeenTimeLimit, mtmConfig.Stats.NotMinedTimeLimit),
metamorph.WithStatTimeLimits(mtmConfig.Stats.NotSeenTimeLimit, mtmConfig.Stats.NotFinalTimeLimit),
metamorph.WithMaxRetries(mtmConfig.MaxRetries),
metamorph.WithMinimumHealthyConnections(mtmConfig.Health.MinimumHealthyConnections))

Expand Down
2 changes: 1 addition & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ type HealthConfig struct {

type StatsConfig struct {
NotSeenTimeLimit time.Duration `mapstructure:"notSeenTimeLimit"`
NotMinedTimeLimit time.Duration `mapstructure:"notMinedTimeLimit"`
NotFinalTimeLimit time.Duration `mapstructure:"notFinalTimeLimit"`
}

type APIConfig struct {
Expand Down
2 changes: 1 addition & 1 deletion config/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func getMetamorphConfig() *MetamorphConfig {
RejectCallbackContaining: []string{"http://localhost", "https://localhost"},
Stats: &StatsConfig{
NotSeenTimeLimit: 10 * time.Minute,
NotMinedTimeLimit: 20 * time.Minute,
NotFinalTimeLimit: 20 * time.Minute,
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion config/example_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ metamorph:
rejectCallbackContaining: [ "http://localhost", "https://localhost" ]
stats:
notSeenTimeLimit: 10m # amount of time after storing at which a non-seen tx will be counted towards not seen stat
notMinedTimeLimit: 20m # amount of time after storing at which a seen but not mined tx will be counted towards not mined stat
notFinalTimeLimit: 20m # amount of time after storing at which a seen but not mined tx will be counted towards not mined stat

blocktx:
listenAddr: localhost:8011 # address space for blocktx to listen on. Can be for example localhost:8011 or :8011 for listening on all addresses
Expand Down
4 changes: 2 additions & 2 deletions internal/metamorph/processor_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import (
"github.com/bitcoin-sv/arc/internal/metamorph/metamorph_api"
)

func WithStatTimeLimits(notSeenLimit time.Duration, notMinedLimit time.Duration) func(*Processor) {
func WithStatTimeLimits(notSeenLimit time.Duration, notFinalLimit time.Duration) func(*Processor) {
return func(p *Processor) {
p.stats = newProcessorStats(WithLimits(notSeenLimit, notMinedLimit))
p.stats = newProcessorStats(WithLimits(notSeenLimit, notFinalLimit))
}
}

Expand Down
26 changes: 16 additions & 10 deletions internal/metamorph/stats_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var ErrFailedToRegisterStats = fmt.Errorf("failed to register stats collector")

type processorStats struct {
notSeenLimit time.Duration
notMinedLimit time.Duration
notFinalLimit time.Duration

mu sync.RWMutex
statusStored prometheus.Gauge
Expand All @@ -34,16 +34,17 @@ type processorStats struct {
statusDoubleSpendAttempted prometheus.Gauge
statusRejected prometheus.Gauge
statusMined prometheus.Gauge
statusNotMined prometheus.Gauge
statusNotMined prometheus.Gauge // Todo: remove - is replaced by statusNotFinal
statusNotFinal prometheus.Gauge
statusNotSeen prometheus.Gauge
statusMinedTotal prometheus.Gauge
statusSeenOnNetworkTotal prometheus.Gauge
}

func WithLimits(notSeenLimit time.Duration, notMinedLimit time.Duration) func(*processorStats) {
func WithLimits(notSeenLimit time.Duration, notFinalLimit time.Duration) func(*processorStats) {
return func(p *processorStats) {
p.notSeenLimit = notSeenLimit
p.notMinedLimit = notMinedLimit
p.notFinalLimit = notFinalLimit
}
}

Expand Down Expand Up @@ -98,7 +99,7 @@ func newProcessorStats(opts ...func(stats *processorStats)) *processorStats {
Help: "Total number of monitored transactions with status MINED",
}),
notSeenLimit: notSeenLimitDefault,
notMinedLimit: notMinedLimitDefault,
notFinalLimit: notMinedLimitDefault,
}

for _, opt := range opts {
Expand All @@ -107,7 +108,11 @@ func newProcessorStats(opts ...func(stats *processorStats)) *processorStats {

p.statusNotMined = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "arc_status_not_mined_count",
Help: fmt.Sprintf("Number of monitored transactions which are SEEN_ON_NETWORK but haven reached status MINED for more than %s", p.notMinedLimit.String()),
Help: fmt.Sprintf("Number of monitored transactions which are SEEN_ON_NETWORK but haven reached status MINED for more than %s", p.notFinalLimit.String()),
})
p.statusNotFinal = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "arc_status_not_final_count",
Help: fmt.Sprintf("Number of monitored transactions which are not in a final state of either MINED or rejected %s", p.notFinalLimit.String()),
})
p.statusNotSeen = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "arc_status_not_seen_count",
Expand All @@ -131,7 +136,7 @@ func (p *Processor) StartCollectStats() error {
p.stats.statusDoubleSpendAttempted,
p.stats.statusRejected,
p.stats.statusMined,
p.stats.statusNotMined,
p.stats.statusNotFinal,
p.stats.statusNotSeen,
p.stats.statusSeenOnNetworkTotal,
p.stats.statusMinedTotal,
Expand Down Expand Up @@ -160,7 +165,7 @@ func (p *Processor) StartCollectStats() error {
p.stats.statusDoubleSpendAttempted,
p.stats.statusRejected,
p.stats.statusMined,
p.stats.statusNotMined,
p.stats.statusNotFinal,
p.stats.statusNotSeen,
p.stats.statusSeenOnNetworkTotal,
p.stats.statusMinedTotal,
Expand All @@ -176,7 +181,7 @@ func (p *Processor) StartCollectStats() error {

getStatsSince := p.now().Add(-1 * p.mapExpiryTime)

collectedStats, err := p.store.GetStats(p.ctx, getStatsSince, p.stats.notSeenLimit, p.stats.notMinedLimit)
collectedStats, err := p.store.GetStats(p.ctx, getStatsSince, p.stats.notSeenLimit, p.stats.notFinalLimit)
if err != nil {
p.logger.Error("failed to get stats", slog.String("err", err.Error()))
continue
Expand All @@ -193,7 +198,8 @@ func (p *Processor) StartCollectStats() error {
p.stats.statusDoubleSpendAttempted.Set(float64(collectedStats.StatusDoubleSpendAttempted))
p.stats.statusRejected.Set(float64(collectedStats.StatusRejected))
p.stats.statusMined.Set(float64(collectedStats.StatusMined))
p.stats.statusNotMined.Set(float64(collectedStats.StatusNotMined))
p.stats.statusNotMined.Set(float64(collectedStats.StatusNotFinal))
p.stats.statusNotFinal.Set(float64(collectedStats.StatusNotFinal))
p.stats.statusNotSeen.Set(float64(collectedStats.StatusNotSeen))
p.stats.statusSeenOnNetworkTotal.Set(float64(collectedStats.StatusSeenOnNetworkTotal))
p.stats.statusMinedTotal.Set(float64(collectedStats.StatusMinedTotal))
Expand Down
12 changes: 6 additions & 6 deletions internal/metamorph/store/postgresql/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -934,7 +934,7 @@ func (p *PostgreSQL) ClearData(ctx context.Context, retentionDays int32) (int64,
return rows, nil
}

func (p *PostgreSQL) GetStats(ctx context.Context, since time.Time, notSeenLimit time.Duration, notMinedLimit time.Duration) (*store.Stats, error) {
func (p *PostgreSQL) GetStats(ctx context.Context, since time.Time, notSeenLimit time.Duration, notFinalLimit time.Duration) (*store.Stats, error) {
q := `
SELECT
max(status_counts.status_count) FILTER (where status_counts.status = $3 )
Expand Down Expand Up @@ -1043,20 +1043,20 @@ func (p *PostgreSQL) GetStats(ctx context.Context, since time.Time, notSeenLimit
WHERE t.last_submitted_at > $1 AND status < $2 AND t.locked_by = $3
AND $4 - t.stored_at > $5
`
err = p.db.QueryRowContext(ctx, qNotSeen, since, metamorph_api.Status_SEEN_ON_NETWORK, p.hostname, p.now(), notSeenLimit.Seconds()).Scan(&stats.StatusNotSeen)
err = p.db.QueryRowContext(ctx, qNotSeen, since, metamorph_api.Status_SEEN_IN_ORPHAN_MEMPOOL, p.hostname, p.now(), notSeenLimit.Seconds()).Scan(&stats.StatusNotSeen)
if err != nil {
return nil, err
}

qNotMined := `
qNotFinal := `
SELECT
count(*)
FROM
metamorph.transactions t
WHERE t.last_submitted_at > $1 AND status = $2 AND t.locked_by = $3
AND EXTRACT(EPOCH FROM ($4 - t.stored_at)) > $5
WHERE t.last_submitted_at > $1 AND status >= $2 AND status <$3 AND t.locked_by = $4
AND EXTRACT(EPOCH FROM ($5 - t.stored_at)) > $6
`
err = p.db.QueryRowContext(ctx, qNotMined, since, metamorph_api.Status_SEEN_ON_NETWORK, p.hostname, p.now(), notMinedLimit.Seconds()).Scan(&stats.StatusNotMined)
err = p.db.QueryRowContext(ctx, qNotFinal, since, metamorph_api.Status_SEEN_ON_NETWORK, metamorph_api.Status_REJECTED, p.hostname, p.now(), notFinalLimit.Seconds()).Scan(&stats.StatusNotFinal)
if err != nil {
return nil, err
}
Expand Down
13 changes: 7 additions & 6 deletions internal/metamorph/store/postgresql/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ import (
"testing"
"time"

"github.com/bitcoin-sv/arc/internal/blocktx/blocktx_api"
"github.com/bitcoin-sv/arc/internal/metamorph/metamorph_api"
"github.com/bitcoin-sv/arc/internal/metamorph/store"
testutils "github.com/bitcoin-sv/arc/internal/test_utils"
"github.com/bitcoin-sv/arc/internal/testdata"
_ "github.com/golang-migrate/migrate/v4/source/file"
_ "github.com/lib/pq"
"github.com/ory/dockertest/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/bitcoin-sv/arc/internal/blocktx/blocktx_api"
"github.com/bitcoin-sv/arc/internal/metamorph/metamorph_api"
"github.com/bitcoin-sv/arc/internal/metamorph/store"
testutils "github.com/bitcoin-sv/arc/internal/test_utils"
"github.com/bitcoin-sv/arc/internal/testdata"
)

const (
Expand Down Expand Up @@ -714,7 +715,7 @@ func TestPostgresDB(t *testing.T) {
require.Equal(t, int64(1), res.StatusRejected)
require.Equal(t, int64(0), res.StatusSeenInOrphanMempool)
require.Equal(t, int64(1), res.StatusDoubleSpendAttempted)
require.Equal(t, int64(1), res.StatusNotMined)
require.Equal(t, int64(2), res.StatusNotFinal)
require.Equal(t, int64(2), res.StatusNotSeen)
require.Equal(t, int64(6), res.StatusMinedTotal)
require.Equal(t, int64(2), res.StatusSeenOnNetworkTotal)
Expand Down
5 changes: 3 additions & 2 deletions internal/metamorph/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"errors"
"time"

"github.com/libsv/go-p2p/chaincfg/chainhash"

"github.com/bitcoin-sv/arc/internal/blocktx/blocktx_api"
"github.com/bitcoin-sv/arc/internal/metamorph/metamorph_api"
"github.com/libsv/go-p2p/chaincfg/chainhash"
)

var ErrNotFound = errors.New("key could not be found")
Expand Down Expand Up @@ -56,7 +57,7 @@ type Stats struct {
StatusRejected int64
StatusMined int64
StatusNotSeen int64
StatusNotMined int64
StatusNotFinal int64
StatusSeenOnNetworkTotal int64
StatusMinedTotal int64
}
Expand Down
2 changes: 1 addition & 1 deletion test/config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ metamorph:
rejectCallbackContaining: [ "http://localhost", "https://localhost" ]
stats:
notSeenTimeLimit: 10m
notMinedTimeLimit: 20m
notFinalTimeLimit: 20m

blocktx:
listenAddr: 0.0.0.0:8011
Expand Down

0 comments on commit 08472be

Please sign in to comment.