feat: add error callback for file output writer
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
- Add FileWriterOption type and WithFileErrorCallback option - Add reportError method to FileWriter for error reporting - Update Builder to propagate error callback to file writers - File write errors now logged via the same callback mechanism - Helps diagnose permission or disk space issues Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -68,6 +68,19 @@ type FileWriter struct {
|
||||
maxSize int64
|
||||
maxBackups int
|
||||
currentSize int64
|
||||
errorCallback ErrorCallback
|
||||
failuresMu sync.Mutex
|
||||
failures int
|
||||
}
|
||||
|
||||
// FileWriterOption is a function type for configuring FileWriter
|
||||
type FileWriterOption func(*FileWriter)
|
||||
|
||||
// WithFileErrorCallback sets an error callback for file write errors
|
||||
func WithFileErrorCallback(cb ErrorCallback) FileWriterOption {
|
||||
return func(w *FileWriter) {
|
||||
w.errorCallback = cb
|
||||
}
|
||||
}
|
||||
|
||||
// NewFileWriter creates a new file writer with rotation
|
||||
@ -76,7 +89,7 @@ func NewFileWriter(path string) (*FileWriter, error) {
|
||||
}
|
||||
|
||||
// NewFileWriterWithConfig creates a new file writer with custom rotation config
|
||||
func NewFileWriterWithConfig(path string, maxSize int64, maxBackups int) (*FileWriter, error) {
|
||||
func NewFileWriterWithConfig(path string, maxSize int64, maxBackups int, opts ...FileWriterOption) (*FileWriter, error) {
|
||||
// Create directory if it doesn't exist
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
@ -96,14 +109,21 @@ func NewFileWriterWithConfig(path string, maxSize int64, maxBackups int) (*FileW
|
||||
return nil, fmt.Errorf("failed to stat file: %w", err)
|
||||
}
|
||||
|
||||
return &FileWriter{
|
||||
w := &FileWriter{
|
||||
file: file,
|
||||
encoder: json.NewEncoder(file),
|
||||
path: path,
|
||||
maxSize: maxSize,
|
||||
maxBackups: maxBackups,
|
||||
currentSize: info.Size(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Apply options (for error callback)
|
||||
for _, opt := range opts {
|
||||
opt(w)
|
||||
}
|
||||
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// rotate rotates the log file if it exceeds the max size
|
||||
@ -149,6 +169,7 @@ func (w *FileWriter) Write(rec api.LogRecord) error {
|
||||
// Check if rotation is needed
|
||||
if w.currentSize >= w.maxSize {
|
||||
if err := w.rotate(); err != nil {
|
||||
w.reportError(fmt.Errorf("failed to rotate file: %w", err))
|
||||
return fmt.Errorf("failed to rotate file: %w", err)
|
||||
}
|
||||
}
|
||||
@ -163,6 +184,7 @@ func (w *FileWriter) Write(rec api.LogRecord) error {
|
||||
// Write to file
|
||||
n, err := w.file.Write(data)
|
||||
if err != nil {
|
||||
w.reportError(fmt.Errorf("failed to write to file: %w", err))
|
||||
return fmt.Errorf("failed to write to file: %w", err)
|
||||
}
|
||||
w.currentSize += int64(n)
|
||||
@ -170,6 +192,17 @@ func (w *FileWriter) Write(rec api.LogRecord) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// reportError reports a file write error via the configured callback
|
||||
func (w *FileWriter) reportError(err error) {
|
||||
if w.errorCallback != nil {
|
||||
w.failuresMu.Lock()
|
||||
w.failures++
|
||||
failures := w.failures
|
||||
w.failuresMu.Unlock()
|
||||
w.errorCallback(w.path, err, failures)
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the file
|
||||
func (w *FileWriter) Close() error {
|
||||
w.mutex.Lock()
|
||||
@ -531,7 +564,7 @@ func NewBuilder() *BuilderImpl {
|
||||
return &BuilderImpl{}
|
||||
}
|
||||
|
||||
// WithErrorCallback sets an error callback for all unix_socket writers created by this builder
|
||||
// WithErrorCallback sets an error callback for all unix_socket and file writers created by this builder
|
||||
func (b *BuilderImpl) WithErrorCallback(cb ErrorCallback) *BuilderImpl {
|
||||
b.errorCallback = cb
|
||||
return b
|
||||
@ -564,7 +597,12 @@ func (b *BuilderImpl) NewFromConfig(cfg api.AppConfig) (api.Writer, error) {
|
||||
if path == "" {
|
||||
return nil, fmt.Errorf("file output requires 'path' parameter")
|
||||
}
|
||||
writer, err = NewFileWriter(path)
|
||||
// Build options list for file writer
|
||||
var fileOpts []FileWriterOption
|
||||
if b.errorCallback != nil {
|
||||
fileOpts = append(fileOpts, WithFileErrorCallback(b.errorCallback))
|
||||
}
|
||||
writer, err = NewFileWriterWithConfig(path, DefaultMaxFileSize, DefaultMaxBackups, fileOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user