1+ from time import time
2+
13from .exporter import Exporter
24
5+ def is_positive_number (func ):
6+ def wrapper (self , value ):
7+ if not isinstance (value , int ) and not isinstance (value , float ):
8+ raise TypeError ("%s must be an integer or float" , func .__name__ )
9+ if value < 0 :
10+ raise ValueError ("%s must be a positive number" , func .__name__ )
11+ return func (self , value )
12+ return wrapper
13+
314
415def cached_exporter (cls ):
516 if not isinstance (cls , Exporter ) and not issubclass (cls , Exporter ):
@@ -13,54 +24,59 @@ class CachedExporter(cls):
1324 """
1425
1526 def __init__ (self , * args , ** kwargs ):
27+ """Call the super which reads the config.
28+ Prefer cache life setting from kwargs, then config, then default to 60 seconds.
29+ """
1630 super ().__init__ (* args , ** kwargs )
17- if cache_life := kwargs .pop ("cache_life" , None ):
18- self .cache_life = cache_life
19- elif not hasattr (self , "cache_life" ):
20- self .cache_life = 60
31+ self .cache_life = kwargs .pop ("cache_life" , self .config .get ("cache_life" , 60 ))
32+ self .logger .info ("Cache life set to: %d seconds" , self .cache_life )
33+
34+ @property
35+ def cache_life (self ) -> int :
36+ return getattr (self , "_cache_life" , 60 )
37+
38+ @cache_life .setter
39+ @is_positive_number
40+ def cache_life (self , value ) -> None :
41+ self .logger .info ("Setting cache_life to: %ds" , value )
42+ self ._cache_life = value
43+
44+ @property
45+ def cache_time (self ) -> int :
46+ return getattr (self , "_cache_time" , 0 )
2147
22- def __setattr__ (self , name , value ):
23- """Override setattr for cache_life"""
24- if name == "cache_life" :
25- if not isinstance (value , int ):
26- raise TypeError ("cache_life must be an integer" )
27- if value < 0 :
28- raise ValueError ("cache_life must be a positive integer" )
29- self .logger .info ("Setting cache_life to: %ds" , value )
30- super ().__setattr__ (name , value )
48+ @cache_time .setter
49+ @is_positive_number
50+ def cache_time (self , value ) -> None :
51+ self .logger .info ("Setting cache_time to: %d" , value )
52+ self ._cache_time = value
3153
32- def read_config (self ):
33- """Override read_config to add cache_life"""
34- super ().read_config ()
35- if hasattr (self , "cache_life" ):
36- self .logger .debug ("Cache life already set to: %ds" , self .cache_life )
37- return
38- self .cache_life = self .config .get ("cache_life" , 60 )
39- self .logger .info ("Set cache_life to: %d seconds" , self .cache_life )
54+ @property
55+ def cache_age (self ) -> int :
56+ """ Returns the age of the cache """
57+ cache_age = time () - getattr (self , "_cache_time" , 0 )
58+ self .logger .debug ("[%s] Cache age: %d" % (self .name , cache_age ))
59+ return time () - getattr (self , "_cache_time" , 0 )
4060
41- async def get_metrics (self , label_filter = {}):
42- """Get metrics from the exporter, caching the result."""
61+ async def get_metrics (self , label_filter = {}) -> list :
62+ """Get metrics from the exporter, respecting label filters and caching the result."""
4363 for key , value in label_filter .items ():
4464 if key not in self .labels and self .labels [key ] != value :
4565 self .logger .debug ("Label filter check failed: %s != %s" , self .labels , label_filter )
46- return
47- from time import time
66+ return []
4867
49- cache_time = time () - getattr (self , "_cache_time" , 0 )
50- name = getattr (self , "name" , self .__class__ .__name__ )
51- self .logger .debug ("[%s] Cache time: %d" % (name , cache_time ))
52- if not hasattr (self , "_cached_metrics" ) or cache_time >= self .cache_life :
53- self .metrics = []
68+ if not hasattr (self , "_cached_metrics" ) or self .cache_age >= self .cache_life :
5469 if new_metrics := await super ().get_metrics (label_filter = label_filter ):
5570 self .metrics = new_metrics
5671 self ._cached_metrics = new_metrics
57- self ._cache_time = time ()
72+ self .cache_time = time ()
5873 elif hasattr (self , "_cached_metrics" ):
59- self .logger .warning ("[%s] Exporter returned no metrics, returning cached metrics" % name )
74+ self .logger .warning ("[%s] Exporter returned no metrics, returning cached metrics" % self . name )
6075 self .metrics = self ._cached_metrics
6176 else :
62- self .logger .log (5 , "[%s] Returning cached metrics: %s" % (name , self ._cached_metrics ))
77+ self .logger .log (5 , "[%s] Returning cached metrics: %s" % (self . name , self ._cached_metrics ))
6378 self .metrics = self ._cached_metrics
79+ return self .metrics .copy ()
6480
6581 CachedExporter .__name__ = f"Cached{ cls .__name__ } "
6682 CachedExporter .__module__ = cls .__module__
0 commit comments