Files
mev-beta/pkg/observability/metrics.go
Administrator 5d9a1d72a0
Some checks failed
V2 CI/CD Pipeline / Pre-Flight Checks (push) Has been cancelled
V2 CI/CD Pipeline / Build & Dependencies (push) Has been cancelled
V2 CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
V2 CI/CD Pipeline / Unit Tests (100% Coverage Required) (push) Has been cancelled
V2 CI/CD Pipeline / Integration Tests (push) Has been cancelled
V2 CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
V2 CI/CD Pipeline / Decimal Precision Validation (push) Has been cancelled
V2 CI/CD Pipeline / Modularity Validation (push) Has been cancelled
V2 CI/CD Pipeline / Final Validation Summary (push) Has been cancelled
feat(foundation): create V2 foundation with core interfaces and types
Created complete V2 foundation infrastructure for modular MEV bot:

Core Types (pkg/types/):
- swap.go: SwapEvent with protocol support for 13+ DEXs
- pool.go: PoolInfo with multi-index cache support
- errors.go: Comprehensive error definitions
- Full validation methods and helper functions
- Proper decimal scaling (18 decimals internal representation)

Parser Interface (pkg/parsers/):
- Parser interface for protocol-specific implementations
- Factory interface for routing and registration
- Support for single log and full transaction parsing
- SupportsLog() for dynamic protocol identification

Cache Interface (pkg/cache/):
- PoolCache interface with multi-index support
- O(1) lookups by: address, token pair, protocol, liquidity
- Add, Update, Remove, Count, Clear operations
- Context-aware for cancellation support

Validation Interface (pkg/validation/):
- Validator interface for swap events and pools
- ValidationRules with configurable thresholds
- FilterValid() for batch validation
- Zero address, zero amount, decimal precision checks

Observability (pkg/observability/):
- Logger interface with structured logging (slog)
- Metrics interface with Prometheus integration
- Performance tracking (parse latency, execution)
- Business metrics (arbitrage opportunities, profit)

Project Files:
- go.mod: Module definition with ethereum and prometheus deps
- README.md: Complete project overview and documentation

Architecture Principles:
- Interface-first design for testability
- Single responsibility per interface
- Dependency injection ready
- Observable by default
- 18 decimal internal representation

Ready for Phase 1 implementation:
- All interfaces defined
- Error types established
- Core types validated
- Logging and metrics infrastructure ready

Next: Implement protocol-specific parsers (P2-001 through P2-055)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-10 14:43:36 +01:00

138 lines
4.1 KiB
Go

// Package observability provides logging and metrics infrastructure
package observability
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
// Metrics defines the metrics collection interface
type Metrics interface {
// RecordSwapEvent records a swap event being processed
RecordSwapEvent(protocol string, success bool)
// RecordParseLatency records parsing latency in seconds
RecordParseLatency(protocol string, latencySeconds float64)
// RecordArbitrageOpportunity records an arbitrage opportunity
RecordArbitrageOpportunity(profit float64)
// RecordExecution records a trade execution
RecordExecution(success bool, netProfit float64)
// IncrementPoolCacheSize increments the pool cache size
IncrementPoolCacheSize()
// DecrementPoolCacheSize decrements the pool cache size
DecrementPoolCacheSize()
}
// prometheusMetrics implements Metrics using Prometheus
type prometheusMetrics struct {
swapEventsTotal *prometheus.CounterVec
parseLatency *prometheus.HistogramVec
arbitrageOpportunities *prometheus.CounterVec
arbitrageProfit *prometheus.HistogramVec
executionsTotal *prometheus.CounterVec
executionProfit *prometheus.HistogramVec
poolCacheSize prometheus.Gauge
}
// NewMetrics creates a new Prometheus metrics collector
func NewMetrics(namespace string) Metrics {
return &prometheusMetrics{
swapEventsTotal: promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Name: "swap_events_total",
Help: "Total number of swap events processed",
},
[]string{"protocol", "status"},
),
parseLatency: promauto.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Name: "parse_latency_seconds",
Help: "Latency of parsing swap events in seconds",
Buckets: []float64{0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0},
},
[]string{"protocol"},
),
arbitrageOpportunities: promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Name: "arbitrage_opportunities_total",
Help: "Total number of arbitrage opportunities detected",
},
[]string{"status"},
),
arbitrageProfit: promauto.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Name: "arbitrage_profit_eth",
Help: "Arbitrage profit in ETH",
Buckets: []float64{0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0},
},
[]string{"status"},
),
executionsTotal: promauto.NewCounterVec(
prometheus.CounterOpts{
Namespace: namespace,
Name: "executions_total",
Help: "Total number of trade executions",
},
[]string{"status"},
),
executionProfit: promauto.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: namespace,
Name: "execution_profit_eth",
Help: "Execution profit in ETH (after gas)",
Buckets: []float64{-1.0, -0.1, -0.01, 0, 0.01, 0.1, 1.0, 10.0},
},
[]string{"status"},
),
poolCacheSize: promauto.NewGauge(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "pool_cache_size",
Help: "Current number of pools in cache",
},
),
}
}
func (m *prometheusMetrics) RecordSwapEvent(protocol string, success bool) {
status := "success"
if !success {
status = "failure"
}
m.swapEventsTotal.WithLabelValues(protocol, status).Inc()
}
func (m *prometheusMetrics) RecordParseLatency(protocol string, latencySeconds float64) {
m.parseLatency.WithLabelValues(protocol).Observe(latencySeconds)
}
func (m *prometheusMetrics) RecordArbitrageOpportunity(profit float64) {
m.arbitrageOpportunities.WithLabelValues("detected").Inc()
m.arbitrageProfit.WithLabelValues("detected").Observe(profit)
}
func (m *prometheusMetrics) RecordExecution(success bool, netProfit float64) {
status := "success"
if !success {
status = "failure"
}
m.executionsTotal.WithLabelValues(status).Inc()
m.executionProfit.WithLabelValues(status).Observe(netProfit)
}
func (m *prometheusMetrics) IncrementPoolCacheSize() {
m.poolCacheSize.Inc()
}
func (m *prometheusMetrics) DecrementPoolCacheSize() {
m.poolCacheSize.Dec()
}