mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-20 14:11:11 +02:00
Fixes #1563 This implements dmesg reading via `/dev/kmsg`, with message parsing and formatting. Kernel log facility and severity are parsed, timestamp is calculated relative to boot time (it's accurate unless time jumps a lot during node lifetime). New flags to follow dmesg was added, tail flag allows to stream only new message (ignoring old messages). We could try to implement tailing last N messages, just a bit more work, open to suggestions (for symmetry with regular logs). Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
100 lines
1.8 KiB
Go
100 lines
1.8 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package kmsg_test
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/talos-systems/talos/internal/pkg/kmsg"
|
|
)
|
|
|
|
func skipIfNoKmsg(t *testing.T) {
|
|
f, err := os.OpenFile("/dev/kmsg", os.O_RDONLY, 0)
|
|
if err != nil {
|
|
t.Skip("/dev/kmsg is not available", err.Error())
|
|
}
|
|
|
|
f.Close() //nolint: errcheck
|
|
}
|
|
|
|
func TestReaderNoFollow(t *testing.T) {
|
|
skipIfNoKmsg(t)
|
|
|
|
r, err := kmsg.NewReader()
|
|
assert.NoError(t, err)
|
|
|
|
defer r.Close() //nolint: errcheck
|
|
|
|
messageCount := 0
|
|
|
|
for packet := range r.Scan(context.Background()) {
|
|
assert.NoError(t, packet.Err)
|
|
|
|
messageCount++
|
|
}
|
|
|
|
assert.Greater(t, messageCount, 0)
|
|
|
|
assert.NoError(t, r.Close())
|
|
}
|
|
|
|
func TestReaderFollow(t *testing.T) {
|
|
testReaderFollow(t, true)
|
|
}
|
|
|
|
func TestReaderFollowTail(t *testing.T) {
|
|
testReaderFollow(t, false, kmsg.FromTail())
|
|
}
|
|
|
|
func testReaderFollow(t *testing.T, expectMessages bool, options ...kmsg.Option) {
|
|
skipIfNoKmsg(t)
|
|
|
|
r, err := kmsg.NewReader(append([]kmsg.Option{kmsg.Follow()}, options...)...)
|
|
assert.NoError(t, err)
|
|
|
|
defer r.Close() //nolint: errcheck
|
|
|
|
messageCount := 0
|
|
|
|
ctx, ctxCancel := context.WithCancel(context.Background())
|
|
defer ctxCancel()
|
|
|
|
ch := r.Scan(ctx)
|
|
|
|
var closed bool
|
|
|
|
LOOP:
|
|
for {
|
|
select {
|
|
case packet, ok := <-ch:
|
|
if !ok {
|
|
if !closed {
|
|
assert.Fail(t, "channel closed before cancel")
|
|
}
|
|
|
|
break LOOP
|
|
}
|
|
|
|
assert.NoError(t, packet.Err)
|
|
|
|
messageCount++
|
|
case <-time.After(100 * time.Millisecond):
|
|
// abort
|
|
closed = true
|
|
ctxCancel()
|
|
assert.NoError(t, r.Close())
|
|
}
|
|
}
|
|
|
|
if expectMessages {
|
|
assert.Greater(t, messageCount, 0)
|
|
}
|
|
}
|