Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue1097 fractional rates #1106

Merged
merged 5 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/source/Reference/sr3_options.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ flag
an option that has only True or False values (aka: a boolean value)

float
a floating point number.
a floating point number (3 decimal places max, numbers > 1000 are integers)

list
a list of string values, each succeeding occurrence catenates to the total.
Expand Down
1 change: 1 addition & 0 deletions docs/source/fr/Reference/sr3_options.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ flag

float
un nombre à virgule flottante, (séparateur de décimale étant un point.)
max de trois chiffres après le décimal, alors plus grand que 1000 devient des nombre entiers.

list
une liste de chaîne de caractères, chaque occurrence successive se rajoute au total.
Expand Down
66 changes: 56 additions & 10 deletions sarracenia/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ def __repr__(self) -> str:

count_options = [
'batch', 'count', 'exchangeSplit', 'instances', 'logRotateCount', 'no',
'post_exchangeSplit', 'prefetch', 'messageCountMax', 'messageRateMax',
'messageRateMin', 'runStateThreshold_cpuSlow', 'runStateThreshold_reject', 'runStateThreshold_retry', 'runStateThreshold_slow',
'post_exchangeSplit', 'prefetch', 'messageCountMax', 'runStateThreshold_cpuSlow',
'runStateThreshold_reject', 'runStateThreshold_retry', 'runStateThreshold_slow',
]


Expand All @@ -152,7 +152,7 @@ def __repr__(self) -> str:
'statehost', 'users', 'v2compatRenameDoublePost', 'wololo'
]

float_options = [ ]
float_options = [ 'messageRateMax', 'messageRateMin' ]

duration_options = [
'expire', 'housekeeping', 'logRotateInterval', 'message_ttl', 'fileAgeMax', 'fileAgeMin', 'metrics_writeInterval', \
Expand Down Expand Up @@ -338,12 +338,58 @@ def isTrue(S):
return S.lower() in ['true', 'yes', 'on', '1']

def parse_count(cstr):
"""
number argument accepts k,m,g suffix with i and b to use base 2 ) and +-
return value is integer.
"""
if cstr[0] == '-':
offset=1
else:
offset=0
count=humanfriendly.parse_size(cstr[offset:], binary=cstr[-1].lower() in ['i','b'] )
return -count if offset else count
try:
count=humanfriendly.parse_size(cstr[offset:], binary=cstr[-1].lower() in ['i','b'] )
return -count if offset else count
except Exception as Ex:
logger.error( f"failed to parse: {cstr} as a count value" )
logger.debug('Exception details: ', exc_info=True)
return 0

def parse_float(cstr):
"""
like parse_count, numeric argument accepts k,m,g suffix and +-.
below 1000, return a decimal number with 3 digits max.
"""
if type(cstr) is not str:
return cstr

try:
fa = parse_count(cstr)
if abs(fa) < 1000:
if cstr[-1] in [ 'b', 'i' ]:
if cstr[-2] in [ 'k' ]:
fa=float(cstr[0:-2])*1024
else:
fa=float(cstr[0:-1])
elif cstr[-1] in [ 'k' ]:
fa=float(cstr[0:-1])*1000
else:
fa=float(cstr)

# apply 3 sig figs.
if abs(fa) > 1000:
fa=int(fa)
elif abs(fa) > 100:
fa=round(fa,1)
elif abs(fa) > 10:
fa=round(fa,2)
else:
fa=round(fa,3)

return fa
except Exception as Ex:
logger.error( f"failed to parse: {cstr} as a float value" )
logger.debug('Exception details: ', exc_info=True)
return 0.0

def get_package_lib_dir():
return os.path.dirname(inspect.getfile(Config))
Expand Down Expand Up @@ -1114,7 +1160,7 @@ def add_option(self, option, kind='list', default_value=None, all_values=None ):
elif kind == 'float' or kind == float :
float_options.append(option)
if type(v) is not float:
setattr(self, option, float(v))
setattr(self, option, parse_float(v))
elif kind == 'list' or kind == list:
list_options.append( option )
if type(v) is not list:
Expand Down Expand Up @@ -1623,7 +1669,7 @@ def parse_line(self, component, cfg, cfname, lineno, l ):
setattr(self, k, durationToSeconds(v))
elif k in float_options:
try:
setattr(self, k, float(v))
setattr(self, k, parse_float(v))
except (ValueError, TypeError) as e:
logger.error(f"{','.join(self.files)}:{self.lineno} Ignored '{i}': {e}")
elif k in perm_options:
Expand Down Expand Up @@ -1673,7 +1719,7 @@ def parse_line(self, component, cfg, cfname, lineno, l ):
v = ' '.join(line[1:])
if hasattr(self, k):
if type(getattr(self, k)) is float:
setattr(self, k, float(v))
setattr(self, k, parse_float(v))
elif type(getattr(self, k)) is int:
# the only integers that have units are durations.
# integers without units will come out unchanged.
Expand Down Expand Up @@ -1855,7 +1901,7 @@ def finalize(self, component=None, config=None):

for f in float_options:
if hasattr(self, f) and (type(getattr(self, f)) is str):
setattr(self, f, float(getattr(self, f)))
setattr(self, f, parse_float(getattr(self, f)))

if ( (len(self.logEvents) > 0 ) or self.log_flowcb_needed) :
if ('sarracenia.flowcb.log.Log' not in self.plugins_late) and \
Expand Down Expand Up @@ -2028,7 +2074,7 @@ def check_undeclared_options(self):
setattr(self,u,isTrue(getattr(self,u)))
elif u in float_options:
if type( getattr(self,u) ) is not float:
setattr(self,u,float(getattr(self,u)))
setattr(self,u,parse_float(getattr(self,u)))
elif u in set_options:
if type( getattr(self,u) ) is not set:
setattr(self,u,self._parse_set_string(getattr(self,u),set()))
Expand Down
16 changes: 16 additions & 0 deletions tests/sarracenia/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ def test_read_line_counts():
options.parse_line( "subscribe", "ex1", "subscribe/ex1", 1, "batch 1.9" )
assert( options.batch == 1 )

def test_read_line_floats():

options = sarracenia.config.default_config()

options.parse_line( "subscribe", "ex1", "subscribe/ex1", 1, "messageRateMax 1.5mb" )
assert( options.messageRateMax == 1572864 )

options.parse_line( "subscribe", "ex1", "subscribe/ex1", 1, "messageRateMax 0.5k" )
assert( options.messageRateMax == 500 )

options.parse_line( "subscribe", "ex1", "subscribe/ex1", 1, "messageRateMax 0.5kb" )
assert( options.messageRateMax == 512 )

options.parse_line( "subscribe", "ex1", "subscribe/ex1", 1, "messageRateMax 0.5b" )
assert( options.messageRateMax == 0.5 )


def test_read_line_sets():

Expand Down
Loading