| Conditions | 25 |
| Total Lines | 170 |
| Code Lines | 93 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like glances.processes.GlancesProcesses.update() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | # -*- coding: utf-8 -*- |
||
| 249 | def update(self): |
||
| 250 | """Update the processes stats.""" |
||
| 251 | # Reset the stats |
||
| 252 | self.processlist = [] |
||
| 253 | self.reset_processcount() |
||
| 254 | |||
| 255 | # Do not process if disable tag is set |
||
| 256 | if self.disable_tag: |
||
| 257 | return |
||
| 258 | |||
| 259 | # Time since last update (for disk_io rate computation) |
||
| 260 | time_since_update = getTimeSinceLastUpdate('process_disk') |
||
| 261 | |||
| 262 | # Grab standard stats |
||
| 263 | ##################### |
||
| 264 | sorted_attrs = ['cpu_percent', 'cpu_times', 'memory_percent', 'name', 'status', 'status', 'num_threads'] |
||
| 265 | displayed_attr = ['memory_info', 'nice', 'pid', 'ppid'] |
||
| 266 | cached_attrs = ['cmdline', 'username'] |
||
| 267 | |||
| 268 | # Some stats are optional |
||
| 269 | if not self.disable_io_counters: |
||
| 270 | sorted_attrs.append('io_counters') |
||
| 271 | if not self.disable_gids: |
||
| 272 | displayed_attr.append('gids') |
||
| 273 | # Some stats are not sort key |
||
| 274 | # An optimisation can be done be only grabbed displayed_attr |
||
| 275 | # for displayed processes (but only in standalone mode...) |
||
| 276 | sorted_attrs.extend(displayed_attr) |
||
| 277 | # Some stats are cached (not necessary to be refreshed every time) |
||
| 278 | if self.cache_timer.finished(): |
||
| 279 | sorted_attrs += cached_attrs |
||
| 280 | self.cache_timer.set(self.cache_timeout) |
||
| 281 | self.cache_timer.reset() |
||
| 282 | is_cached = False |
||
| 283 | else: |
||
| 284 | is_cached = True |
||
| 285 | |||
| 286 | # Build the processes stats list (it is why we need psutil>=5.3.0) |
||
| 287 | self.processlist = [ |
||
| 288 | p.info |
||
| 289 | for p in psutil.process_iter(attrs=sorted_attrs, ad_value=None) |
||
| 290 | # OS-related processes filter |
||
| 291 | if not (BSD and p.info['name'] == 'idle') |
||
| 292 | and not (WINDOWS and p.info['name'] == 'System Idle Process') |
||
| 293 | and not (MACOS and p.info['name'] == 'kernel_task') |
||
| 294 | and |
||
| 295 | # Kernel threads filter |
||
| 296 | not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0) |
||
| 297 | ] |
||
| 298 | |||
| 299 | # Sort the processes list by the current sort_key |
||
| 300 | self.processlist = sort_stats(self.processlist, sorted_by=self.sort_key, reverse=True) |
||
| 301 | |||
| 302 | # Update the processcount |
||
| 303 | self.update_processcount(self.processlist) |
||
| 304 | |||
| 305 | # Loop over processes and add metadata |
||
| 306 | first = True |
||
| 307 | for proc in self.processlist: |
||
| 308 | # Get extended stats, only for top processes (see issue #403). |
||
| 309 | if first and not self.disable_extended_tag: |
||
| 310 | # - cpu_affinity (Linux, Windows, FreeBSD) |
||
| 311 | # - ionice (Linux and Windows > Vista) |
||
| 312 | # - num_ctx_switches (not available on Illumos/Solaris) |
||
| 313 | # - num_fds (Unix-like) |
||
| 314 | # - num_handles (Windows) |
||
| 315 | # - memory_maps (only swap, Linux) |
||
| 316 | # https://www.cyberciti.biz/faq/linux-which-process-is-using-swap/ |
||
| 317 | # - connections (TCP and UDP) |
||
| 318 | extended = {} |
||
| 319 | try: |
||
| 320 | top_process = psutil.Process(proc['pid']) |
||
| 321 | extended_stats = ['cpu_affinity', 'ionice', 'num_ctx_switches'] |
||
| 322 | if LINUX: |
||
| 323 | # num_fds only avalable on Unix system (see issue #1351) |
||
| 324 | extended_stats += ['num_fds'] |
||
| 325 | if WINDOWS: |
||
| 326 | extended_stats += ['num_handles'] |
||
| 327 | |||
| 328 | # Get the extended stats |
||
| 329 | extended = top_process.as_dict(attrs=extended_stats, ad_value=None) |
||
| 330 | |||
| 331 | if LINUX: |
||
| 332 | try: |
||
| 333 | extended['memory_swap'] = sum([v.swap for v in top_process.memory_maps()]) |
||
| 334 | except (psutil.NoSuchProcess, KeyError): |
||
| 335 | # (KeyError catch for issue #1551) |
||
| 336 | pass |
||
| 337 | except (psutil.AccessDenied, NotImplementedError): |
||
| 338 | # NotImplementedError: /proc/${PID}/smaps file doesn't exist |
||
| 339 | # on kernel < 2.6.14 or CONFIG_MMU kernel configuration option |
||
| 340 | # is not enabled (see psutil #533/glances #413). |
||
| 341 | extended['memory_swap'] = None |
||
| 342 | try: |
||
| 343 | extended['tcp'] = len(top_process.connections(kind="tcp")) |
||
| 344 | extended['udp'] = len(top_process.connections(kind="udp")) |
||
| 345 | except (psutil.AccessDenied, psutil.NoSuchProcess): |
||
| 346 | # Manage issue1283 (psutil.AccessDenied) |
||
| 347 | extended['tcp'] = None |
||
| 348 | extended['udp'] = None |
||
| 349 | except (psutil.NoSuchProcess, ValueError, AttributeError) as e: |
||
| 350 | logger.error('Can not grab extended stats ({})'.format(e)) |
||
| 351 | extended['extended_stats'] = False |
||
| 352 | else: |
||
| 353 | logger.debug('Grab extended stats for process {}'.format(proc['pid'])) |
||
| 354 | extended['extended_stats'] = True |
||
| 355 | proc.update(extended) |
||
| 356 | first = False |
||
| 357 | # /End of extended stats |
||
| 358 | |||
| 359 | # PID is the key |
||
| 360 | proc['key'] = 'pid' |
||
| 361 | |||
| 362 | # Time since last update (for disk_io rate computation) |
||
| 363 | proc['time_since_update'] = time_since_update |
||
| 364 | |||
| 365 | # Process status (only keep the first char) |
||
| 366 | proc['status'] = str(proc['status'])[:1].upper() |
||
| 367 | |||
| 368 | # Process IO |
||
| 369 | # procstat['io_counters'] is a list: |
||
| 370 | # [read_bytes, write_bytes, read_bytes_old, write_bytes_old, io_tag] |
||
| 371 | # If io_tag = 0 > Access denied or first time (display "?") |
||
| 372 | # If io_tag = 1 > No access denied (display the IO rate) |
||
| 373 | if 'io_counters' in proc and proc['io_counters'] is not None: |
||
| 374 | io_new = [proc['io_counters'].read_bytes, proc['io_counters'].write_bytes] |
||
| 375 | # For IO rate computation |
||
| 376 | # Append saved IO r/w bytes |
||
| 377 | try: |
||
| 378 | proc['io_counters'] = io_new + self.io_old[proc['pid']] |
||
| 379 | io_tag = 1 |
||
| 380 | except KeyError: |
||
| 381 | proc['io_counters'] = io_new + [0, 0] |
||
| 382 | io_tag = 0 |
||
| 383 | # then save the IO r/w bytes |
||
| 384 | self.io_old[proc['pid']] = io_new |
||
| 385 | else: |
||
| 386 | proc['io_counters'] = [0, 0] + [0, 0] |
||
| 387 | io_tag = 0 |
||
| 388 | # Append the IO tag (for display) |
||
| 389 | proc['io_counters'] += [io_tag] |
||
| 390 | |||
| 391 | # Manage cached information |
||
| 392 | if is_cached: |
||
| 393 | # Grab cached values (in case of a new incoming process) |
||
| 394 | if proc['pid'] not in self.processlist_cache: |
||
| 395 | try: |
||
| 396 | self.processlist_cache[proc['pid']] = psutil.Process(pid=proc['pid']).as_dict( |
||
| 397 | attrs=cached_attrs, ad_value=None |
||
| 398 | ) |
||
| 399 | except psutil.NoSuchProcess: |
||
| 400 | pass |
||
| 401 | # Add cached value to current stat |
||
| 402 | try: |
||
| 403 | proc.update(self.processlist_cache[proc['pid']]) |
||
| 404 | except KeyError: |
||
| 405 | pass |
||
| 406 | else: |
||
| 407 | # Save values to cache |
||
| 408 | self.processlist_cache[proc['pid']] = {cached: proc[cached] for cached in cached_attrs} |
||
| 409 | |||
| 410 | # Apply filter |
||
| 411 | self.processlist = [p for p in self.processlist if not (self._filter.is_filtered(p))] |
||
| 412 | |||
| 413 | # Compute the maximum value for keys in self._max_values_list: CPU, MEM |
||
| 414 | # Useful to highlight the processes with maximum values |
||
| 415 | for k in self._max_values_list: |
||
| 416 | values_list = [i[k] for i in self.processlist if i[k] is not None] |
||
| 417 | if values_list: |
||
| 418 | self.set_max_values(k, max(values_list)) |
||
| 419 | |||
| 522 |