v1.0.8: Add configurable log level and immediate service stop
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled

- Add log_level config option (debug, info, warn, error)
- Add JA4SENTINEL_LOG_LEVEL environment variable support
- Set TimeoutStopSec=2 for immediate stop on restart/stop
- Consolidate config files into single example (config.yml.example)
- Update RPM changelog

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
Jacquin Antoine
2026-03-01 02:51:11 +01:00
parent d89c90dc03
commit fd162982d9
8 changed files with 57 additions and 56 deletions

View File

@ -35,7 +35,7 @@ COPY . .
# Build binary for Linux
# Binary will be dynamically linked but compatible with all RHEL-based distros
ARG VERSION=1.0.7
ARG VERSION=1.0.8
ARG BUILD_TIME=""
ARG GIT_COMMIT=""
RUN mkdir -p dist && \
@ -53,7 +53,7 @@ FROM rockylinux:9 AS rpm-builder
WORKDIR /package
# VERSION must be redeclared for each stage that needs it
ARG VERSION=1.0.7
ARG VERSION=1.0.8
# Install rpm-build tools (Rocky Linux 9)
RUN dnf install -y \
@ -72,7 +72,7 @@ COPY packaging/rpm/ja4sentinel.spec /root/rpmbuild/SPECS/ja4sentinel.spec
# Copy binary from Go builder and other files to SOURCES
COPY --from=builder /build/dist/ja4sentinel /root/rpmbuild/SOURCES/ja4sentinel
COPY packaging/systemd/ja4sentinel.service /root/rpmbuild/SOURCES/ja4sentinel.service
COPY packaging/systemd/config.yml /root/rpmbuild/SOURCES/config.yml
COPY config.yml.example /root/rpmbuild/SOURCES/config.yml
# Set permissions
RUN chmod 755 /root/rpmbuild/SOURCES/ja4sentinel && \

View File

@ -23,6 +23,7 @@ type Config struct {
BPFFilter string `json:"bpf_filter,omitempty"`
FlowTimeoutSec int `json:"flow_timeout_sec,omitempty"` // Timeout for TLS handshake extraction (default: 30)
PacketBufferSize int `json:"packet_buffer_size,omitempty"` // Buffer size for packet channel (default: 1000)
LogLevel string `json:"log_level,omitempty"` // Log level: debug, info, warn, error (default: info)
}
// IPMeta contains IP metadata for stack fingerprinting
@ -241,6 +242,7 @@ const (
DefaultBPFFilter = ""
DefaultFlowTimeout = 30 // seconds
DefaultPacketBuffer = 1000 // packet channel buffer size
DefaultLogLevel = "info"
)
// DefaultConfig returns an AppConfig with sensible default values.
@ -256,6 +258,7 @@ func DefaultConfig() AppConfig {
BPFFilter: DefaultBPFFilter,
FlowTimeoutSec: DefaultFlowTimeout,
PacketBufferSize: DefaultPacketBuffer,
LogLevel: DefaultLogLevel,
},
Outputs: []OutputConfig{},
}

View File

@ -22,7 +22,7 @@ import (
var (
// Version information (set via ldflags)
Version = "1.0.7"
Version = "1.0.8"
BuildTime = "unknown"
GitCommit = "unknown"
)
@ -38,9 +38,22 @@ func main() {
os.Exit(0)
}
// Create logger factory
// Load configuration
cfgLoader := config.NewLoader(*configPath)
appConfig, err := cfgLoader.Load()
if err != nil {
// Create logger with default level for error reporting
loggerFactory := &logging.LoggerFactory{}
appLogger := loggerFactory.NewDefaultLogger()
appLogger.Error("main", "Failed to load configuration", map[string]string{
"error": err.Error(),
})
os.Exit(1)
}
// Create logger factory with configured log level
loggerFactory := &logging.LoggerFactory{}
appLogger := loggerFactory.NewLogger(appConfig.Core.LogLevel)
appLogger.Info("main", "Starting ja4sentinel", map[string]string{
"version": Version,
@ -48,19 +61,10 @@ func main() {
"git_commit": GitCommit,
})
// Load configuration
cfgLoader := config.NewLoader(*configPath)
appConfig, err := cfgLoader.Load()
if err != nil {
appLogger.Error("main", "Failed to load configuration", map[string]string{
"error": err.Error(),
})
os.Exit(1)
}
appLogger.Info("main", "Configuration loaded", map[string]string{
"interface": appConfig.Core.Interface,
"listen_ports": formatPorts(appConfig.Core.ListenPorts),
"log_level": appConfig.Core.LogLevel,
})
// Create context with cancellation for graceful shutdown

View File

@ -19,6 +19,10 @@ core:
# Buffer size for packet channel (default: 1000, increase for high-traffic environments)
packet_buffer_size: 1000
# Log level: debug, info, warn, error (default: info)
# Can be overridden by JA4SENTINEL_LOG_LEVEL environment variable
log_level: info
outputs:
# Output to stdout (JSON lines)
- type: stdout

View File

@ -104,6 +104,11 @@ func (l *LoaderImpl) loadFromEnv(config api.AppConfig) api.AppConfig {
}
}
// JA4SENTINEL_LOG_LEVEL
if val := os.Getenv("JA4SENTINEL_LOG_LEVEL"); val != "" {
config.Core.LogLevel = val
}
return config
}
@ -166,6 +171,10 @@ func mergeConfigs(base, override api.AppConfig) api.AppConfig {
result.Core.PacketBufferSize = override.Core.PacketBufferSize
}
if override.Core.LogLevel != "" {
result.Core.LogLevel = override.Core.LogLevel
}
if len(override.Outputs) > 0 {
result.Outputs = override.Outputs
}
@ -196,6 +205,19 @@ func (l *LoaderImpl) validate(config api.AppConfig) error {
return fmt.Errorf("packet_buffer_size must be between 1 and 1000000")
}
// Validate log level
validLogLevels := map[string]struct{}{
"debug": {},
"info": {},
"warn": {},
"error": {},
}
if config.Core.LogLevel != "" {
if _, ok := validLogLevels[config.Core.LogLevel]; !ok {
return fmt.Errorf("log_level must be one of: debug, info, warn, error")
}
}
allowedTypes := map[string]struct{}{
"stdout": {},
"file": {},

View File

@ -3,7 +3,7 @@
%if %{defined build_version}
%define spec_version %{build_version}
%else
%define spec_version 1.0.7
%define spec_version 1.0.8
%endif
Name: ja4sentinel
@ -117,6 +117,12 @@ fi
%dir /var/run/logcorrelator
%changelog
* Sun Mar 01 2026 Jacquin Antoine <rpm@arkel.fr> - 1.0.8-1
- Add configurable log level (debug, info, warn, error) via config.yml
- Add JA4SENTINEL_LOG_LEVEL environment variable support
- Set TimeoutStopSec=2 for immediate service stop on restart/stop
- Consolidate config files into single example (config.yml.example)
* Sat Feb 28 2026 Jacquin Antoine <rpm@arkel.fr> - 1.0.4-1
- Add systemd sdnotify support (READY, WATCHDOG, STOPPING signals)
- Enable systemd watchdog with 30s timeout

View File

@ -1,39 +0,0 @@
# Default configuration file for ja4sentinel
# This file is installed as /etc/ja4sentinel/config.yml.default
core:
# Network interface to capture traffic from
# Will be overridden by JA4SENTINEL_INTERFACE env var if set
interface: eth0
# TCP ports to monitor for TLS handshakes
listen_ports:
- 443
- 8443
# Optional BPF filter (leave empty for auto-generated filter based on listen_ports)
bpf_filter: ""
# Timeout in seconds for TLS handshake extraction (default: 30)
flow_timeout_sec: 30
# Buffer size for packet channel (default: 1000, increase for high-traffic environments)
packet_buffer_size: 1000
outputs:
# Output to stdout (JSON lines) - disabled by default for production
- type: stdout
enabled: false
params: {}
# Output to file
- type: file
enabled: true
params:
path: /var/log/ja4sentinel/ja4.log
# Output to UNIX socket (for systemd/journald or other consumers)
- type: unix_socket
enabled: true
params:
socket_path: /var/run/ja4sentinel.sock

View File

@ -13,6 +13,7 @@ ExecStart=/usr/bin/ja4sentinel --config /etc/ja4sentinel/config.yml
Restart=on-failure
RestartSec=5
WatchdogSec=30
TimeoutStopSec=2
NotifyAccess=main
Environment=JA4SENTINEL_LOG_LEVEL=info