I concur with using visdom.
I recommend putting the code that handles drawing the visualizations in a different module for clarity, e.g.:
# module visualizations.py
from datetime import datetime
import visdom

class Visualizations:
    def __init__(self, env_name=None):
        if env_name is None:
            env_name = str(datetime.now().strftime("%d-%m %Hh%M"))
        self.env_name = env_name
        self.vis = visdom.Visdom(env=self.env_name)
        self.loss_win = None

    def plot_loss(self, loss, step):
        self.loss_win = self.vis.line(
            [loss],
            [step],
            win=self.loss_win,
            update='append' if self.loss_win else None,
            opts=dict(
                xlabel='Step',
                ylabel='Loss',
                title='Loss (mean per 10 steps)',
            )
        )

# module train.py
(...)

def train():
    (...)
    
    # Initialize the visualization environment
    vis = Visualizations()

    # Training loop
    loss_values = []
    for step, input in enumerate(loader):
        # Forward pass
        output = model(input)
        loss = model.loss(output)
        loss_values.append(loss.item())
    
        # Backward pass
        model.zero_grad()
        loss.backward()
        optimizer.step()
    
        # Visualization data
        if step % 10 == 0:
            vis.plot_loss(np.mean(loss_values), step)
            loss_values.clear()

Visdom is partially documented on its github page, and I found the demo 240 they provide to answer a lot of my questions on the usage. For more complex plots, use matplotlib and embed them using vis.matplot 54.
Here is an example of a visdom environment:

chrome_VjAh5A73XH.png1529×877 68.1 KB