@@ -16,6 +16,7 @@ import {
1616 PrometheusClient ,
1717 PrometheusMetric ,
1818 PrometheusValue ,
19+ QueryResultData ,
1920} from '../infrastructure/prometheus_scraper' ;
2021import { DataUsageByUser , DataUsageTimeframe } from '../model/metrics' ;
2122
@@ -111,6 +112,8 @@ export class PrometheusManagerMetrics implements ManagerMetrics {
111112 Math . ceil ( now / PROMETHEUS_RANGE_QUERY_STEP_SECONDS ) * PROMETHEUS_RANGE_QUERY_STEP_SECONDS ;
112113 const start = end - timeframe . seconds ;
113114
115+ this . prunePrometheusCache ( ) ;
116+
114117 const [
115118 bandwidth ,
116119 bandwidthRange ,
@@ -121,34 +124,34 @@ export class PrometheusManagerMetrics implements ManagerMetrics {
121124 dataTransferredByAccessKeyRange ,
122125 tunnelTimeByAccessKeyRange ,
123126 ] = await Promise . all ( [
124- this . prometheusClient . query (
127+ this . cachedPrometheusClient . query (
125128 `sum(rate(shadowsocks_data_bytes_per_location{dir=~"c<p|p>t"}[${ PROMETHEUS_RANGE_QUERY_STEP_SECONDS } s]))`
126129 ) ,
127- this . prometheusClient . queryRange (
130+ this . cachedPrometheusClient . queryRange (
128131 `sum(rate(shadowsocks_data_bytes_per_location{dir=~"c<p|p>t"}[${ PROMETHEUS_RANGE_QUERY_STEP_SECONDS } s]))` ,
129132 start ,
130133 end ,
131134 `${ PROMETHEUS_RANGE_QUERY_STEP_SECONDS } s`
132135 ) ,
133- this . prometheusClient . query (
136+ this . cachedPrometheusClient . query (
134137 `sum(increase(shadowsocks_data_bytes_per_location{dir=~"c<p|p>t"}[${ timeframe . seconds } s])) by (location, asn, asorg)`
135138 ) ,
136- this . prometheusClient . query (
139+ this . cachedPrometheusClient . query (
137140 `sum(increase(shadowsocks_tunnel_time_seconds_per_location[${ timeframe . seconds } s])) by (location, asn, asorg)`
138141 ) ,
139- this . prometheusClient . query (
142+ this . cachedPrometheusClient . query (
140143 `sum(increase(shadowsocks_data_bytes{dir=~"c<p|p>t"}[${ timeframe . seconds } s])) by (access_key)`
141144 ) ,
142- this . prometheusClient . query (
145+ this . cachedPrometheusClient . query (
143146 `sum(increase(shadowsocks_tunnel_time_seconds[${ timeframe . seconds } s])) by (access_key)`
144147 ) ,
145- this . prometheusClient . queryRange (
148+ this . cachedPrometheusClient . queryRange (
146149 `sum(increase(shadowsocks_data_bytes{dir=~"c<p|p>t"}[${ PROMETHEUS_RANGE_QUERY_STEP_SECONDS } s])) by (access_key)` ,
147150 start ,
148151 end ,
149152 `${ PROMETHEUS_RANGE_QUERY_STEP_SECONDS } s`
150153 ) ,
151- this . prometheusClient . queryRange (
154+ this . cachedPrometheusClient . queryRange (
152155 `sum(increase(shadowsocks_tunnel_time_seconds[${ PROMETHEUS_RANGE_QUERY_STEP_SECONDS } s])) by (access_key)` ,
153156 start ,
154157 end ,
@@ -231,6 +234,41 @@ export class PrometheusManagerMetrics implements ManagerMetrics {
231234 accessKeys : Array . from ( accessKeyMap . values ( ) ) ,
232235 } ;
233236 }
237+
238+ private prometheusCache = new Map < string , { timestamp : number ; result : QueryResultData } > ( ) ;
239+
240+ private get cachedPrometheusClient ( ) {
241+ return new Proxy ( this . prometheusClient , {
242+ get : ( target , prop ) => {
243+ if ( typeof target [ prop ] !== 'function' ) {
244+ return target [ prop ] ;
245+ }
246+
247+ return async ( query , ...args ) => {
248+ const cacheId = `${ String ( prop ) } : ${ query } (args: ${ args . join ( ', ' ) } ))` ;
249+
250+ if ( this . prometheusCache . has ( cacheId ) ) {
251+ return this . prometheusCache . get ( cacheId ) . result ;
252+ }
253+
254+ const result = await ( target [ prop ] as Function ) ( query , ...args ) ;
255+
256+ this . prometheusCache . set ( cacheId , { timestamp : Date . now ( ) , result} ) ;
257+
258+ return result ;
259+ } ;
260+ } ,
261+ } ) ;
262+ }
263+
264+ private prunePrometheusCache ( ) {
265+ const now = Date . now ( ) ;
266+ for ( const [ key , value ] of this . prometheusCache ) {
267+ if ( now - value . timestamp > PROMETHEUS_RANGE_QUERY_STEP_SECONDS * 1000 ) {
268+ this . prometheusCache . delete ( key ) ;
269+ }
270+ }
271+ }
234272}
235273
236274function getServerMetricsLocationEntry (
0 commit comments