journal/attr_key.go

139 lines
3.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package journal
import (
"fmt"
)
// AttrKey holds the key part of a key/value (attribute) pair. Passing an
// uninitialised (or invalid) AttrKey to other journal methods will cause the
// attribute to be ignored; check for errors from NewAttrKey to ensure that
// your keys are valid ahead of time.
type AttrKey struct {
// key is written directly to the journal socket. If it is empty, then
// the attribute should be silently discarded. By having it unexported,
// we can ensure that library users can only ever have valid string
// values here.
key string
}
// Key returns the string value of the key. If the attribute is invalid, it
// returns an empty string.
func (ak AttrKey) Key() string {
return ak.key
}
// Valid returns true if ak is valid.
func (ak AttrKey) Valid() bool {
return ak.key != ""
}
// NewAttrKey initialises and returns an AttrKey that may be used when
// constructing key/value (attribute) pairs for logging. If the key is invalid,
// then an error will be returned (and the returned key value will be invalid,
// and any attribute using that key will silently be omitted from the logs).
// Rules for valid attribute keys:
// - must not be empty;
// - must not begin with an underscore '_';
// - must only contain uppercase ASCII 'A''Z', digits '0''9', or
// underscores;
// - must be < 256 characters.
func NewAttrKey(key string) (AttrKey, error) {
if err := AttrKeyValid(key); err != nil {
return AttrKey{}, err
}
return AttrKey{
key: key,
}, nil
}
// MustAttrKey returns an AttrKey for the given string. If the string is not a
// valid systemd attribute key, it returns an invalid AttrKey that will cause
// the attribute not to be emitted to the journal.
func MustAttrKey(key string) AttrKey {
if err := AttrKeyValid(key); err != nil {
return AttrKey{}
}
return AttrKey{
key: key,
}
}
// AttrKeyValid checks the given attribute key and returns an error if there is
// a fault with it.
func AttrKeyValid(key string) error {
switch {
case key == "":
return &InvalidAttrKey{
Key: key,
Reason: AttrKeyEmpty,
}
case key[0] == '_':
return &InvalidAttrKey{
Key: key,
Reason: AttrKeyTrusted,
}
case len(key) >= 256:
return &InvalidAttrKey{
Key: key,
Reason: AttrKeyLength,
}
case !attrKeyValidChars(key):
return &InvalidAttrKey{
Key: key,
Reason: AttrKeyInvalidChars,
}
default:
return nil
}
}
// attrKeyValidChars returns true if the given key comprises only ASCII 'A''Z',
// '0''9' and underscores.
func attrKeyValidChars(key string) bool {
for _, b := range key {
switch {
case b >= 'A' && b <= 'Z':
case b >= '0' && b <= '9':
case b == '_':
default:
return false
}
}
return true
}
// InvalidAttrKey details why a given attribute key is invalid.
type InvalidAttrKey struct {
Key string
Reason InvalidAttrKeyReason
}
func (iak *InvalidAttrKey) Error() string {
return fmt.Sprintf("invalid systemd journal attribute key %q: %s", iak.Key, iak.Reason)
}
type InvalidAttrKeyReason int
const (
AttrKeyEmpty InvalidAttrKeyReason = iota
AttrKeyTrusted
AttrKeyLength
AttrKeyInvalidChars
)
func (iar InvalidAttrKeyReason) String() string {
switch iar {
case AttrKeyEmpty:
return "key is empty"
case AttrKeyTrusted:
return "key is trusted (begins with '_' character)"
case AttrKeyLength:
return "key is too long (max 256 chars)"
case AttrKeyInvalidChars:
return "key contains invalid character (only 'A''Z', '0''9', or '_' allowed)"
default:
return "???"
}
}