You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
4.9 KiB
107 lines
4.9 KiB
# Copyright (C) 2005-2025 Splunk Inc. All Rights Reserved.
|
|
|
|
import copy
|
|
import datetime
|
|
|
|
from ITOA.itoa_common import is_valid_dict, is_string_numeric, is_valid_str
|
|
from ITOA.setup_logging import logger
|
|
import custom_threshold_windows.constants as CustomThresholdWindowConstants
|
|
|
|
|
|
def update_custom_aggregate_thresholds(threshold_object, percentage_modifier):
|
|
"""
|
|
Modifies an aggregate_threshold policy by the percentage adjustment specified (total change to be passed in)
|
|
|
|
@param threshold_object: the aggregate_threshold policy
|
|
@param percentage_modifier: float that should already be calculated
|
|
"""
|
|
if 'thresholdLevels' in threshold_object:
|
|
for level in threshold_object.get('thresholdLevels'):
|
|
level['thresholdValue'] = round(level['thresholdValue'] * percentage_modifier, 3)
|
|
return True
|
|
return False
|
|
|
|
|
|
def calculate_custom_thresholds(kpi, active_window):
|
|
"""
|
|
If the given KPI needs to recalculate the custom thresholds for the active window, perform calculations and
|
|
update existing entries on the KPI.
|
|
|
|
@type kpi: dict
|
|
@param kpi: the kpi object itself
|
|
@type active_window: dict
|
|
@param active_window: the custom threshold window with threshold percentage differences
|
|
@rtype: dict
|
|
@return: the kpi dict (modified or not)
|
|
"""
|
|
if not kpi.get('active_custom_threshold_window', ''):
|
|
logger.warn(
|
|
'KPI {} could not recalculate custom thresholds because no custom threshold window was marked active.'
|
|
.format(kpi.get('_key', ''))
|
|
)
|
|
return kpi
|
|
|
|
kpi['recalculate_custom_thresholds'] = False
|
|
kpi_window = kpi.get('active_custom_threshold_window', '')
|
|
if not is_valid_str(kpi_window):
|
|
logger.error('Somehow custom threshold windows stored on KPI {} is malformed. Fixing KPI and skipping.'
|
|
.format(kpi.get('_key')))
|
|
kpi['active_custom_threshold_window'] = ''
|
|
return kpi
|
|
|
|
if not active_window:
|
|
logger.error('No custom threshold window passed in when trying to calculate new thresholds.')
|
|
return kpi
|
|
|
|
if active_window.get('window_type', '') == CustomThresholdWindowConstants.TYPE_PERCENTAGE:
|
|
percentage_config = active_window.get('window_config_percentage', 0)
|
|
if percentage_config == 0:
|
|
# If value is for some reason not set, do not modify
|
|
logger.warn(
|
|
'Custom threshold window {} does not have a percentage modification set.'
|
|
.format(active_window.get('_key')))
|
|
return kpi
|
|
elif abs(percentage_config) > 200:
|
|
logger.warn('Custom threshold window {} has a percentage set as greater than maximum'
|
|
' absolute value of 200. Calculating custom thresholds based on 200.'
|
|
.format(active_window.get('_key')))
|
|
percentage_config = 200 if percentage_config > 0 else -200
|
|
percentage_modifier = 1.00 + (percentage_config / 100)
|
|
|
|
if kpi.get('time_variate_thresholds', False):
|
|
kpi['time_variate_thresholds_specification_custom'] = copy.deepcopy(
|
|
kpi.get('time_variate_thresholds_specification'))
|
|
for policy in kpi['time_variate_thresholds_specification_custom']['policies']:
|
|
successful_update = update_custom_aggregate_thresholds(
|
|
kpi['time_variate_thresholds_specification_custom']['policies'][policy]['aggregate_thresholds'],
|
|
percentage_modifier)
|
|
if not successful_update:
|
|
logger.error('KPI {} had no thresholdLevels to update for an aggregate threshold '
|
|
'configuration. No modifications were applied to the base threshold levels.'
|
|
.format(kpi.get('_key')))
|
|
else:
|
|
kpi['aggregate_thresholds_custom'] = copy.deepcopy(kpi.get('aggregate_thresholds'))
|
|
successful_update = update_custom_aggregate_thresholds(kpi['aggregate_thresholds_custom'],
|
|
percentage_modifier)
|
|
if not successful_update:
|
|
logger.error('KPI {} had no thresholdLevels to update for its aggregate thresholds. No '
|
|
'modification were applied to the base threshold levels.'
|
|
.format(kpi.get('_key')))
|
|
else:
|
|
logger.error('Customer set static custom threshold window thresholds, which is not available in the'
|
|
'beta. Please fix and use the percentage adjustment for thresholds.')
|
|
|
|
return kpi
|
|
|
|
|
|
def get_human_readable_time_str(timestamp):
|
|
"""
|
|
Get a human-readable string representing the provided timestamp in the machine's timezone.
|
|
We use the machine timezone as we don't have any user-specific information.
|
|
|
|
:param timestamp: Unix-timestamp
|
|
:type timestamp: int
|
|
:return: str
|
|
"""
|
|
return datetime.datetime.utcfromtimestamp(timestamp).astimezone().strftime('%c (%Z)')
|