@@ -12,8 +12,18 @@ export interface InfluxConfig extends MetricsConfig {
1212 } ;
1313}
1414
15+ interface InfluxQLResponse {
16+ series ?: Array < {
17+ name : string ;
18+ columns : string [ ] ;
19+ values : Array < Array < string | number | null > > ;
20+ } > ;
21+ error ?: string ;
22+ }
23+
1524export class InfluxMetricsCollector extends MetricsCollector {
1625 private writeApi : WriteApi ;
26+ private influxDb : InfluxDB ;
1727
1828 constructor (
1929 private config : InfluxConfig ,
@@ -22,11 +32,12 @@ export class InfluxMetricsCollector extends MetricsCollector {
2232 super ( config ) ;
2333
2434 const { url, username, password, org, bucket } = config . influx ;
25-
26- this . writeApi = new InfluxDB ( {
35+ this . influxDb = new InfluxDB ( {
2736 url,
2837 token : `${ username } :${ password } ` ,
29- } ) . getWriteApi ( org , bucket ) ;
38+ } ) ;
39+
40+ this . writeApi = this . influxDb . getWriteApi ( org , bucket ) ;
3041 }
3142
3243 public async init ( ) : Promise < void > {
@@ -58,6 +69,18 @@ export class InfluxMetricsCollector extends MetricsCollector {
5869 . stringField ( "txType" , metric . tx . txType )
5970 . stringField ( "labelFrom" , metric . tx . labelFrom || "" )
6071 . stringField ( "labelTo" , metric . tx . labelTo || "" ) ;
72+
73+ if ( metric . tx . gasPrice ) {
74+ point . floatField ( "gasPrice" , parseFloat ( metric . tx . gasPrice ) ) ;
75+ } else if ( metric . tx . maxFeePerGas ) {
76+ point . floatField ( "maxFeePerGas" , parseFloat ( metric . tx . maxFeePerGas ) ) ;
77+ if ( metric . tx . maxPriorityFeePerGas ) {
78+ point . floatField (
79+ "maxPriorityFeePerGas" ,
80+ parseFloat ( metric . tx . maxPriorityFeePerGas ) ,
81+ ) ;
82+ }
83+ }
6184 }
6285
6386 return point ;
@@ -66,12 +89,117 @@ export class InfluxMetricsCollector extends MetricsCollector {
6689 try {
6790 this . writeApi . writePoints ( points ) ;
6891 await this . writeApi . flush ( ) ;
69- this . logger . debug ( `Saved ${ metricsBatch . length } metrics` ) ;
7092 } catch ( error ) {
7193 this . logger . error ( error , "Error saving metrics to InfluxDB" ) ;
7294 }
7395 }
7496
97+ private async executeInfluxQLQuery (
98+ query : string ,
99+ ) : Promise < InfluxQLResponse | null > {
100+ const { url, username, password } = this . config . influx ;
101+ const database = this . config . influx . bucket ;
102+
103+ const queryUrl = `${ url } /query?db=${ database } &q=${ encodeURIComponent ( query ) } ` ;
104+
105+ try {
106+ const response = await fetch ( queryUrl , {
107+ method : "GET" ,
108+ headers : {
109+ Authorization : `Basic ${ Buffer . from ( `${ username } :${ password } ` ) . toString ( "base64" ) } ` ,
110+ "Content-Type" : "application/json" ,
111+ } ,
112+ } ) ;
113+
114+ const result = await response . json ( ) ;
115+
116+ if ( ! response . ok ) {
117+ throw new Error (
118+ `InfluxDB query failed: ${ response . status } ${ response . statusText } ` ,
119+ ) ;
120+ }
121+
122+ if ( result . error ) {
123+ throw new Error ( `InfluxQL error: ${ result . error } ` ) ;
124+ }
125+
126+ return result . results ?. [ 0 ] || null ;
127+ } catch ( error ) {
128+ this . logger . error ( error , `InfluxQL query failed: ${ query } ` ) ;
129+ return null ;
130+ }
131+ }
132+
133+ public async getAvgGasPrice ( ) : Promise < number | null > {
134+ try {
135+ const MIN_TXS = 5 ;
136+
137+ const query = `SELECT MEAN(gasPrice), COUNT(gasPrice) FROM tx_firewall_metrics WHERE time >= now() - 30d AND gasPrice > 0` ;
138+
139+ const response = await this . executeInfluxQLQuery ( query ) ;
140+
141+ if ( ! response || ! response . series || response . series . length === 0 ) {
142+ return null ;
143+ }
144+
145+ const series = response . series [ 0 ] ;
146+ if ( ! series . values || series . values . length === 0 ) {
147+ return null ;
148+ }
149+
150+ const data = series . values [ 0 ] ;
151+ const avgGasPrice = data [ 1 ] as number ;
152+ const count = data [ 2 ] as number ;
153+
154+ if ( ! avgGasPrice || count < MIN_TXS ) {
155+ return null ;
156+ }
157+
158+ return avgGasPrice ;
159+ } catch ( error ) {
160+ this . logger . error (
161+ error ,
162+ "Error fetching average gas price from InfluxDB" ,
163+ ) ;
164+ return null ;
165+ }
166+ }
167+
168+ public async getAvgFeePerGas ( ) : Promise < number | null > {
169+ try {
170+ const MIN_TXS = 5 ;
171+
172+ const query = `SELECT MEAN(maxFeePerGas), COUNT(maxFeePerGas) FROM tx_firewall_metrics WHERE time >= now() - 30d AND maxFeePerGas > 0` ;
173+
174+ const response = await this . executeInfluxQLQuery ( query ) ;
175+
176+ if ( ! response || ! response . series || response . series . length === 0 ) {
177+ return null ;
178+ }
179+
180+ const series = response . series [ 0 ] ;
181+ if ( ! series . values || series . values . length === 0 ) {
182+ return null ;
183+ }
184+
185+ const data = series . values [ 0 ] ;
186+ const avgFeePerGas = data [ 1 ] as number ;
187+ const count = data [ 2 ] as number ;
188+
189+ if ( ! avgFeePerGas || count < MIN_TXS ) {
190+ return null ;
191+ }
192+
193+ return avgFeePerGas ;
194+ } catch ( error ) {
195+ this . logger . error (
196+ error ,
197+ "Error fetching average fee per gas from InfluxDB" ,
198+ ) ;
199+ return null ;
200+ }
201+ }
202+
75203 public close ( ) {
76204 super . close ( ) ;
77205 this . writeApi . close ( ) . catch ( ( error : Error ) => {
0 commit comments