import psutil import panel as pn import pandas as pd import holoviews as hv from holoviews import dim, opts hv.extension("bokeh") # Define functions to get memory and CPU usage def get_mem_data(): vmem = psutil.virtual_memory() df = pd.DataFrame(dict(free=vmem.free/vmem.total, used=vmem.used/vmem.total), index=[pd.Timestamp.now()]) return df*100 def get_cpu_data(): cpu_percent = psutil.cpu_percent(percpu=True) df = pd.DataFrame(list(enumerate(cpu_percent)), columns=['CPU', 'Utilization']) df['time'] = pd.Timestamp.now() return df # Define DynamicMap callbacks returning Elements def mem_stack(data): data = pd.melt(data, 'index', var_name='Type', value_name='Usage') areas = hv.Dataset(data).to(hv.Area, 'index', 'Usage') return hv.Area.stack(areas.overlay()).relabel('Memory') def cpu_box(data): return hv.BoxWhisker(data, 'CPU', 'Utilization', label='CPU Usage') # Set up StreamingDataFrame and add async callback cpu_stream = hv.streams.Buffer(get_cpu_data(), 800, index=False) mem_stream = hv.streams.Buffer(get_mem_data()) # Define DynamicMaps and display plot cpu_dmap = hv.DynamicMap(cpu_box, streams=[cpu_stream]) mem_dmap = hv.DynamicMap(mem_stack, streams=[mem_stream]) plot = (cpu_dmap + mem_dmap).opts( opts.Area(height=400, width=400, ylim=(0, 100), framewise=True), opts.BoxWhisker(box_fill_color=dim('CPU').str(), cmap='Category20', width=500, height=400, ylim=(0, 100)) ) # Create PeriodicCallback which run every 500 milliseconds def cb(): cpu_stream.send(get_cpu_data()) mem_stream.send(get_mem_data()) callback = pn.io.PeriodicCallback(callback=cb, period=500) callback.start() # Show plot inside notebook plot