| from docker import DockerClient, APIClient |
| import time |
| import re |
| |
| |
| def docker_container_id(container_name): |
| """ |
| Uses the container name to return the container ID. |
| |
| :param container_name: The full name of the docker container. |
| :type container_name: ``str`` |
| :return: Returns the container ID or None if the container is not running or could not be found. |
| :rtype: ``dict`` |
| """ |
| c = APIClient() |
| detail = c.inspect_container(container_name) |
| if bool(detail["State"]["Running"]): |
| return detail['Id'] |
| return None |
| |
| |
| def docker_abs_cpu(container_id): |
| """ |
| Returns the used CPU time since container startup and the system time in nanoseconds and returns the number |
| of available CPU cores. |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns a dict with CPU_used in nanoseconds, the current system time in nanoseconds and the number of |
| CPU cores available. |
| :rtype: ``dict`` |
| """ |
| with open('/sys/fs/cgroup/cpuacct/docker/' + container_id + '/cpuacct.usage_percpu', 'r') as f: |
| line = f.readline() |
| sys_time = int(time.time() * 1000000000) |
| numbers = [int(x) for x in line.split()] |
| cpu_usage = 0 |
| for number in numbers: |
| cpu_usage += number |
| return {'CPU_used': cpu_usage, 'CPU_used_systime': sys_time, 'CPU_cores': len(numbers)} |
| |
| |
| def docker_mem_used(container_id): |
| """ |
| Bytes of memory used from the docker container. |
| |
| Note: If you have problems with this command you have to enable memory control group. |
| For this you have to add the following kernel parameters: `cgroup_enable=memory swapaccount=1`. |
| See: https://docs.docker.com/engine/admin/runmetrics/ |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns the memory utilization in bytes. |
| :rtype: ``str`` |
| """ |
| with open('/sys/fs/cgroup/memory/docker/' + container_id + '/memory.usage_in_bytes', 'r') as f: |
| return int(f.readline()) |
| |
| |
| def docker_max_mem(container_id): |
| """ |
| Bytes of memory the docker container could use. |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns the bytes of memory the docker container could use. |
| :rtype: ``str`` |
| """ |
| with open('/sys/fs/cgroup/memory/docker/' + container_id + '/memory.limit_in_bytes', 'r') as f: |
| mem_limit = int(f.readline()) |
| with open('/proc/meminfo', 'r') as f: |
| line = f.readline().split() |
| sys_value = int(line[1]) |
| unit = line[2] |
| if unit == 'kB': |
| sys_value *= 1024 |
| if unit == 'MB': |
| sys_value *= 1024 * 1024 |
| |
| if sys_value < mem_limit: |
| return sys_value |
| else: |
| return mem_limit |
| |
| |
| def docker_mem(container_id): |
| """ |
| Calculates the current, maximal and percentage usage of the specified docker container. |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns a dictionary with the total memory usage, the maximal available memory and the percentage |
| memory usage. |
| :rtype: ``dict`` |
| """ |
| out_dict = dict() |
| out_dict['MEM_used'] = docker_mem_used(container_id) |
| out_dict['MEM_limit'] = docker_max_mem(container_id) |
| out_dict['MEM_%'] = float(out_dict['MEM_used']) / float(out_dict['MEM_limit']) |
| return out_dict |
| |
| |
| def docker_abs_net_io(container_id): |
| """ |
| Network traffic of all network interfaces within the controller. |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns the absolute network I/O till container startup, in bytes. The return dict also contains the |
| system time. |
| :rtype: ``dict`` |
| """ |
| c = APIClient() |
| command = c.exec_create(container_id, 'ifconfig') |
| ifconfig = c.exec_start(command['Id']) |
| sys_time = int(time.time() * 1000000000) |
| |
| in_bytes = 0 |
| m = re.findall('RX bytes:(\d+)', str(ifconfig)) |
| if m: |
| for number in m: |
| in_bytes += int(number) |
| else: |
| in_bytes = None |
| |
| out_bytes = 0 |
| m = re.findall('TX bytes:(\d+)', str(ifconfig)) |
| if m: |
| for number in m: |
| out_bytes += int(number) |
| else: |
| out_bytes = None |
| |
| return {'NET_in': in_bytes, 'NET_out': out_bytes, 'NET_systime': sys_time} |
| |
| |
| def docker_block_rw(container_id): |
| """ |
| Determines the disk read and write access from the controller since startup. |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns a dictionary with the total disc I/O since container startup, in bytes. |
| :rtype: ``dict`` |
| """ |
| with open('/sys/fs/cgroup/blkio/docker/' + container_id + '/blkio.throttle.io_service_bytes', 'r') as f: |
| read = f.readline().split() |
| write = f.readline().split() |
| rw_dict = dict() |
| rw_dict['BLOCK_systime'] = int(time.time() * 1000000000) |
| if len(read) < 3: |
| rw_dict['BLOCK_read'] = 0 |
| else: |
| rw_dict['BLOCK_read'] = read[2] |
| if len(write) < 3: |
| rw_dict['BLOCK_write'] = 0 |
| else: |
| rw_dict['BLOCK_write'] = write[2] |
| return rw_dict |
| |
| |
| def docker_PIDS(container_id): |
| """ |
| Determines the number of processes within the docker container. |
| |
| :param container_id: The full ID of the docker container. |
| :type container_id: ``str`` |
| :return: Returns the number of PIDS within a dictionary. |
| :rtype: ``dict`` |
| """ |
| with open('/sys/fs/cgroup/cpuacct/docker/' + container_id + '/tasks', 'r') as f: |
| return {'PIDS': len(f.read().split('\n')) - 1} |
| |
| |
| def monitoring_over_time(container_id): |
| """ |
| Calculates the cpu workload and the network traffic per second. |
| |
| :param container_id: The full docker container ID |
| :type container_id: ``str`` |
| :return: A dictionary with disk read and write per second, network traffic per second (in and out), |
| the cpu workload and the number of cpu cores available. |
| :rtype: ``dict`` |
| """ |
| first_cpu_usage = docker_abs_cpu(container_id) |
| first = docker_abs_net_io(container_id) |
| first_disk_io = docker_block_rw(container_id) |
| time.sleep(1) |
| second_cpu_usage = docker_abs_cpu(container_id) |
| second = docker_abs_net_io(container_id) |
| second_disk_io = docker_block_rw(container_id) |
| |
| # Disk access |
| time_div = (int(second_disk_io['BLOCK_systime']) - int(first_disk_io['BLOCK_systime'])) |
| read_div = int(second_disk_io['BLOCK_read']) - int(first_disk_io['BLOCK_read']) |
| write_div = int(second_disk_io['BLOCK_write']) - int(first_disk_io['BLOCK_write']) |
| out_dict = {'BLOCK_read/s': int(read_div * 1000000000 / float(time_div) + 0.5), |
| 'BLOCK_write/s': int(write_div * 1000000000 / float(time_div) + 0.5)} |
| |
| # Network traffic |
| time_div = (int(second['NET_systime']) - int(first['NET_systime'])) |
| in_div = int(second['NET_in']) - int(first['NET_in']) |
| out_div = int(second['NET_out']) - int(first['NET_out']) |
| out_dict.update({'NET_in/s': int(in_div * 1000000000 / float(time_div) + 0.5), |
| 'NET_out/s': int(out_div * 1000000000 / float(time_div) + 0.5)}) |
| |
| # CPU utilization |
| time_div = (int(second_cpu_usage['CPU_used_systime']) - int(first_cpu_usage['CPU_used_systime'])) |
| usage_div = int(second_cpu_usage['CPU_used']) - int(first_cpu_usage['CPU_used']) |
| out_dict.update({'CPU_%': usage_div / float(time_div), 'CPU_cores': first_cpu_usage['CPU_cores']}) |
| return out_dict |