Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Fix custom tx status metrics #652

Merged
merged 1 commit into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
28 changes: 17 additions & 11 deletions internal/metamorph/stats_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import (
const (
statCollectionIntervalDefault = 60 * time.Second
notSeenLimitDefault = 10 * time.Minute
notMinedLimitDefault = 20 * time.Minute
notFinalLimitDefault = 20 * time.Minute
)

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
kuba-4chain marked this conversation as resolved.
Show resolved Hide resolved
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: notFinalLimitDefault,
}

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
Loading