diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..ef820d4039a54bf590e5c675c97a718b0681dc6e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter"] + path = docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter + url = https://git.astron.nl/lofar2.0/ska-tango-grafana-exporter.git + branch = station-control diff --git a/docker-compose/tango-prometheus-exporter/Dockerfile b/docker-compose/tango-prometheus-exporter/Dockerfile index 780c566de34915847ab9fc621278478265c1ce3b..4f548bbc1a7ff9eebb906fe912cd7a74992bd558 100644 --- a/docker-compose/tango-prometheus-exporter/Dockerfile +++ b/docker-compose/tango-prometheus-exporter/Dockerfile @@ -6,10 +6,10 @@ RUN apt-get update && apt-get install curl -y USER tango -ADD code /code +ADD ska-tango-grafana-exporter/exporter/code /code RUN pip install -r /code/pip-requirements.txt WORKDIR /code ENV PYTHONPATH '/code/' -CMD ["python" , "/code/collector.py"] \ No newline at end of file +CMD ["python" , "/code/collector.py"] diff --git a/docker-compose/tango-prometheus-exporter/code/collector.py b/docker-compose/tango-prometheus-exporter/code/collector.py deleted file mode 100644 index 9e579788afc69f84194baf21077154a9b4fa18bc..0000000000000000000000000000000000000000 --- a/docker-compose/tango-prometheus-exporter/code/collector.py +++ /dev/null @@ -1,258 +0,0 @@ -import time -import argparse -from prometheus_client.core import GaugeMetricFamily, REGISTRY, CounterMetricFamily -from prometheus_client import start_http_server -from tango import Database, DeviceProxy, CmdArgType as ArgType, AttrDataFormat - -class CustomCollector(object): - def __init__(self): - self.replicas=1 - self.replica_id=0 - try: - self.db = Database() - except: - pass - - def add_to_metric(self, dev, attr_info, metric): - if(attr_info.data_type == ArgType.DevShort or attr_info.data_type == ArgType.DevLong or - attr_info.data_type == ArgType.DevUShort or attr_info.data_type == ArgType.DevULong or - attr_info.data_type == ArgType.DevLong64 or attr_info.data_type == ArgType.DevULong64 or - attr_info.data_type == ArgType.DevInt or attr_info.data_type == ArgType.DevFloat or - attr_info.data_type == ArgType.DevDouble): - attr_value = dev.read_attribute(attr_info.name) - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '', 'float', str(attr_value.dim_x), str(attr_value.dim_y), '0', '0'], float(attr_value.value)) - return 1 - elif(attr_info.data_type == ArgType.DevBoolean): - attr_value = dev.read_attribute(attr_info.name) - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '','bool', str(attr_value.dim_x), str(attr_value.dim_y), '0', '0'], int(attr_value.value)) - return 1 - elif(attr_info.data_type == ArgType.DevString): - attr_value = dev.read_attribute(attr_info.name) - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value),'string', str(attr_value.dim_x), str(attr_value.dim_y), '0', '0'], 1) - return 1 - elif(attr_info.data_type == ArgType.DevEnum): - attr_config = dev.get_attribute_config(attr_info.name) - attr_value = dev.read_attribute(attr_info.name) - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_config.enum_labels[attr_value.value]),'enum', str(attr_value.dim_x), str(attr_value.dim_y), '0', '0'], int(attr_value.value)) - return 1 - elif(attr_info.data_type == ArgType.DevState): - attr_value = dev.read_attribute(attr_info.name) - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '' ,'state', str(attr_value.dim_x), str(attr_value.dim_y), '0', '0'], int(attr_value.value)) - return 1 - else: - return 0 - - def add_to_metric_spectrum(self, dev, attr_info, metric): - attr_value = dev.read_attribute(attr_info.name) - for x in range(int(attr_value.dim_x)): - if(attr_info.data_type == ArgType.DevShort or attr_info.data_type == ArgType.DevLong or - attr_info.data_type == ArgType.DevUShort or attr_info.data_type == ArgType.DevULong or - attr_info.data_type == ArgType.DevLong64 or attr_info.data_type == ArgType.DevULong64 or - attr_info.data_type == ArgType.DevInt or attr_info.data_type == ArgType.DevFloat or - attr_info.data_type == ArgType.DevDouble): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '', 'float', str(attr_value.dim_x), str(attr_value.dim_y), f"{x:02}", '0'], float(attr_value.value[x])) - elif(attr_info.data_type == ArgType.DevBoolean): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '','bool', str(attr_value.dim_x), str(attr_value.dim_y), f"{x:02}", '0'], int(attr_value.value[x])) - elif(attr_info.data_type == ArgType.DevString): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value[x]),'string', str(attr_value.dim_x), str(attr_value.dim_y), f"{x:02}", '0'], 1) - elif(attr_info.data_type == ArgType.DevEnum): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value[x]),'enum', str(attr_value.dim_x), str(attr_value.dim_y), f"{x:02}", '0'], int(attr_value.value[x])) - elif(attr_info.data_type == ArgType.DevState): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value[x]),'state', str(attr_value.dim_x), str(attr_value.dim_y), f"{x:02}", '0'], int(attr_value.value[x])) - else: - pass - return 1 - - def add_to_metric_image(self, dev, attr_info, metric): - attr_value = dev.read_attribute(attr_info.name) - if attr_value.dim_x * attr_value.dim_y > 256: - # too big, don't monitor - return 0 - - for y in range(int(attr_value.dim_y)): - for x in range(int(attr_value.dim_x)): - """ NOTE: We switch x and y in the annotation, to allow queries to combine 1D and 2D arrays in their first dimension using the same label (x). We effectively expose - the array as [x][y] instead of [y][x]. """ - - if(attr_info.data_type == ArgType.DevShort or attr_info.data_type == ArgType.DevLong or - attr_info.data_type == ArgType.DevUShort or attr_info.data_type == ArgType.DevULong or - attr_info.data_type == ArgType.DevLong64 or attr_info.data_type == ArgType.DevULong64 or - attr_info.data_type == ArgType.DevInt or attr_info.data_type == ArgType.DevFloat or - attr_info.data_type == ArgType.DevDouble): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '', 'float', str(attr_value.dim_x), str(attr_value.dim_y), f"{y:02}", f"{x:02}"], float(attr_value.value[y][x])) - elif(attr_info.data_type == ArgType.DevBoolean): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, '','bool', str(attr_value.dim_x), str(attr_value.dim_y), f"{y:02}", f"{x:02}"], int(attr_value.value[y][x])) - elif(attr_info.data_type == ArgType.DevString): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value[y][x]),'string', str(attr_value.dim_x), str(attr_value.dim_y), f"{y:02}", f"{x:02}"], 1) - elif(attr_info.data_type == ArgType.DevEnum): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value[y][x]),'enum', str(attr_value.dim_x), str(attr_value.dim_y), f"{y:02}", f"{x:02}"], int(attr_value.value[y][x])) - elif(attr_info.data_type == ArgType.DevState): - metric.add_metric([dev.dev_name(), attr_info.name, attr_info.label, str(attr_value.value[y][x]),'state', str(attr_value.dim_x), str(attr_value.dim_y), f"{y:02}", f"{x:02}"], int(attr_value.value[y][x])) - else: - pass - return 1 - - def collect(self): - attribute_metrics = GaugeMetricFamily("device_attribute", 'Device attribute value', labels=['device', 'name', 'label', 'str_value', 'type', 'dim_x', 'dim_y', 'x', 'y']) - total_count = 0 - read_count = 0 - error_count = 0 - error_attr_count = 0 - scalar_count = 0 - spectrum_count = 0 - image_count = 0 - not_managed_attribute_count = 0 - try: - server_list = self.db.get_server_list() - except: - try: - self.db = Database() - except: - sys_errors = GaugeMetricFamily("system_errors_count", 'Total number of system errors acccessing the TANGO system') - sys_errors.add_metric([], 1) - return sys_errors - - count = len(server_list) / self.replicas # 15,8 - i = int(count * self.replica_id) # 0 15,8 31,6 47,4 63,2 -> 0 15 31 47 63 - count = int(count) + i # 15 31 47 63 - if(self.replicas-1 == self.replica_id): - count = len(server_list) # 79 - #print("i=" + str(i) +",count="+str(count)) - while i < count: - # https://pytango.readthedocs.io/en/stable/database.html#tango.Database.get_device_class_list - class_list = self.db.get_device_class_list(server_list[i]) - j = 0 - while j < len(class_list): - try: - if "dserver" in class_list[j]: - j += 2 - continue - dev = DeviceProxy(class_list[j]) - #print(class_list[j]) - dev.set_timeout_millis(10) - attr_list = dev.attribute_list_query() - for attr_info in attr_list: - try: - #print(" " +attr_info.name) - - total_count += 1 - # 1: tango._tango.CmdArgType.DevBoolean, - # 2: tango._tango.CmdArgType.DevShort, - # 3: tango._tango.CmdArgType.DevLong, - # 4: tango._tango.CmdArgType.DevFloat, - # 5: tango._tango.CmdArgType.DevDouble, - # 6: tango._tango.CmdArgType.DevUShort, - # 7: tango._tango.CmdArgType.DevULong, - # 8: tango._tango.CmdArgType.DevString, - # 19: tango._tango.CmdArgType.DevState, - # 23: tango._tango.CmdArgType.DevLong64, - # 24: tango._tango.CmdArgType.DevULong64, - # 27: tango._tango.CmdArgType.DevInt, - # 29: tango._tango.CmdArgType.DevEnum, - if(attr_info.data_format == AttrDataFormat.SCALAR): - res = self.add_to_metric(dev, attr_info, attribute_metrics) - if(res > 0): - read_count = read_count + res - scalar_count += 1 - else: - # {0: tango._tango.CmdArgType.DevVoid, - # 28: tango._tango.CmdArgType.DevEncoded, - # 30: tango._tango.CmdArgType.DevPipeBlob, - # 22: tango._tango.CmdArgType.DevUChar, - # 20: tango._tango.CmdArgType.ConstDevString, - not_managed_attribute_count += 1 - #print("*******NOT MANAGED: "+attr_info.name) - # 9: tango._tango.CmdArgType.DevVarCharArray, - # 10: tango._tango.CmdArgType.DevVarShortArray, - # 11: tango._tango.CmdArgType.DevVarLongArray, - # 12: tango._tango.CmdArgType.DevVarFloatArray, - # 13: tango._tango.CmdArgType.DevVarDoubleArray, - # 14: tango._tango.CmdArgType.DevVarUShortArray, - # 15: tango._tango.CmdArgType.DevVarULongArray, - # 16: tango._tango.CmdArgType.DevVarStringArray, - # 17: tango._tango.CmdArgType.DevVarLongStringArray, - # 18: tango._tango.CmdArgType.DevVarDoubleStringArray, - # 21: tango._tango.CmdArgType.DevVarBooleanArray, - # 25: tango._tango.CmdArgType.DevVarLong64Array, - # 26: tango._tango.CmdArgType.DevVarULong64Array, - # 31: tango._tango.CmdArgType.DevVarStateArray} - elif(attr_info.data_format == AttrDataFormat.SPECTRUM): - res = self.add_to_metric_spectrum(dev, attr_info, attribute_metrics) - if(res <= 0): - not_managed_attribute_count += 1 - print("*******NOT MANAGED: "+attr_info.name) - else: - spectrum_count += 1 - read_count += 1 - - elif(attr_info.data_format == AttrDataFormat.IMAGE): - res = self.add_to_metric_image(dev, attr_info, attribute_metrics) - if(res <= 0): - not_managed_attribute_count += 1 - print("*******NOT MANAGED: "+attr_info.name) - else: - image_count += 1 - read_count += 1 - else: - # AttrDataFormat.FMT_UNKNOWN - not_managed_attribute_count += 1 - print("*******NOT MANAGED: "+attr_info.name) - except Exception as e1: - #print ("Could not connect to the '"+ class_list[j] + "." + attr_info.name+"' Attribute.\r\n") - #print(e1) - error_attr_count += 1 - except Exception as e2: - #print ("Could not connect to the '"+class_list[j]+"' DeviceProxy.\r\n") - #print(e2) - error_count += 1 - j += 2 - i += 1 - - yield attribute_metrics - - errors = GaugeMetricFamily("error_count", 'Total number of errors reading the devices') - errors.add_metric([], error_count) - yield errors - - errors_attr = GaugeMetricFamily("error_attr_count", 'Total number of errors reading the device attributes') - errors_attr.add_metric([], error_attr_count) - yield errors_attr - - attribute_count = GaugeMetricFamily("attribute_count", 'Total number of attributes') - attribute_count.add_metric([], total_count) - yield attribute_count - - attribute_read_count = GaugeMetricFamily("attribute_read_count", 'Total number of read attributes') - attribute_read_count.add_metric([], read_count) - yield attribute_read_count - - spectrum_attribute_count = GaugeMetricFamily("spectrum_attribute_count", 'Total number of spectrum attributes') - spectrum_attribute_count.add_metric([], spectrum_count) - yield spectrum_attribute_count - - image_attribute_count = GaugeMetricFamily("image_attribute_count", 'Total number of image attributes') - image_attribute_count.add_metric([], image_count) - yield image_attribute_count - - not_managed = GaugeMetricFamily("not_managed_attribute_count", 'Total number of not managed attributes') - not_managed.add_metric([], not_managed_attribute_count) - yield not_managed - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('-i', '--replica_id', help='Replica ID identification') - parser.add_argument('-r', '--replicas', help='Replica count') - - args = parser.parse_args() - - collector = CustomCollector() - - if(args.replica_id and args.replicas): - collector.replica_id=int(args.replica_id) - collector.replicas=int(args.replicas) - - - start_http_server(8000) - REGISTRY.register(collector) - while True: - time.sleep(1) diff --git a/docker-compose/tango-prometheus-exporter/code/pip-requirements.txt b/docker-compose/tango-prometheus-exporter/code/pip-requirements.txt deleted file mode 100644 index a73ea1c9ee09237c091d001f2409c0b7031a821a..0000000000000000000000000000000000000000 --- a/docker-compose/tango-prometheus-exporter/code/pip-requirements.txt +++ /dev/null @@ -1 +0,0 @@ -prometheus_client \ No newline at end of file diff --git a/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter b/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter new file mode 160000 index 0000000000000000000000000000000000000000..c7cadb8f48dc8b36860f23ce421c72e90216a548 --- /dev/null +++ b/docker-compose/tango-prometheus-exporter/ska-tango-grafana-exporter @@ -0,0 +1 @@ +Subproject commit c7cadb8f48dc8b36860f23ce421c72e90216a548