galog_serial.go (63 lines of code) (raw):

// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package galog import ( "context" "fmt" "go.bug.st/serial" ) const ( // DefaultSerialBaud is the default serial baud for serial port writing. DefaultSerialBaud = 115200 // defaultSerialQueueSize is the default queue size of the serial backend. defaultSerialQueueSize = 1000 ) // SerialBackend is an implementation for logging to serial. type SerialBackend struct { // backendID is the serial backend ID. backendID string // opts is the serial configuration options. opts *SerialOptions // config is a pointer to the generic Config interface implementation. config *backendConfig } // SerialOptions contains the options for serial backend. type SerialOptions struct { // Port is the serial port name to be written to. Port string // Baud is the serial port baud. Baud int } // NewSerialBackend returns a Backend implementation that will log out to // the configured serial port. func NewSerialBackend(ctx context.Context, opts *SerialOptions) *SerialBackend { res := &SerialBackend{ backendID: "log-backend,serial", opts: opts, config: newBackendConfig(defaultSerialQueueSize), } res.config.SetFormat(ErrorLevel, `{{.When.Format "2006-01-02T15:04:05.0000Z07:00"}} {{if .Prefix}} {{.Prefix}}: {{end}}[{{.Level}}]: {{.Message}}`) res.config.SetFormat(DebugLevel, `{{.When.Format "2006-01-02T15:04:05.0000Z07:00"}} {{if .Prefix}} {{.Prefix}}: {{end}}[{{.Level}}]: ({{.File}}:{{.Line}}) {{.Message}}`) return res } // Log prints the log entry to setup serial. func (sb *SerialBackend) Log(entry *LogEntry) error { config := &serial.Mode{ BaudRate: sb.opts.Baud, } port, err := serial.Open(sb.opts.Port, config) if err != nil { return fmt.Errorf("error opening serial port: %+v", err) } defer port.Close() format := sb.config.Format(entry.Level) message, err := entry.Format(format + "\n") if err != nil { return fmt.Errorf("failed to format log level: %+v", err) } nn, err := port.Write([]byte(message)) if err != nil { return fmt.Errorf("failed to write log to serial: %+v", err) } if nn != len(message) { return fmt.Errorf("failed to write the message, wrote %d bytes out of %d bytes", nn, len(message)) } return nil } // ID returns the cloud logging backend implementation's ID. func (sb *SerialBackend) ID() string { return sb.backendID } // Shutdown is a no-op implementation for serial backend as we are opening the file // for every log operation. func (sb *SerialBackend) Shutdown(context.Context) error { return nil } // Config returns the configuration of the serial backend. func (sb *SerialBackend) Config() Config { return sb.config }