| Current Path : /lib/python3.6/site-packages/azurelinuxagent/common/ |
| Current File : //lib/python3.6/site-packages/azurelinuxagent/common/resourceusage.py |
# Copyright 2019 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Requires Python 2.6+ and Openssl 1.0+
import os
from azurelinuxagent.common import logger
from azurelinuxagent.common.exception import AgentError
from azurelinuxagent.common.future import ustr
from azurelinuxagent.common.logger import EVERY_SIX_HOURS
from azurelinuxagent.common.utils import fileutil
PAGE_SIZE = os.sysconf('SC_PAGE_SIZE')
PROC_STATM_FILENAME_FORMAT = "/proc/{0}/statm"
PROC_CMDLINE_FILENAME_FORMAT = "/proc/{0}/cmdline"
PROC_COMM_FILENAME_FORMAT = "/proc/{0}/comm"
PROC_STATUS_FILENAME_FORMAT = "/proc/{0}/status"
class ResourceUsage(object):
pass
class MemoryResourceUsage(ResourceUsage):
@staticmethod
def get_memory_usage_from_proc_statm(process_id):
proc_pid_rss = 0
try:
proc_pid_rss = MemoryResourceUsage._get_proc_rss(process_id)
except Exception as e:
if isinstance(e, (IOError, OSError)):
raise
logger.periodic_info(EVERY_SIX_HOURS, "[PERIODIC] Could not get the /prod/{0}/statm data due to {1}", process_id, ustr(e))
raise ProcessInfoException("Could not get the /proc/{0}/statm due to {1}".format(process_id, ustr(e)))
return proc_pid_rss
@staticmethod
def _get_proc_rss(process_id):
"""
/proc/<pid>/statm fields: columns are (in pages):
total program size|
resident set size|
shared pages|
text (code) |
data/stack |
library |
dirty pages |
Here an example:
root@vm:/# cat /proc/1392/statm
17637 5316 2125 938 0 3332 0
:return: resident set size in bytes.
"""
pid_statm = fileutil.read_file(PROC_STATM_FILENAME_FORMAT.format(process_id)).split()
pid_rss = int(pid_statm[1]) # Index 1 is RSS.
return pid_rss * PAGE_SIZE
class ProcessInfo(object):
@staticmethod
def get_proc_name(process_id):
proc_pid_rss = ProcessInfo._get_proc_comm(process_id)
return proc_pid_rss
@staticmethod
def get_proc_cmdline(process_id):
proc_pid_rss = ProcessInfo._get_proc_cmdline(process_id)
return proc_pid_rss
@classmethod
def _get_proc_cmdline(cls, process_id):
"""
/proc/<pid>/cmdline returns cmdline arguments passed to the Linux kernel. The returned string is delimited with
the \0 character and needs to be replaced with some other character to make it readable.
Here an example:
root@vm:/# cat /proc/1392/cmdline
python--targettest_resourceusage.py
root@vm:/# cat /proc/1392/cmdline | tr "\0" " "
python --target test_resourceusage.py
:return: command line passed to the process string.
"""
cmdline_file_name = PROC_CMDLINE_FILENAME_FORMAT.format(process_id)
try:
pid_cmdline = fileutil.read_file(cmdline_file_name).replace("\0", " ").strip()
except Exception as e:
if isinstance(e, (IOError, OSError)):
raise
raise ProcessInfoException("Could not get contents from {0}".format(cmdline_file_name), e)
return pid_cmdline
@classmethod
def _get_proc_comm(cls, process_id):
"""
/proc/<pid>/comm This file exposes the process's comm value-that is, the command name associated with the
process. Strings longer than TASK_COMM_LEN (16) characters are silently truncated.
Here an example:
root@vm:/# cat /proc/1392/comm
python
:return: process name
"""
comm_file_name = PROC_COMM_FILENAME_FORMAT.format(process_id)
try:
pid_comm = fileutil.read_file(comm_file_name).strip()
pid_comm_str = str(pid_comm)
except Exception as e:
if isinstance(e, (IOError, OSError)):
raise
raise ProcessInfoException("Could not get contents from {0}".format(comm_file_name), e)
return pid_comm_str
class ProcessInfoException(AgentError):
"""
Exception to classify any issues when we get any issues related to fetching ProcessInfo (cmdline, comm, etc.).
"""
def __init__(self, msg=None, inner=None):
super(ProcessInfoException, self).__init__(msg, inner)