Project

General

Profile

RE: Increased BER, Uncorrected Blocks and Continuity Erro... ยป check_tvheadend.py

Michael Wieland, 2020-04-14 16:03

 
1
#! /usr/bin/env python3
2
import os
3
import re
4

    
5
import requests
6
from requests.auth import HTTPDigestAuth
7

    
8

    
9
def scaled_value(value, scale, db_unit):
10
    max_value = 65535
11

    
12
    if scale == 1:  # Percentage
13
        calculated_value = value / max_value * 100
14
        return calculated_value, "{}%".format(round(calculated_value))
15
    elif scale == 2:  # dB
16
        calculated_value = value * 0.001
17
        return calculated_value, "{} {}".format(round(calculated_value, 1), db_unit)
18

    
19

    
20
CHECK_MK_STATE_OK = 0
21
CHECK_MK_STATE_WARNING = 1
22
CHECK_MK_STATE_CRITICAL = 2
23
CHECK_MK_STATE_UNKNOWN = 3
24

    
25
username = os.getenv("TVHEADEND_API_USERNAME")
26
password = os.getenv("TVHEADEND_API_PASSWORD")
27
timeout = os.getenv("TVHEADEND_API_TIMEOUT", 5)
28

    
29
check_name = os.getenv("TVHEADEND_CHECK_NAME", "Tvheadend_Input_{tuner}")
30

    
31
continuity_errors_critical = int(os.getenv("TVHEADEND_CHECK_CONTINUITY_ERRORS_CRITICAL", 100))
32
continuity_errors_warning = int(os.getenv("TVHEADEND_CHECK_CONTINUITY_ERRORS_WARNING", 50))
33

    
34
snr_signal_strength_percentage_critical = int(os.getenv("TVHEADEND_CHECK_SNR_SIGNAL_STRENGTH_PERCENTAGE_CRITICAL", 33))
35
snr_signal_strength_percentage_warning = int(os.getenv("TVHEADEND_CHECK_SNR_SIGNAL_STRENGTH_PERCENTAGE_WARNING", 66))
36

    
37
inputs_response = requests.get("http://localhost:9981/api/status/inputs", auth=HTTPDigestAuth(username, password), timeout=timeout)
38

    
39
inputs_response.raise_for_status()
40

    
41
inputs = inputs_response.json()["entries"]
42

    
43
for input_object in inputs:
44
    tuner_name = re.sub(r"\W+", "_", input_object["input"])
45

    
46
    snr = scaled_value(input_object["snr"], input_object["snr_scale"], "dB")
47
    signal_strength = scaled_value(input_object["signal"], input_object["signal_scale"], "dBm")
48
    bandwidth = input_object["bps"]
49
    continuity_errors = input_object["cc"]
50
    ec_bit = input_object["ec_bit"]
51
    tc_bit = input_object["tc_bit"]
52
    unc = input_object["unc"]
53
    transport_errors = input_object["te"]
54

    
55
    state = CHECK_MK_STATE_OK
56
    performance_data = {}
57
    details = []
58

    
59
    if tc_bit == 0:
60
        ber = input_object["ber"]
61
    else:
62
        ber = ec_bit / tc_bit
63

    
64
    if ber != 0:
65
        state = max(state, CHECK_MK_STATE_CRITICAL)
66
        details.append("BER = {} (!!)".format(ber))
67

    
68
    performance_data["ber"] = (ber, 1, 1)
69

    
70
    if unc != 0:
71
        # TODO: Uncorrected Blocks will always increase while scanning EPG... every day
72
        # state = max(state, CHECK_MK_STATE_CRITICAL)
73
        state = max(state, CHECK_MK_STATE_WARNING)
74
        details.append("Uncorrected Blocks = {} (!!)".format(unc))
75

    
76
    performance_data["unc"] = (unc, 1, 1)
77

    
78
    if transport_errors != 0:
79
        state = max(state, CHECK_MK_STATE_CRITICAL)
80
        details.append("Transport Errors = {} (!!)".format(transport_errors))
81

    
82
    performance_data["transport_errors"] = (transport_errors, 1, 1)
83

    
84
    performance_data["bandwidth"] = bandwidth
85

    
86
    if bandwidth:
87
        details.append("Bandwidth = {} kb/s".format(bandwidth / 1024))
88

    
89
    if continuity_errors > continuity_errors_critical:
90
        # TODO: Continuity Errors will always increase on switching mux and while scanning EPG... every day
91
        # state = max(state, CHECK_MK_STATE_CRITICAL)
92
        state = max(state, CHECK_MK_STATE_WARNING)
93
        details.append("Continuity Errors = {} (!!)".format(continuity_errors))
94
    elif continuity_errors > continuity_errors_warning:
95
        state = max(state, CHECK_MK_STATE_WARNING)
96
        details.append("Continuity Errors = {} (!)".format(continuity_errors))
97

    
98
    performance_data["continuity_errors"] = (continuity_errors, continuity_errors_warning, continuity_errors_critical)
99

    
100
    if snr is None:
101
        snr_value = 0
102
        snr_string = "N/A"
103
        performance_data["snr"] = 0
104
    else:
105
        snr_value, snr_string = snr
106

    
107
        # State calculation currently only possible if SNR is in percent (scale = 1)
108
        if input_object["snr_scale"] == 1:
109
            performance_data["snr"] = (snr_value, snr_signal_strength_percentage_warning, snr_signal_strength_percentage_critical)
110
            # TODO: SNR is currently only at ~24% which is bad but doesn't seem to have any impact right now
111
            # if snr_value <= snr_signal_strength_percentage_critical:
112
            #     state = max(state, CHECK_MK_STATE_CRITICAL)
113
            #     snr_string = "{} (!!)".format(snr_string)
114
            # elif snr_value <= snr_signal_strength_percentage_warning:
115
            #     state = max(state, CHECK_MK_STATE_WARNING)
116
            #     snr_string = "{} (!)".format(snr_string)
117
        else:
118
            performance_data["snr"] = snr_value
119

    
120
        details.append("SNR = {}".format(snr_string))
121

    
122
    if signal_strength is None:
123
        signal_strength_value = 0
124
        signal_strength_string = "N/A"
125
        performance_data["signal_strength"] = 0
126
    else:
127
        signal_strength_value, signal_strength_string = signal_strength
128

    
129
        # State calculation currently only possible if signal strength is in percent (scale = 1)
130
        if input_object["signal_scale"] == 1:
131
            performance_data["signal_strength"] = (signal_strength_value, snr_signal_strength_percentage_warning, snr_signal_strength_percentage_critical)
132
            if signal_strength_value <= snr_signal_strength_percentage_critical:
133
                state = max(state, CHECK_MK_STATE_CRITICAL)
134
                signal_strength_string = "{} (!!)".format(signal_strength_string)
135
            elif signal_strength_value <= snr_signal_strength_percentage_warning:
136
                state = max(state, CHECK_MK_STATE_WARNING)
137
                signal_strength_string = "{} (!)".format(signal_strength_string)
138
        else:
139
            performance_data["signal_strength"] = signal_strength_value
140

    
141
        details.append("Signal Strength = {}".format(signal_strength_string))
142

    
143
    if "stream" in input_object:
144
        active_stream = input_object["stream"]
145
    else:
146
        active_stream = "Stream inactive"
147

    
148
    performance_data_string = []
149

    
150
    for key, value in performance_data.items():
151
        if type(value) == tuple:
152
            performance_data_string.append("{}={}".format(key, ";".join(map(str, value))))
153
        else:
154
            performance_data_string.append("{}={}".format(key, value))
155

    
156
    if len(details):
157
        details_string = "({})".format(", ".join(details))
158
    else:
159
        details_string = ""
160

    
161
    print("{state} {check_name} {performance_data} {active_stream} {details}".format(state=state, check_name=check_name.format(tuner=tuner_name), performance_data="|".join(performance_data_string), active_stream=active_stream, details=details_string))
    (1-1/1)