Monitoring Setup
A comprehensive guide to setting up monitoring and alerting for your liquid staking protocol on Solana. Learn about metrics collection, alerting systems, performance tracking, and incident response.
Last updated: 2024-03-21
Edit on GitHubMonitoring Overview
Comprehensive monitoring is crucial for maintaining a secure and efficient liquid staking protocol. This guide covers monitoring setup, metrics collection, alerting systems, and incident response procedures.
Key Metrics
- •Validator performance
- •Stake distribution
- •Protocol health
- •User operations
Alert Types
- •Security incidents
- •Performance issues
- •System anomalies
- •Threshold breaches
Implementation Guide
Learn how to implement comprehensive monitoring systems.
Monitoring Service
1import { Connection, PublicKey } from '@solana/web3.js'
2import { MetricsClient } from './metrics'
3import { AlertSystem } from './alerts'
4
5export class MonitoringService {
6 private connection: Connection
7 private metricsClient: MetricsClient
8 private alertSystem: AlertSystem
9 private stakePool: PublicKey
10 private config: MonitoringConfig
11
12 constructor(config: MonitoringConfig) {
13 this.connection = new Connection(config.rpcEndpoint)
14 this.metricsClient = new MetricsClient(config.metricsEndpoint)
15 this.alertSystem = new AlertSystem(config.alertEndpoint)
16 this.stakePool = config.stakePool
17 this.config = config
18 }
19
20 async monitorValidatorPerformance() {
21 const validators = await this.getValidators()
22
23 for (const validator of validators) {
24 // Check uptime
25 const uptime = await this.checkValidatorUptime(validator)
26 if (uptime < this.config.minUptime) {
27 await this.alertSystem.sendAlert({
28 type: 'ValidatorUptime',
29 severity: 'high',
30 validator: validator.toString(),
31 metric: uptime,
32 threshold: this.config.minUptime,
33 })
34 }
35
36 // Check skip rate
37 const skipRate = await this.checkValidatorSkipRate(validator)
38 if (skipRate > this.config.maxSkipRate) {
39 await this.alertSystem.sendAlert({
40 type: 'ValidatorSkipRate',
41 severity: 'high',
42 validator: validator.toString(),
43 metric: skipRate,
44 threshold: this.config.maxSkipRate,
45 })
46 }
47
48 // Record metrics
49 await this.metricsClient.recordValidatorMetrics({
50 validator: validator.toString(),
51 uptime,
52 skipRate,
53 commission: await this.getValidatorCommission(validator),
54 stake: await this.getValidatorStake(validator),
55 })
56 }
57 }
58
59 async monitorProtocolHealth() {
60 // Check total stake
61 const totalStake = await this.getTotalStake()
62 await this.metricsClient.recordMetric('total_stake', totalStake)
63
64 if (totalStake < this.config.minTotalStake) {
65 await this.alertSystem.sendAlert({
66 type: 'LowTotalStake',
67 severity: 'medium',
68 metric: totalStake,
69 threshold: this.config.minTotalStake,
70 })
71 }
72
73 // Check stake concentration
74 const concentration = await this.checkStakeConcentration()
75 if (concentration > this.config.maxConcentration) {
76 await this.alertSystem.sendAlert({
77 type: 'HighStakeConcentration',
78 severity: 'high',
79 metric: concentration,
80 threshold: this.config.maxConcentration,
81 })
82 }
83
84 // Monitor exchange rate
85 const exchangeRate = await this.getExchangeRate()
86 await this.metricsClient.recordMetric('exchange_rate', exchangeRate)
87
88 // Check reward rate
89 const rewardRate = await this.getRewardRate()
90 if (rewardRate < this.config.minRewardRate) {
91 await this.alertSystem.sendAlert({
92 type: 'LowRewardRate',
93 severity: 'medium',
94 metric: rewardRate,
95 threshold: this.config.minRewardRate,
96 })
97 }
98 }
99
100 async monitorUserOperations() {
101 // Monitor deposits
102 const deposits = await this.getRecentDeposits()
103 await this.metricsClient.recordMetric('deposits_count', deposits.length)
104 await this.metricsClient.recordMetric(
105 'deposits_volume',
106 deposits.reduce((sum, d) => sum + d.amount, 0)
107 )
108
109 // Monitor withdrawals
110 const withdrawals = await this.getRecentWithdrawals()
111 await this.metricsClient.recordMetric('withdrawals_count', withdrawals.length)
112 await this.metricsClient.recordMetric(
113 'withdrawals_volume',
114 withdrawals.reduce((sum, w) => sum + w.amount, 0)
115 )
116
117 // Check for unusual patterns
118 if (this.detectAnomalies(deposits, withdrawals)) {
119 await this.alertSystem.sendAlert({
120 type: 'UnusualActivityPattern',
121 severity: 'high',
122 details: 'Unusual deposit/withdrawal pattern detected',
123 })
124 }
125 }
126
127 async start() {
128 // Start monitoring loops
129 setInterval(
130 () => this.monitorValidatorPerformance(),
131 this.config.validatorCheckInterval
132 )
133 setInterval(
134 () => this.monitorProtocolHealth(),
135 this.config.protocolCheckInterval
136 )
137 setInterval(
138 () => this.monitorUserOperations(),
139 this.config.operationsCheckInterval
140 )
141
142 // Start metrics collection
143 await this.metricsClient.startCollection()
144
145 // Initialize alert handlers
146 await this.alertSystem.initialize()
147 }
148}
Metrics Collection
Implement comprehensive metrics collection and storage.
Metrics Client
1export class MetricsClient {
2 private endpoint: string
3 private buffer: MetricPoint[] = []
4 private flushInterval: number = 60000 // 1 minute
5
6 constructor(endpoint: string) {
7 this.endpoint = endpoint
8 }
9
10 async recordMetric(name: string, value: number) {
11 const point = {
12 name,
13 value,
14 timestamp: Date.now(),
15 }
16
17 this.buffer.push(point)
18
19 if (this.buffer.length >= 100) {
20 await this.flush()
21 }
22 }
23
24 async recordValidatorMetrics(metrics: ValidatorMetrics) {
25 await this.recordMetric(
26 `validator.${metrics.validator}.uptime`,
27 metrics.uptime
28 )
29 await this.recordMetric(
30 `validator.${metrics.validator}.skip_rate`,
31 metrics.skipRate
32 )
33 await this.recordMetric(
34 `validator.${metrics.validator}.commission`,
35 metrics.commission
36 )
37 await this.recordMetric(
38 `validator.${metrics.validator}.stake`,
39 metrics.stake
40 )
41 }
42
43 private async flush() {
44 if (this.buffer.length === 0) return
45
46 try {
47 await fetch(this.endpoint, {
48 method: 'POST',
49 headers: {
50 'Content-Type': 'application/json',
51 },
52 body: JSON.stringify({
53 metrics: this.buffer,
54 }),
55 })
56
57 this.buffer = []
58 } catch (error) {
59 console.error('Failed to flush metrics:', error)
60 }
61 }
62
63 async startCollection() {
64 setInterval(() => this.flush(), this.flushInterval)
65 }
66}
Alert System
Implement an alert system for incident detection and response.
Alert System
1export class AlertSystem {
2 private endpoint: string
3 private handlers: Map<AlertType, AlertHandler> = new Map()
4 private throttle: Map<string, number> = new Map()
5
6 constructor(endpoint: string) {
7 this.endpoint = endpoint
8 }
9
10 async initialize() {
11 // Register alert handlers
12 this.handlers.set('ValidatorUptime', this.handleUptimeAlert)
13 this.handlers.set('ValidatorSkipRate', this.handleSkipRateAlert)
14 this.handlers.set('LowTotalStake', this.handleStakeAlert)
15 this.handlers.set('HighStakeConcentration', this.handleConcentrationAlert)
16 this.handlers.set('UnusualActivityPattern', this.handleActivityAlert)
17 }
18
19 async sendAlert(alert: Alert) {
20 // Check throttle
21 const key = `${alert.type}:${alert.validator || 'protocol'}`
22 const lastAlert = this.throttle.get(key) || 0
23
24 if (Date.now() - lastAlert < 3600000) { // 1 hour
25 return // Skip alert
26 }
27
28 // Update throttle
29 this.throttle.set(key, Date.now())
30
31 // Handle alert
32 const handler = this.handlers.get(alert.type)
33 if (handler) {
34 await handler(alert)
35 }
36
37 // Send to alert endpoint
38 try {
39 await fetch(this.endpoint, {
40 method: 'POST',
41 headers: {
42 'Content-Type': 'application/json',
43 },
44 body: JSON.stringify(alert),
45 })
46 } catch (error) {
47 console.error('Failed to send alert:', error)
48 }
49 }
50
51 private async handleUptimeAlert(alert: Alert) {
52 if (alert.severity === 'high') {
53 // Consider emergency unstake
54 await this.considerEmergencyAction(alert)
55 }
56 }
57
58 private async handleSkipRateAlert(alert: Alert) {
59 if (alert.severity === 'high') {
60 // Consider reducing stake
61 await this.considerStakeReduction(alert)
62 }
63 }
64
65 private async handleStakeAlert(alert: Alert) {
66 // Notify stakeholders
67 await this.notifyStakeholders(alert)
68 }
69
70 private async handleConcentrationAlert(alert: Alert) {
71 // Trigger rebalancing
72 await this.triggerRebalancing(alert)
73 }
74
75 private async handleActivityAlert(alert: Alert) {
76 // Investigate unusual activity
77 await this.investigateActivity(alert)
78 }
79}
Monitoring Best Practices
- Implement comprehensive logging for all operations
- Set up proper alert thresholds and escalation procedures
- Monitor system resources and performance metrics
- Maintain historical data for trend analysis
- Have clear incident response procedures
- Regularly review and update monitoring parameters