Files
akvorado/outlet/flow/root.go
Vincent Bernat cb92fc7199 outlet/flow: persist decoders' state
Currently, for NetFlow, persist data/options templates and options. This
should allow the outlet to restart without loosing any message.

Fix #2100
2025-11-18 21:13:51 +01:00

89 lines
2.1 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
// Package flow handles flow decoding from protobuf messages.
package flow
import (
"time"
"akvorado/common/pb"
"akvorado/common/reporter"
"akvorado/outlet/flow/decoder"
)
// Component represents the flow decoder component.
type Component struct {
r *reporter.Reporter
d *Dependencies
config Configuration
errLogger reporter.Logger
metrics struct {
decoderStats *reporter.CounterVec
decoderErrors *reporter.CounterVec
}
// Available decoders
decoders map[pb.RawFlow_Decoder]decoder.Decoder
}
// Dependencies are the dependencies of the flow component.
type Dependencies = decoder.Dependencies
// New creates a new flow component.
func New(r *reporter.Reporter, config Configuration, dependencies Dependencies) (*Component, error) {
c := Component{
r: r,
d: &dependencies,
config: config,
errLogger: r.Sample(reporter.BurstSampler(30*time.Second, 3)),
decoders: make(map[pb.RawFlow_Decoder]decoder.Decoder),
}
// Initialize available decoders
for decoderType, decoderFunc := range availableDecoders {
c.decoders[decoderType] = decoderFunc(r, dependencies)
}
// Metrics
c.metrics.decoderStats = c.r.CounterVec(
reporter.CounterOpts{
Name: "decoder_flows_total",
Help: "Decoder processed count.",
},
[]string{"name"},
)
c.metrics.decoderErrors = c.r.CounterVec(
reporter.CounterOpts{
Name: "decoder_errors_total",
Help: "Decoder processed error count.",
},
[]string{"name"},
)
return &c, nil
}
// Start starts the flow component.
func (c *Component) Start() error {
if c.config.StatePersistFile != "" {
if err := c.RestoreState(c.config.StatePersistFile); err != nil {
c.r.Warn().Err(err).Msg("cannot load decoders' state, ignoring")
} else {
c.r.Info().Msg("previous decoders' state loaded")
}
}
return nil
}
// Stop stops the flow component
func (c *Component) Stop() error {
if c.config.StatePersistFile != "" {
if err := c.SaveState(c.config.StatePersistFile); err != nil {
c.r.Err(err).Msg("cannot save decorders' state")
}
}
return nil
}