1

I have a bluetooth service written in go, let's call it ble-service. I want to add a characteristic to stream logs from the service over bluetooth.

My plan is to use "github.com/coreos/go-systemd/v22/sdjournal" to access the local journal from within a gatt notifier, read each log message until there are none left, then wait for more logs to come in.

So far I have:

// +build linux

package service

import (
    "fmt"
    "regexp"
    "time"

    "github.com/coreos/go-systemd/v22/sdjournal"
    "github.com/paypal/gatt"
)

var (
    attrLogServiceUUID  = gatt.UUID16(0xD200)
    attrLogs            = BleAttribute{uuid: gatt.UUID16(0xD201), name: "Ble Service Logs"}
)

var messageRe = regexp.MustCompile(`"message"=>"(.*?)"`)

func nextJournalLog(journal *sdjournal.Journal) (msg string, hasMore bool, err error) {
    i, err := journal.Next()
    if err != nil {
        return "", i == 0, err
    }
    if  i == 0 {
        return "", false, err
    }

    fmt.Println("Cursor ", i)
    entry, err := journal.GetEntry()
    if err != nil {
        return "", true, err
    }
    fmt.Println("Entry: ", entry)
    msgDataValue, err := journal.GetDataValue("MESSAGE")
    if err != nil {
        return "", true, err
    }
    fmt.Println("Message: ", msgDataValue)

    matches := messageRe.FindStringSubmatch(msgDataValue)
    fmt.Println(matches)
    if len(matches) > 1 {
        return matches[1], true, nil
    }
    return "", true, nil
}

func NewLogService() (s *gatt.Service) {
    s = newService(attrLogServiceUUID)
    
    logsChar := addCharacteristic(s, attrLogs)
    
    logsChar.HandleNotifyFunc(
        func(r gatt.Request, n gatt.Notifier) {
            defer logBLENotify(r, logsChar, "Logs")()

            journal, err := sdjournal.NewJournal()
            if err != nil {
                fmt.Println("Error creating journal", err)
                return
            }
            defer func() { journal.Close() }()

            err = journal.SeekTail()
            if err != nil {
                fmt.Println("Error seeking journal tail", err)
                return
            }
            cursor, err := journal.PreviousSkip(3)
            if err != nil {
                fmt.Println("Error seeking journal tail", err)
                return
            }
            fmt.Println("Cursor ", cursor)

            for !n.Done() {
                msg, hasMore, err := nextJournalLog(journal)
                time.Sleep(time.Second)
                if err != nil {
                    fmt.Println(err)
                    continue
                }
                if !hasMore {
                    fmt.Println("Waiting for more logs")
                    time.Sleep(3 * time.Second)
                    continue
                }
                _, err = n.Write([]byte(msg))
                if err != nil {
                    fmt.Println("Failed to write msg", msg)
                    continue
                }
            }
        })

        return
}

When ran as a systems service, I can subscribe to the above log characteristic, but I see no log output. However, If I run this as an executable, I can see the journald logs from the last time I ran it as a systems service.

Is there a way to access the logs of the service as it is running?

0 Answers0