2 # -*- encoding: utf-8; py-indent-offset: 4 -*-
3 # +------------------------------------------------------------------+
4 # | ____ _ _ __ __ _ __ |
5 # | / ___| |__ ___ ___| | __ | \/ | |/ / |
6 # | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
7 # | | |___| | | | __/ (__| < | | | | . \ |
8 # | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
10 # | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
11 # +------------------------------------------------------------------+
13 # This file is part of Check_MK.
14 # The official homepage is at http://mathias-kettner.de/check_mk.
16 # check_mk is free software; you can redistribute it and/or modify it
17 # under the terms of the GNU General Public License as published by
18 # the Free Software Foundation in version 2. check_mk is distributed
19 # in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
20 # out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
21 # PARTICULAR PURPOSE. See the GNU General Public License for more de-
22 # tails. You should have received a copy of the GNU General Public
23 # License along with GNU Make; see the file COPYING. If not, write
24 # to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 # Boston, MA 02110-1301 USA.
27 memused_default_levels
= (150.0, 200.0)
29 factory_settings
["memory_default_levels"] = {
30 "levels": memused_default_levels
,
34 # Parse /proc/meminfo into the canonical form: into bytes, not kB
35 # This function is also used by the ps check
36 def parse_proc_meminfo_bytes(info
):
40 if len(line
) > 2 and line
[2] == 'kB':
42 meminfo
[line
[0][:-1]] = value
46 def check_memory(params
, meminfo
):
47 swapused_kb
= meminfo
['SwapTotal'] - meminfo
['SwapFree']
48 swapused
= swapused_kb
* 1024.0
49 memused_kb
= meminfo
['MemTotal'] - meminfo
['MemFree']
50 memused
= memused_kb
* 1024.0
52 # Buffers and Cached are optional. On Linux both mean basically the same.
53 caches_kb
= meminfo
.get('Buffers', 0) + meminfo
.get('Cached', 0)
54 caches
= caches_kb
* 1024.0
56 # Size of Pagetable on Linux can be relevant e.g. on ORACLE
57 # servers with much memory, that do not use HugeTables. We account
59 pagetables_kb
= meminfo
.get('PageTables', 0)
60 pagetables_mb
= pagetables_kb
/ 1024.0
62 totalused_kb
= (swapused_kb
+ memused_kb
- caches_kb
+ pagetables_kb
)
63 totalused_mb
= totalused_kb
/ 1024.0
64 totalused
= totalused_kb
* 1024.0
65 totalmem_kb
= meminfo
['MemTotal']
66 totalmem_mb
= totalmem_kb
/ 1024.0
67 totalmem
= totalmem_kb
* 1024.0
68 totalused_perc
= 100 * (float(totalused_kb
) / float(totalmem_kb
))
69 totalvirt_mb
= (meminfo
['SwapTotal'] + meminfo
['MemTotal']) / 1024.0
71 if isinstance(params
, tuple):
72 params
= {"levels": params
}
73 warn
, crit
= params
["levels"]
77 details
.append("%s SWAP" % render
.fmt_bytes(swapused
))
80 details
.append("%s Pagetables" % render
.fmt_bytes(pagetables_kb
* 1024.0))
83 details
.insert(0, "%s RAM" % render
.fmt_bytes(memused
- caches
))
84 details_txt
= " + ".join(details
) + ", "
88 if meminfo
["SwapTotal"]:
89 swap_txt
= (" + %s SWAP" % render
.fmt_bytes(meminfo
["SwapTotal"]))
93 infotext
= "%s used (%sthis is %.1f%% of %s RAM%s)" % \
94 (render
.fmt_bytes(totalused
), details_txt
,
95 totalused_perc
, render
.fmt_bytes(totalmem
), swap_txt
)
97 # Take into account averaging
98 average_min
= params
.get("average")
100 totalused_mb_avg
= get_average(
101 "mem.used.total", time
.time(), totalused_mb
, average_min
, initialize_zero
=False)
102 totalused_perc_avg
= totalused_mb_avg
/ totalmem_mb
* 100
103 infotext
+= ", %d min average %.1f%%" % (average_min
, totalused_perc_avg
)
104 comp_mb
= totalused_mb_avg
106 comp_mb
= totalused_mb
108 # levels may be given either in int -> MB or in float -> percentages. So convert
109 # effective levels to MB now
110 if isinstance(warn
, float):
111 warn_mb
= int(warn
/ 100.0 * totalmem_mb
)
112 crit_mb
= int(crit
/ 100.0 * totalmem_mb
)
113 leveltext
= lambda x
: "%.1f%%" % x
117 leveltext
= lambda x
: "%.2f GB" % (x
/ 1024.0)
119 # Prepare performance data
121 ('ramused', (memused_kb
- caches_kb
) / 1024, None, None, 0, totalmem_mb
),
122 ('swapused', swapused_kb
/ 1024, None, None, 0, meminfo
['SwapTotal'] / 1024),
123 ('memused', totalused_mb
, warn_mb
, crit_mb
, 0, totalvirt_mb
),
127 perfdata
.append(('memusedavg', totalused_mb_avg
))
131 if warn_mb
> 0: # positive levels - used memory
132 if comp_mb
>= crit_mb
:
134 infotext
+= ", critical at %s used" % leveltext(crit
)
135 elif comp_mb
>= warn_mb
:
137 infotext
+= ", warning at %s used" % leveltext(warn
)
138 else: # negative levels - free memory
139 freemem_mb
= totalvirt_mb
- comp_mb
140 if freemem_mb
<= -crit_mb
:
142 infotext
+= ", critical at %s free" % leveltext(-crit
)
143 elif freemem_mb
<= -warn_mb
:
145 infotext
+= ", warning at %s free" % leveltext(-warn
)
147 # Add additional metrics, provided by Linux.
148 mapped
= meminfo
.get('Mapped')
150 mapped_mb
= int(mapped
) / 1024
151 committed_as_mb
= int(meminfo
.get('Committed_AS', 0)) / 1024
152 shared_mb
= int(meminfo
.get('Shmem', 0)) / 1024
155 ('mapped', mapped_mb
),
156 ('committed_as', committed_as_mb
),
157 ('pagetables', pagetables_mb
),
158 ('shared', shared_mb
),
160 infotext
+= ", %.1f mapped, %.1f committed, %.1f shared" % \
161 (mapped_mb
/ 1024.0, committed_as_mb
/ 1024.0, shared_mb
/ 1024.0)
163 return state
, infotext
, perfdata