Skip to content

journal: SendVals with arbitrary auto-converting functions #454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions journal/journal_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,24 @@ func fdIsJournalStream(fd int) (bool, error) {
// (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
// for more details. vars may be nil.
func Send(message string, priority Priority, vars map[string]string) error {
return send(message, priority, func(b *bytes.Buffer) {
for k, v := range vars {
appendVariable(b, k, v)
}
})
}

// Send a message to the local systemd journal. Optional values may be
// provided as a list of Value variablese.
func SendVals(message string, priority Priority, values ...Value) error {
return send(message, priority, func(b *bytes.Buffer) {
for _, v := range values {
appendVariable(b, v.Name(), v.Value())
}
})
}

func send(message string, priority Priority, varFunc func(data *bytes.Buffer)) error {
conn := getOrInitConn()
if conn == nil {
return errors.New("could not initialize socket to journald")
Expand All @@ -142,9 +160,7 @@ func Send(message string, priority Priority, vars map[string]string) error {
data := new(bytes.Buffer)
appendVariable(data, "PRIORITY", strconv.Itoa(int(priority)))
appendVariable(data, "MESSAGE", message)
for k, v := range vars {
appendVariable(data, k, v)
}
varFunc(data)

_, _, err := conn.WriteMsgUnix(data.Bytes(), nil, socketAddr)
if err == nil {
Expand Down
18 changes: 18 additions & 0 deletions journal/journal_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,24 @@ func TestStderrIsJournalStream(t *testing.T) {
if err != nil {
t.Fatal(err)
}

err = journal.Send(message, journal.PriInfo, map[string]string{"KEY": "VALUE"})
if err != nil {
t.Fatal(err)
}

err = journal.SendVals(message, journal.PriInfo)
if err != nil {
t.Fatal(err)
}

err = journal.SendVals(message, journal.PriInfo,
journal.String("KEY", "VALUE"),
journal.Int("INT_KEY", 1),
)
if err != nil {
t.Fatal(err)
}
}
}

Expand Down
80 changes: 80 additions & 0 deletions journal/values.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package journal

import (
"strconv"
"time"
)

// Value represents a key-value pair that can be logged to the journal.
type Value interface {
// Name must be composed of uppercase letters, numbers,
// and underscores, but must not start with an underscore. Within these
// restrictions, any arbitrary field name may be used. Some names have special
// significance: see the journalctl documentation
// (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html)
// for more details.
Name() string

// Value must be a string representation of the value.
Value() string
}

type value struct {
name string
value string
}

var _ = Value(&value{})

func (s value) Name() string {
return s.name
}

func (s value) Value() string {
return s.value
}

// String returns a Value for a string value.
func String(name, Value string) Value {
return &value{name, Value}
}

// Int returns a Value for an int.
func Int(name string, Value int) Value {
return &value{name, strconv.Itoa(Value)}
}

// Int64 returns a Value for an int64.
func Int64(name string, Value int64) Value {
return &value{name, strconv.FormatInt(Value, 10)}
}

// Uint64 returns a Value for a uint64.
func Uint64(name string, Value uint64) Value {
return &value{name, strconv.FormatUint(Value, 10)}
}

// Float64 returns a Value for a floating-point number.
func Float64(name string, Value float64) Value {
return &value{name, strconv.FormatFloat(Value, 'g', -1, 64)}
}

// Bool returns a Value for a bool.
func Bool(name string, Value bool) Value {
return &value{name, strconv.FormatBool(Value)}
}

// Time returns a Value for a time.Time.
func Time(name string, Value time.Time) Value {
return &value{name, Value.Format(time.RFC3339Nano)}
}

// Duration returns a Value for a time.Duration.
func Duration(name string, Value time.Duration) Value {
return &value{name, Value.String()}
}

// Error returns a Value for an error.
func Error(name string, Value error) Value {
return &value{name, Value.Error()}
}
Loading