feat(foundation): create V2 foundation with core interfaces and types
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
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
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>
This commit is contained in:
76
pkg/observability/logger.go
Normal file
76
pkg/observability/logger.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// Package observability provides logging and metrics infrastructure
|
||||
package observability
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Logger defines the logging interface
|
||||
type Logger interface {
|
||||
// Debug logs a debug message
|
||||
Debug(msg string, args ...any)
|
||||
|
||||
// Info logs an info message
|
||||
Info(msg string, args ...any)
|
||||
|
||||
// Warn logs a warning message
|
||||
Warn(msg string, args ...any)
|
||||
|
||||
// Error logs an error message
|
||||
Error(msg string, args ...any)
|
||||
|
||||
// With returns a logger with additional context fields
|
||||
With(args ...any) Logger
|
||||
|
||||
// WithContext returns a logger with context
|
||||
WithContext(ctx context.Context) Logger
|
||||
}
|
||||
|
||||
// slogLogger wraps slog.Logger to implement our Logger interface
|
||||
type slogLogger struct {
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// NewLogger creates a new structured logger
|
||||
func NewLogger(level slog.Level) Logger {
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: level,
|
||||
AddSource: true,
|
||||
}
|
||||
|
||||
handler := slog.NewJSONHandler(os.Stdout, opts)
|
||||
logger := slog.New(handler)
|
||||
|
||||
return &slogLogger{
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *slogLogger) Debug(msg string, args ...any) {
|
||||
l.logger.Debug(msg, args...)
|
||||
}
|
||||
|
||||
func (l *slogLogger) Info(msg string, args ...any) {
|
||||
l.logger.Info(msg, args...)
|
||||
}
|
||||
|
||||
func (l *slogLogger) Warn(msg string, args ...any) {
|
||||
l.logger.Warn(msg, args...)
|
||||
}
|
||||
|
||||
func (l *slogLogger) Error(msg string, args ...any) {
|
||||
l.logger.Error(msg, args...)
|
||||
}
|
||||
|
||||
func (l *slogLogger) With(args ...any) Logger {
|
||||
return &slogLogger{
|
||||
logger: l.logger.With(args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *slogLogger) WithContext(ctx context.Context) Logger {
|
||||
// Could extract trace ID, request ID, etc. from context
|
||||
return l
|
||||
}
|
||||
137
pkg/observability/metrics.go
Normal file
137
pkg/observability/metrics.go
Normal file
@@ -0,0 +1,137 @@
|
||||
// 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()
|
||||
}
|
||||
Reference in New Issue
Block a user