Metadata-Version: 2.4
Name: cjm-system-monitor-nvidia
Version: 0.0.24
Summary: An NVIDIA GPU monitoring plugin for the cjm-plugin-system that provides real-time hardware telemetry via nvitop.
Author-email: "Christian J. Mills" <9126128+cj-mills@users.noreply.github.com>
License: Apache-2.0
Project-URL: Repository, https://github.com/cj-mills/cjm-system-monitor-nvidia
Project-URL: Documentation, https://cj-mills.github.io/cjm-system-monitor-nvidia
Keywords: nbdev,jupyter,notebook,python
Classifier: Natural Language :: English
Classifier: Intended Audience :: Developers
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cjm_plugin_system>=0.0.46
Requires-Dist: cjm_capability_primitives>=0.0.8
Requires-Dist: nvitop
Requires-Dist: psutil
Dynamic: license-file

# cjm-system-monitor-nvidia


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## Install

``` bash
pip install cjm_system_monitor_nvidia
```

## Project Structure

    nbs/
    ├── meta.ipynb   # Metadata introspection for the NVIDIA monitor plugin used by cjm-ctl to generate the registration manifest
    └── plugin.ipynb # Plugin implementation for NVIDIA GPU monitoring using nvitop

Total: 2 notebooks

## Module Dependencies

``` mermaid
graph LR
    meta["meta<br/>meta"]
    plugin["plugin<br/>plugin"]
```

No cross-module dependencies detected.

## CLI Reference

No CLI commands found in this project.

## Module Overview

Detailed documentation for each module in the project:

### meta (`meta.ipynb`)

> Metadata introspection for the NVIDIA monitor plugin used by cjm-ctl
> to generate the registration manifest

#### Import

``` python
from cjm_system_monitor_nvidia.meta import (
    get_plugin_metadata
)
```

#### Functions

``` python
def get_plugin_metadata() -> Dict[str, Any]:  # Plugin metadata for manifest generation
    """Return metadata required to register this plugin with the PluginManager."""
    # Fallback base path (current behavior for backward compatibility)
    base_path = os.path.dirname(os.path.dirname(sys.executable))
    
    # Use CJM config if available, else fallback to env-relative paths
    cjm_plugin_data_dir = os.environ.get("CJM_PLUGIN_DATA_DIR")
    
    # Plugin data directory
    plugin_name = "cjm-system-monitor-nvidia"
    if cjm_plugin_data_dir
    "Return metadata required to register this plugin with the PluginManager."
```

### plugin (`plugin.ipynb`)

> Plugin implementation for NVIDIA GPU monitoring using nvitop

#### Import

``` python
from cjm_system_monitor_nvidia.plugin import (
    NvidiaMonitorPlugin
)
```

#### Classes

``` python
class NvidiaMonitorPlugin:
    def __init__(self):
        """Initialize the NVIDIA monitor plugin."""
        self.logger = logging.getLogger(f"{__name__}.{type(self).__name__}")
        self.config = {}

    @property
    def name(self) -> str:  # Tool identity, derived from the installed distribution (PILLAR 1c)
    "NVIDIA System Monitor using nvitop (a pure-telemetry ToolCapability)."
    
    def __init__(self):
            """Initialize the NVIDIA monitor plugin."""
            self.logger = logging.getLogger(f"{__name__}.{type(self).__name__}")
            self.config = {}
    
        @property
        def name(self) -> str:  # Tool identity, derived from the installed distribution (PILLAR 1c)
        "Initialize the NVIDIA monitor plugin."
    
    def name(self) -> str:  # Tool identity, derived from the installed distribution (PILLAR 1c)
            """Get the tool name (the installed distribution name)."""
            from importlib.metadata import metadata, packages_distributions
            # `__package__` is None in a notebook/__main__ context, so guard the
            # derivation with the known package module name.
            pkg = __package__ or "cjm_system_monitor_nvidia"
            dist = (packages_distributions().get(pkg) or [pkg.replace("_", "-")])[0]
            return metadata(dist)["Name"]
    
        @property
        def version(self) -> str:  # Tool version
        "Get the tool name (the installed distribution name)."
    
    def version(self) -> str:  # Tool version
            """Get the tool version string."""
            from cjm_system_monitor_nvidia import __version__
            return __version__
    
        def initialize(
            self,
            config: Optional[Dict[str, Any]] = None  # Configuration dictionary
        ) -> None
        "Get the tool version string."
    
    def initialize(
            self,
            config: Optional[Dict[str, Any]] = None  # Configuration dictionary
        ) -> None
        "Initialize or reconfigure the plugin."
    
    def get_config_schema(self) -> Dict[str, Any]:  # JSON Schema
            """Return JSON Schema for configuration."""
            return {}  # No config needed for monitoring
    
        def get_current_config(self) -> Dict[str, Any]:  # Current config
        "Return JSON Schema for configuration."
    
    def get_current_config(self) -> Dict[str, Any]:  # Current config
            """Return current configuration."""
            return self.config
    
    
    
        def _get_gpu_info_internal(self) -> Dict[str, Any]:  # Raw GPU data
        "Return current configuration."
    
    def get_system_status(self) -> SystemStats:  # Current system telemetry
            """Collect host CPU/RAM + aggregated GPU stats as a typed SystemStats.
    
            Per-process GPU usage is exposed separately via `list_processes()`. This
            is the native-dispatch surface the substrate's `_get_global_stats` calls
            for resource-derived admission (`MonitorToolProtocol`).
            """
            # 1. Get Host CPU/RAM (psutil)
            vm = psutil.virtual_memory()
    
            # 2. Get GPU Data
            gpu_raw = self._get_gpu_info_internal()
    
            # 3. Aggregate GPU Stats for the Scheduler
            total_vram_free = 0
            total_vram_total = 0
            total_vram_used = 0
            max_load = 0
    
            if gpu_raw['available']
        "Collect host CPU/RAM + aggregated GPU stats as a typed SystemStats.

Per-process GPU usage is exposed separately via `list_processes()`. This
is the native-dispatch surface the substrate's `_get_global_stats` calls
for resource-derived admission (`MonitorToolProtocol`)."
    
    def list_processes(self) -> List[ProcessStats]:  # Per-process GPU usage
        "Per-process GPU memory usage as typed ProcessStats.

Sources the same nvitop/nvidia-smi enumeration `get_system_status` uses;
returns `[]` when there is no GPU or no per-process attribution available.
The substrate's GPU subtree attribution intersects these PIDs with the
worker's process tree (`attribute_gpu_to_worker_subtree`)."
```
