LinuxMonitor 1.4.9__tar.gz → 1.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0/LinuxMonitor.egg-info}/PKG-INFO +1 -1
- {linuxmonitor-1.4.9/LinuxMonitor.egg-info → linuxmonitor-1.5.0}/PKG-INFO +1 -1
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/linuxmonitor/__main__.py +1 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/linuxmonitor/linuxmonitor.py +79 -9
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/setup.py +1 -1
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/LICENSE.md +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/LinuxMonitor.egg-info/SOURCES.txt +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/LinuxMonitor.egg-info/dependency_links.txt +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/LinuxMonitor.egg-info/requires.txt +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/LinuxMonitor.egg-info/top_level.txt +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/README.md +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/linuxmonitor/__init__.py +0 -0
- {linuxmonitor-1.4.9 → linuxmonitor-1.5.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: LinuxMonitor
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Get information and warning status of Linux server like service, port, ping, ssl certificate, disk/folder/cpu/ram/swap usage, ip connection, ... (Python and shell library, Linux ONLY)
|
|
5
5
|
Home-page: https://github.com/QuentinCG/Linux-Monitor-Python-Library
|
|
6
6
|
Author: Quentin Comte-Gaz
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: LinuxMonitor
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Get information and warning status of Linux server like service, port, ping, ssl certificate, disk/folder/cpu/ram/swap usage, ip connection, ... (Python and shell library, Linux ONLY)
|
|
5
5
|
Home-page: https://github.com/QuentinCG/Linux-Monitor-Python-Library
|
|
6
6
|
Author: Quentin Comte-Gaz
|
|
@@ -71,6 +71,7 @@ def main() -> None:
|
|
|
71
71
|
out_msg += msg
|
|
72
72
|
|
|
73
73
|
out_msg += "\n"
|
|
74
|
+
out_msg += monitoring.check_load_average(display_only_if_critical=False) + "\n"
|
|
74
75
|
out_msg += monitoring.check_cpu_usage(display_only_if_critical=False) + "\n"
|
|
75
76
|
out_msg += monitoring.check_ram_usage(display_only_if_critical=False) + "\n"
|
|
76
77
|
out_msg += monitoring.check_swap_usage(display_only_if_critical=False) + "\n"
|
|
@@ -33,7 +33,7 @@ __email__ = "quentin@comte-gaz.com"
|
|
|
33
33
|
__license__ = "MIT License"
|
|
34
34
|
__copyright__ = "Copyright Quentin Comte-Gaz (2024)"
|
|
35
35
|
__python_version__ = "3.+"
|
|
36
|
-
__version__ = "1.
|
|
36
|
+
__version__ = "1.5.0 (2024/10/27)"
|
|
37
37
|
__status__ = "Usable for any Linux project"
|
|
38
38
|
|
|
39
39
|
import json
|
|
@@ -106,6 +106,14 @@ class LinuxMonitor:
|
|
|
106
106
|
if not isinstance(basic_config, dict):
|
|
107
107
|
raise ValueError("The basic configuration must be a dictionary")
|
|
108
108
|
|
|
109
|
+
if 'warning_load_average_percent' not in basic_config:
|
|
110
|
+
raise ValueError("The basic configuration must contain the 'warning_load_average_percent' key")
|
|
111
|
+
self.warning_load_average_percent: float = basic_config.get('warning_load_average_percent') # type: ignore
|
|
112
|
+
|
|
113
|
+
if 'critical_load_average_percent' not in basic_config:
|
|
114
|
+
raise ValueError("The basic configuration must contain the 'critical_load_average_percent' key")
|
|
115
|
+
self.critical_load_average_percent: float = basic_config.get('critical_load_average_percent') # type: ignore
|
|
116
|
+
|
|
109
117
|
if 'warning_cpu_percent' not in basic_config:
|
|
110
118
|
raise ValueError("The basic configuration must contain the 'warning_cpu_percent' key")
|
|
111
119
|
self.warning_cpu_percent: float = basic_config.get('warning_cpu_percent') # type: ignore
|
|
@@ -587,7 +595,7 @@ class LinuxMonitor:
|
|
|
587
595
|
cpu_cores: int = psutil.cpu_count(logical=False)
|
|
588
596
|
cpu_name: str = self._get_cpu_name()
|
|
589
597
|
|
|
590
|
-
if cpu_percent
|
|
598
|
+
if cpu_percent >= self.critical_cpu_percent:
|
|
591
599
|
out_msg = f"- 🚨 **Critical CPU usage**:\n- **{cpu_percent:.2f}%** used on {cpu_cores} core of {cpu_info:.2f}GHz ({cpu_name})\n⚠️ **Check what is using so much CPU power** ⚠️"
|
|
592
600
|
|
|
593
601
|
# If there is a critical CPU usage, we also display the top 10 processes consuming the most CPU
|
|
@@ -595,7 +603,7 @@ class LinuxMonitor:
|
|
|
595
603
|
|
|
596
604
|
logging.warning(msg=out_msg)
|
|
597
605
|
elif not display_only_if_critical:
|
|
598
|
-
if cpu_percent
|
|
606
|
+
if cpu_percent >= self.warning_cpu_percent:
|
|
599
607
|
icon = "⚠️"
|
|
600
608
|
else:
|
|
601
609
|
icon = "✅"
|
|
@@ -626,7 +634,7 @@ class LinuxMonitor:
|
|
|
626
634
|
used_ram: float = ram.used / (2**30)
|
|
627
635
|
free_ram: float = total_ram - used_ram
|
|
628
636
|
percent_ram: float = ram.percent
|
|
629
|
-
if percent_ram
|
|
637
|
+
if percent_ram >= self.critical_ram_percent:
|
|
630
638
|
out_msg = f"- 🚨 **Critical RAM usage**:\n- Total: {total_ram:.2f}GB\n- Used: {used_ram:.2f}GB ({percent_ram:.2f}%)\n- Free: {free_ram:.2f}GB\n⚠️ **Check what is using so much RAM** ⚠️"
|
|
631
639
|
|
|
632
640
|
# If there is a critical RAM usage, we also display the top 10 processes consuming the most RAM
|
|
@@ -634,7 +642,7 @@ class LinuxMonitor:
|
|
|
634
642
|
|
|
635
643
|
logging.warning(msg=out_msg)
|
|
636
644
|
elif not display_only_if_critical:
|
|
637
|
-
if percent_ram
|
|
645
|
+
if percent_ram >= self.warning_ram_percent:
|
|
638
646
|
icon = "⚠️"
|
|
639
647
|
else:
|
|
640
648
|
icon = "✅"
|
|
@@ -649,6 +657,45 @@ class LinuxMonitor:
|
|
|
649
657
|
|
|
650
658
|
return out_msg
|
|
651
659
|
|
|
660
|
+
def check_load_average(self, display_only_if_critical: bool=False) -> str:
|
|
661
|
+
"""
|
|
662
|
+
Check the load average.
|
|
663
|
+
|
|
664
|
+
:param display_only_if_critical: If True, the string result will only be returned if there is an error during execution.
|
|
665
|
+
|
|
666
|
+
:return: A string containing the result message.
|
|
667
|
+
"""
|
|
668
|
+
out_msg: str = ""
|
|
669
|
+
try:
|
|
670
|
+
# Getting load average
|
|
671
|
+
load_avg = psutil.getloadavg()
|
|
672
|
+
|
|
673
|
+
# Getting an average of all 3 values
|
|
674
|
+
avg_load_avg: float = sum(load_avg) / len(load_avg)
|
|
675
|
+
|
|
676
|
+
if avg_load_avg >= self.critical_load_average_percent:
|
|
677
|
+
out_msg = f"- 🚨 **High load average**: **{avg_load_avg:.2f}%**\n⚠️ **Check what is causing the high load average** ⚠️"
|
|
678
|
+
|
|
679
|
+
# If there is a critical load average, we also display the top 10 processes consuming the most CPU
|
|
680
|
+
out_msg += "\n" + self.get_ordered_processes(get_non_consuming_processes=False, order_by_ram=False, max_processes=10)
|
|
681
|
+
|
|
682
|
+
logging.warning(msg=out_msg)
|
|
683
|
+
elif not display_only_if_critical:
|
|
684
|
+
if avg_load_avg >= self.warning_load_average_percent:
|
|
685
|
+
icon = "⚠️"
|
|
686
|
+
else:
|
|
687
|
+
icon = "✅"
|
|
688
|
+
out_msg = f"- {icon} **{avg_load_avg:.2f}%**"
|
|
689
|
+
logging.info(msg=out_msg)
|
|
690
|
+
except Exception as e:
|
|
691
|
+
out_msg = f"- ⚠️ **Error getting load average**:\n```sh\n{e}\n```"
|
|
692
|
+
logging.exception(msg=out_msg)
|
|
693
|
+
|
|
694
|
+
if out_msg != "":
|
|
695
|
+
out_msg = f"# 📈 Load Average 📈\n{out_msg}"
|
|
696
|
+
|
|
697
|
+
return out_msg
|
|
698
|
+
|
|
652
699
|
def check_swap_usage(self, display_only_if_critical: bool=False) -> str:
|
|
653
700
|
"""
|
|
654
701
|
Check the SWAP usage.
|
|
@@ -665,11 +712,11 @@ class LinuxMonitor:
|
|
|
665
712
|
used_swap: float = swap.used / (2**30)
|
|
666
713
|
free_swap: float = swap.free / (2**30)
|
|
667
714
|
percent_swap: float = swap.percent
|
|
668
|
-
if percent_swap
|
|
715
|
+
if percent_swap >= self.critical_swap_percent:
|
|
669
716
|
out_msg = f"- 🚨 **Critical SWAP usage**\n- Total: {total_swap:.2f}GB\n- Used: {used_swap:.2f}GB ({percent_swap:.2f}%)\n- Free: {free_swap:.2f}GB\n⚠️ **Check what is using so much SWAP** ⚠️"
|
|
670
717
|
logging.warning(msg=out_msg)
|
|
671
718
|
elif not display_only_if_critical:
|
|
672
|
-
if percent_swap
|
|
719
|
+
if percent_swap >= self.warning_swap_percent:
|
|
673
720
|
icon = "⚠️"
|
|
674
721
|
else:
|
|
675
722
|
icon = "✅"
|
|
@@ -715,11 +762,11 @@ class LinuxMonitor:
|
|
|
715
762
|
max_temp = max(temp.current for temp in cpu_temps) # type: ignore
|
|
716
763
|
|
|
717
764
|
# Vérifier la température par rapport au seuil critique
|
|
718
|
-
if max_temp
|
|
765
|
+
if max_temp >= self.critical_temperature_celsius:
|
|
719
766
|
out_msg = f"- 🚨 **Critical CPU temperature**:\n- {max_temp:.2f}°C\n- Critical threshold: {self.critical_temperature_celsius}°C\n⚠️ **Check the CPU cooling system** ⚠️"
|
|
720
767
|
logging.warning(msg=out_msg)
|
|
721
768
|
elif not display_only_if_critical:
|
|
722
|
-
if max_temp
|
|
769
|
+
if max_temp >= self.warning_temperature_celsius:
|
|
723
770
|
icon = "⚠️"
|
|
724
771
|
else:
|
|
725
772
|
icon = "✅"
|
|
@@ -2048,6 +2095,7 @@ class LinuxMonitor:
|
|
|
2048
2095
|
|
|
2049
2096
|
datetime_last_disk_usage_error_displayed: Optional[datetime] = None
|
|
2050
2097
|
datetime_last_folder_usage_error_displayed: Optional[datetime] = None
|
|
2098
|
+
datetime_last_load_average_error_displayed: Optional[datetime] = None
|
|
2051
2099
|
datetime_last_cpu_usage_error_displayed: Optional[datetime] = None
|
|
2052
2100
|
datetime_last_ram_usage_error_displayed: Optional[datetime] = None
|
|
2053
2101
|
datetime_last_swap_usage_error_displayed: Optional[datetime] = None
|
|
@@ -2071,6 +2119,28 @@ class LinuxMonitor:
|
|
|
2071
2119
|
logging.info(msg="-----------------------------------------------")
|
|
2072
2120
|
logging.info(msg="Checking services status and all disk usage, CPU, RAM, Swap, CPU temperature and ping of websites periodically...")
|
|
2073
2121
|
try:
|
|
2122
|
+
# Load average
|
|
2123
|
+
if is_private:
|
|
2124
|
+
msg = self.check_load_average(display_only_if_critical=True)
|
|
2125
|
+
if msg != "":
|
|
2126
|
+
logging.warning(msg=msg)
|
|
2127
|
+
if datetime_last_load_average_error_displayed is None or ((datetime.now() - datetime_last_load_average_error_displayed).total_seconds() > self.max_duration_seconds_showing_same_error_again_in_scheduled_tasks):
|
|
2128
|
+
if out_msg != "":
|
|
2129
|
+
out_msg += "\n"
|
|
2130
|
+
out_msg += msg
|
|
2131
|
+
datetime_last_load_average_error_displayed = datetime.now()
|
|
2132
|
+
else:
|
|
2133
|
+
logging.warning(msg="Load average critical but already notified less than 12 hours ago, not notifying...")
|
|
2134
|
+
elif datetime_last_load_average_error_displayed is not None:
|
|
2135
|
+
msg = "✅ **Load average returned to normal state**"
|
|
2136
|
+
logging.info(msg=msg)
|
|
2137
|
+
if out_msg != "":
|
|
2138
|
+
out_msg += "\n"
|
|
2139
|
+
out_msg += msg
|
|
2140
|
+
datetime_last_load_average_error_displayed = None
|
|
2141
|
+
else:
|
|
2142
|
+
logging.info(msg="- ✅ Load average is OK.")
|
|
2143
|
+
|
|
2074
2144
|
# CPU
|
|
2075
2145
|
if is_private:
|
|
2076
2146
|
msg = self.check_cpu_usage(display_only_if_critical=True)
|
|
@@ -6,7 +6,7 @@ with io.open(file='README.md', mode='r', encoding='utf-8') as readme_file:
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="LinuxMonitor",
|
|
9
|
-
version="1.
|
|
9
|
+
version="1.5.0",
|
|
10
10
|
description="Get information and warning status of Linux server like service, port, ping, ssl certificate, disk/folder/cpu/ram/swap usage, ip connection, ... (Python and shell library, Linux ONLY)",
|
|
11
11
|
long_description=readme,
|
|
12
12
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|