GitHub
09/29/2026, 8:39 PMfile log sink, osctrl-tls 0.5.9 never writes anything to the configured file. The file is not even created. The sink's exports_count and bytes_sent counters still increase, so it looks healthy from the UI.
In pkg/logging/file.go, Status, Result and Query each build a zerolog event but never finish it with .Msg() or .Send(), so zerolog discards it:
func (logFile *LoggerFile) Status(data []byte, environment, uuid string, debug bool) {
logFile.Logger.Info().Str(
"type", types.StatusLog).Str(
"environment", environment).Str(
"uuid", uuid).RawJSON("data", data)
}
Result and Query in the same file have the same shape, so status, scheduled results and on-demand query results (routed to Query by LoggerFile.Export) are all dropped. This is unchanged on main.
Reproduce
Minimal repro, as a test in pkg/logging (fails on v0.5.9 and main):
// pkg/logging/file_test.go
package logging
import (
"os"
"path/filepath"
"testing"
"github.com/jmpsec/osctrl/pkg/config"
"github.com/jmpsec/osctrl/pkg/types"
)
func TestLoggerFileWritesStatusAndResult(t *testing.T) {
path := filepath.Join(t.TempDir(), "result.log")
lf, err := CreateLoggerFile(&config.LocalLogger{FilePath: path, MaxSize: 1})
if err != nil {
t.Fatal(err)
}
data := []byte([{"name":"q","hostIdentifier":"h"}])
lf.Log(types.StatusLog, data, "env", "uuid-1", false)
lf.Log(types.ResultLog, data, "env", "uuid-1", false)
b, err := os.ReadFile(path)
if err != nil {
t.Fatalf("file sink wrote nothing: %v", err)
}
if len(b) == 0 {
t.Fatal("file sink created an empty file")
}
}
go test ./pkg/logging/ -run TestLoggerFileWritesStatusAndResult fails with file sink wrote nothing: open .../result.log: no such file or directory. With the fix below it passes, and the rest of pkg/logging still passes.
On a running install:
1. `tls.yml`: logger.type: file, logger.local.filePath: /var/log/osctrl/result.log, types: [], alwaysLog: false.
2. Start osctrl-tls 0.5.9 and enrol one osquery 5.23.1 node.
3. Wait for status logs (or restart osqueryd on the node) and run a scheduled or on-demand query.
4. /var/log/osctrl/result.log does not exist, while the seeded file sink's exports_count in log_sinks is non-zero.
The stdout sink works for the same traffic (pkg/logging/stdout.go uses Msgf).
Fix
End each of the three events with `.Send()`:
- "uuid", uuid).RawJSON("data", data)
+ "uuid", uuid).RawJSON("data", data).Send()
(once each in Status, Result and Query). The test above could be kept as a regression test.
jmpsec/osctrlGitHub
10/01/2026, 7:44 PM