Maison > développement back-end > Golang > le corps du texte

Création d'un moniteur système simple en temps réel à l'aide de Go, HTMX et Web Socket

Barbara Streisand
Libérer: 2024-11-21 11:37:15
original
550 Les gens l'ont consulté

Je trouvais un projet amusant pour travailler avec Go, HTMX et Tailwwindcss et j'ai fini par créer un simple moniteur système basé sur le Web en temps réel avec la puissance d'un socket Web. Voici le résultat.

Building Simple Real-Time System Monitor using Go, HTMX, and Web Socket

Il affiche les informations système, les mémoires, le disque, le processeur et les processus en cours, mis à jour automatiquement toutes les 5 secondes.

Je vais détailler un peu le code dans cet article.

Piles

  • Allez 1.23.2
  • Htmx
  • Tailwindcss
  • Gopsutil
  • Websocket
  • Extension websocket HTML

Serveur HTTP

type HttpServer struct {
    subscriberMessageBuffer int
    Mux                     http.ServeMux
    subscribersMutex        sync.Mutex
    subscribers             map[*subscriber]struct{}
}

type subscriber struct {
    msgs chan []byte
}
Copier après la connexion

C’est assez simple. HttpServer contient un http.ServeMux comme gestionnaire http et des abonnés pour la diffusion ultérieure de sockets Web. l'abonné dispose simplement d'un canal de messages pour la mise à jour des données.

Comme il n'a besoin de servir qu'un seul fichier HTML, il a alors besoin d'une URL pour afficher la page et d'une URL pour la connexion au socket Web.

func NewHttpServer() *HttpServer {
    s := &HttpServer{
        subscriberMessageBuffer: 10,
        subscribers:             make(map[*subscriber]struct{}),
    }

    s.Mux.Handle("/", http.FileServer(http.Dir("./views")))
    s.Mux.HandleFunc("/ws", s.subscribeHandler)
    return s
}
Copier après la connexion

Connexion Web Socket et abonné

Endpoint /ws gérera la connexion au socket Web et gérera un abonné. Tout d'abord, il lancera un nouvel abonné et l'ajoutera à une carte dans la structure du serveur http. Le verrouillage sera utilisé pour éviter les conditions de concurrence puisque nous utiliserons la routine go plus tard.

func (s *HttpServer) subscribeHandler(w http.ResponseWriter, r *http.Request) {
    err := s.subscribe(r.Context(), w, r)
    if err != nil {
        fmt.Println(err)
        return
    }
}

func (s *HttpServer) addSubscriber(subscriber *subscriber) {
    s.subscribersMutex.Lock()
    s.subscribers[subscriber] = struct{}{}
    s.subscribersMutex.Unlock()
    fmt.Println("subscriber added", subscriber)
}
Copier après la connexion

Le socket Web commence à accepter une connexion et via une boucle, nous détecterons un message de canal entrant de l'abonné et l'écrirons sur le socket Web.

func (s *HttpServer) subscribe(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
    var c *websocket.Conn
    subscriber := &subscriber{
        msgs: make(chan []byte, s.subscriberMessageBuffer),
    }

    s.addSubscriber(subscriber)

    c, err := websocket.Accept(w, r, nil)
    if err != nil {
        return err
    }

    defer c.CloseNow()

    ctx = c.CloseRead(ctx)
    for {
        select {
        case msg := <-subscriber.msgs:
            ctx, cancel := context.WithTimeout(ctx, time.Second)
            defer cancel()
            err := c.Write(ctx, websocket.MessageText, msg)
            if err != nil {
                return err
            }
        case <-ctx.Done():
            return ctx.Err()
        }
    }
}

Copier après la connexion

Mise à jour automatique

La mise à jour automatique des données d'informations système est gérée par la routine go. Nous allons construire une réponse html qui sera envoyée via socket web et htmx gérera la mise à jour côté html.

func main() {
    fmt.Println("Starting system monitor")
    s := server.NewHttpServer()

    go func(s *server.HttpServer) {
        for {
            hostStat, _ := host.Info()
            timestamp := time.Now().Format("2006-01-02 15:04:05")
            html := `
            <span hx-swap-oob="innerHTML:#data-timestamp">` + timestamp + `</span>
            <span hx-swap-oob="innerHTML:#system-hostname">` + hostStat.Hostname + `</span>
            <span hx-swap-oob="innerHTML:#system-os">` + hostStat.OS + `</span>
            `
            s.Broadcast([]byte(html))
            time.Sleep(time.Second * 5)
        }
    }(s)
    // ...
}
Copier après la connexion

La syntaxe hx-swap-oob="innerHTML:#data-timestamp" en htmx nous indique qu'il faut échanger un composant à l'intérieur de l'identifiant d'horodatage des données dans notre code HTML. Tous les mécanismes d'échange seront les mêmes pour les autres composants d'informations du système.

Tous les composants HTML échangeables seront envoyés via la méthode Broadcast (msg) et plus tard seront envoyés via le canal toutes les 5 secondes.

func (s *HttpServer) Broadcast(msg []byte) {
    s.subscribersMutex.Lock()
    for subscriber := range s.subscribers {
        subscriber.msgs <- msg
    }
    s.subscribersMutex.Unlock()
}
Copier après la connexion

La vue HTML

C'est un simple fichier HTML et pour Tailwindcss, j'ai simplement utilisé CDN pour ça

<script src="https://cdn.tailwindcss.com"></script>
Copier après la connexion

Même idée pour HTMX et extension de socket Web pour utiliser CDN.

<script src="https://unpkg.com/htmx.org@2.0.3" integrity="sha384-0895/pl2MU10Hqc6jd4RvrthNlDiE9U1tWmX7WRESftEDRosgxNsQG/Ze9YMRzHq" crossorigin="anonymous"></script>
<script src="https://unpkg.com/htmx-ext-ws@2.0.1/ws.js"></script>
Copier après la connexion

Comment se connecter à la socket web ?

La page de surveillance du système devrait recevoir toutes les données par socket Web afin que je puisse les définir à partir du conteneur div principal. Spécifiez hx-ext="ws" pour indiquer à HTMX d'utiliser l'extension de socket Web et ws-connect = "/ws" pour indiquer à la socket Web de se connecter via l'URL /ws.

<corps>



<h2>
  
  
  Code complet
</h2>

<p>Voici la version complète du code https://github.com/didikz/gosysmon-web et vous voudrez peut-être jouer avec votre propre version.</p>

<p>Bon codage !</p>


          
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal