Skip to content

Commit

Permalink
Merge pull request #2 from arianvp/restructure-things
Browse files Browse the repository at this point in the history
Restructure things a bit
  • Loading branch information
arianvp authored Jul 12, 2024
2 parents 10f6112 + 3037531 commit fd20db1
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 46 deletions.
45 changes: 2 additions & 43 deletions journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,10 @@ import (
"bytes"
"context"
"encoding/binary"
"fmt"
"io"
"log/slog"
"net"
"os"
"runtime"
"strconv"
"syscall"
)

type Priority int
Expand Down Expand Up @@ -80,49 +76,12 @@ func NewHandler(opts *Options) (*Handler, error) {
h.opts.Level = slog.LevelInfo
}

// The "net" library in Go really wants me to either Dial or Listen a UnixConn,
// which would respectively bind() an address or connect() to a remote address,
// but we want neither. We want to create a datagram socket and write to it directly
// and not worry about reconnecting or rebinding.
// so jumping through some hoops here
fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
w, err := newJournalWriter(h.opts.Addr)
if err != nil {
return nil, err
}

if err := syscall.SetNonblock(fd, true); err != nil {
return nil, err
}

f := os.NewFile(uintptr(fd), "journal")
defer f.Close()

fconn, err := net.FileConn(f)
if err != nil {
return nil, err
}
conn, ok := fconn.(*net.UnixConn)
if !ok {
return nil, fmt.Errorf("expected *net.UnixConn, got %T", fconn)
}

if err := conn.SetWriteBuffer(sndBufSize); err != nil {
return nil, err
}

if h.opts.Addr == "" {
h.opts.Addr = "/run/systemd/journal/socket"
}
addr := &net.UnixAddr{
Name: h.opts.Addr,
Net: "unixgram",
}

h.w = &journalWriter{
conn: conn,
addr: addr,
}

h.w = w
h.preformatted = new(bytes.Buffer)
h.prefix = ""

Expand Down
2 changes: 2 additions & 0 deletions journal_linux_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux

package slogjournal

import (
Expand Down
1 change: 0 additions & 1 deletion journal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ func TestSlogtest(t *testing.T) {
if err != nil {
t.Fatal(err)
}
t.Log(kv)
for k, v := range kv {

groups := strings.Split(k, "_")
Expand Down
50 changes: 48 additions & 2 deletions journal_writer.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package slogjournal

import (
"fmt"
"io"
"net"
"os"
Expand All @@ -15,6 +16,51 @@ type journalWriter struct {
conn *net.UnixConn
}

func newJournalWriter(path string) (*journalWriter, error) {
if path == "" {
path = "/run/systemd/journal/socket"
}
// The "net" library in Go really wants me to either Dial or Listen a UnixConn,
// which would respectively bind() an address or connect() to a remote address,
// but we want neither. We want to create a datagram socket and write to it directly
// and not worry about reconnecting or rebinding.
// so jumping through some hoops here
fd, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
if err != nil {
return nil, err
}

if err := syscall.SetNonblock(fd, true); err != nil {
return nil, err
}

f := os.NewFile(uintptr(fd), "journal")
defer f.Close()

fconn, err := net.FileConn(f)
if err != nil {
return nil, err
}
conn, ok := fconn.(*net.UnixConn)
if !ok {
return nil, fmt.Errorf("expected *net.UnixConn, got %T", fconn)
}

if err := conn.SetWriteBuffer(sndBufSize); err != nil {
return nil, err
}

addr := &net.UnixAddr{
Name: path,
Net: "unixgram",
}

return &journalWriter{
addr: addr,
conn: conn,
}, nil
}

// Write implements io.Writer.
// If the message is too large, it will write the message to a temporary file and send the file descriptor as OOB data.
func (j *journalWriter) Write(p []byte) (n int, err error) {
Expand Down Expand Up @@ -50,8 +96,8 @@ func (j *journalWriter) Write(p []byte) (n int, err error) {
return n, err
}
fd := int(file.Fd())
if n, _, err := j.conn.WriteMsgUnix([]byte{}, syscall.UnixRights(fd), j.addr); err != nil {
return n, err
if _, _, err := j.conn.WriteMsgUnix([]byte{}, syscall.UnixRights(fd), j.addr); err != nil {
return 0, err
}
return n, err
}
Expand Down
12 changes: 12 additions & 0 deletions journal_writer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package slogjournal

import (
"testing"
)

func TestJournalWriter(t *testing.T) {
_, err := newJournalWriter("")
if err != nil {
t.Fatal(err)
}
}

0 comments on commit fd20db1

Please sign in to comment.