domain.miningrules.RuleParameters.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nop 9
dl 0
loc 11
rs 9.9
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
'''Mining Rules'''
2
import domain.minerstatistics
3
from domain.mining import Miner
4
5
class RuleParameters(object):
6
    '''configurable parameters for rules'''
7
    def __init__(self, minertype, hashlimit, controllertemplimit, boardtemplimit, restartaftersec, 
8
                 maxtempreset=None, hardware_errors_limit=None, hardware_errors_limit_time=None):
9
        self.minertype = minertype
10
        self.hashlimit = hashlimit
11
        self.controllertemplimit = controllertemplimit
12
        self.boardtemplimit = boardtemplimit
13
        self.restartaftersec = restartaftersec
14
        self.maxtempreset = maxtempreset
15
        self.hardware_errors_limit = hardware_errors_limit
16
        #hours (24h), minutes (60m), seconds (10s)
17
        self.hardware_errors_limit_time = hardware_errors_limit_time
18
19
class BrokenRule(object):
20
    '''broken rules'''
21
    def __init__(self, miner, action, parameter):
22
        self.miner = miner
23
        self.action = action
24
        self.parameter = parameter
25
26
    def __str__(self):
27
        return 'broke {0}:{1} {2}'.format(self.miner.name, self.action, self.parameter)
28
29
class MinerStatisticsRule(object):
30
    '''Rule for evaluating miner statistics'''
31
32
    def __init__(self, miner: Miner, statistics: domain.minerstatistics.MinerStatistics, ruleparameters: RuleParameters):
33
        self.miner = miner
34
        self.statistics = statistics
35
        self.ruleparameters = ruleparameters
36
        self.brokenrules = []
37
38
    @classmethod
39
    def hasreading(cls, reading):
40
        '''True when the reading is not empty'''
41
        if reading is None:
42
            return False
43
        if reading:
44
            return True
45
        return False
46
47
    @classmethod
48
    def hasreading_num(cls, reading):
49
        '''True when the reading is numeric and not empty'''
50
        if reading is None:
51
            return False
52
        if reading == 0:
53
            return False
54
        if isinstance(reading, int):
55
            return True
56
        if isinstance(reading, float):
57
            return True
58
        return False
59
60
    def has_reboot_rule(self):
61
        return any(therule.action == 'restart' and therule.parameter == 'reboot' for therule in self.brokenrules)
62
63
    def addbrokenrule(self, rule):
64
        if rule.action == 'restart':
65
            if not self.has_reboot_rule():
66
                self.brokenrules = [therule for therule in self.brokenrules if therule.action != 'restart']
67
                self.brokenrules.append(rule)
68
        else:
69
            self.brokenrules.append(rule)
70
71
    def isbroken(self):
72
        '''true when the rule is broken'''
73
        self.brokenrules = []
74
        if self.miner.miner_type != self.ruleparameters.minertype:
75
            return False
76
77
        self.check_hash()
78
        self.check_temp_controller()
79
        self.check_temp_boards()
80
        self.check_hardware_errors()
81
82
        return len(self.brokenrules) > 0
83
84
    def check_hardware_errors(self):
85
        if MinerStatisticsRule.hasreading_num(self.statistics.hardware_errors):
86
            #TODO:for now compare absolute values instead of time normalized
87
            if self.statistics.hardware_errors >= self.ruleparameters.hardware_errors_limit:
88
                self.addbrokenrule(BrokenRule(self.miner, 'alert', 'on {} high error rate {}'.format(self.miner.name, self.statistics.hardware_errors)))
89
90
    def check_hash(self):
91
        if MinerStatisticsRule.hasreading_num(self.statistics.currenthash):
92
            if self.statistics.currenthash < self.ruleparameters.hashlimit:
93
                self.brokenrules.append(BrokenRule(self.miner, 'alert', 'on {0} low hash {1} below {2}'.format(self.miner.name, self.statistics.currenthash, self.ruleparameters.hashlimit)))
94
                if self.statistics.elapsed > self.ruleparameters.restartaftersec:
95
                    self.addbrokenrule(BrokenRule(self.miner, 'restart', 'restart'))
96
                    self.addbrokenrule(BrokenRule(self.miner, 'alert', 'restarting {0} '.format(self.miner.name)))
97
98
    def check_temp_controller(self):
99
        if MinerStatisticsRule.hasreading_num(self.statistics.controllertemp):
100
            if self.statistics.controllertemp and self.statistics.controllertemp > self.ruleparameters.controllertemplimit:
101
                self.addbrokenrule(BrokenRule(self.miner, 'alert', 'on {0} controller temp {1} exceeded {2}'.format(self.miner.name, self.statistics.controllertemp, self.ruleparameters.controllertemplimit)))
102
103
    def check_temp_boards(self):
104
        if MinerStatisticsRule.hasreading_num(self.statistics.tempboardmax()):
105
            if self.statistics.tempboardmax() > self.ruleparameters.boardtemplimit:
106
                self.addbrokenrule(BrokenRule(self.miner, 'alert', 'on {0} board temp {1} exceeded {2}'.format(self.miner.name, self.statistics.tempboardmax(), self.ruleparameters.boardtemplimit)))
107
            if self.ruleparameters.maxtempreset and self.statistics.tempboardmax() > self.ruleparameters.maxtempreset:
108
                if self.statistics.elapsed > self.ruleparameters.restartaftersec:
109
                    self.addbrokenrule(BrokenRule(self.miner, 'restart', 'reboot'))
110