Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
579cb92
Fix log level does not change when standalone agent is reloaded
khushijain21 Dec 23, 2025
c02b59d
add comment
khushijain21 Dec 23, 2025
b9b5448
remove log flag
khushijain21 Dec 23, 2025
f36ff2c
Merge branch 'main' into loglevel
khushijain21 Dec 23, 2025
01400fa
Merge branch 'main' into loglevel
khushijain21 Dec 24, 2025
d3fc592
add changelog
khushijain21 Dec 24, 2025
984062a
add comments
khushijain21 Dec 24, 2025
36e34a1
address first three review comments
khushijain21 Dec 30, 2025
2e2e480
Merge branch 'main' into loglevel
khushijain21 Dec 30, 2025
4488ba0
fix test
khushijain21 Dec 30, 2025
73979ce
add standalone check
khushijain21 Dec 30, 2025
c3318a7
pass local log
khushijain21 Dec 30, 2025
e316032
add log level to otel manager struct
khushijain21 Dec 30, 2025
bb0ab3d
fix ci
khushijain21 Dec 30, 2025
e84bcee
address review comments
khushijain21 Dec 31, 2025
3ebcca8
add comment
khushijain21 Dec 31, 2025
b080fec
Merge branch 'main' into loglevel
khushijain21 Dec 31, 2025
ceb7cdb
fix ci
khushijain21 Dec 31, 2025
d511efc
address review comments
khushijain21 Jan 1, 2026
267f104
Merge branch 'main' into loglevel
khushijain21 Jan 1, 2026
5765ff1
fix ci
khushijain21 Jan 1, 2026
f200cd4
add integration test
khushijain21 Jan 2, 2026
1c4b57f
add back build tag
khushijain21 Jan 2, 2026
9b3f032
Merge branch 'main' into loglevel
khushijain21 Jan 2, 2026
0833da4
add comment
khushijain21 Jan 2, 2026
de36b8d
fix ci
khushijain21 Jan 2, 2026
d26711d
fix ci
khushijain21 Jan 2, 2026
6044a3e
fix ci
khushijain21 Jan 2, 2026
eeca2e6
avoid any timing issue and fix ci
khushijain21 Jan 3, 2026
4316f41
address review comments
khushijain21 Jan 6, 2026
a711fd5
Merge branch 'main' into loglevel
khushijain21 Jan 6, 2026
992db44
use log statement
khushijain21 Jan 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions internal/pkg/agent/application/coordinator/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,22 @@ func (c *Coordinator) processConfigAgent(ctx context.Context, cfg *config.Config
}
c.currentCfg = currentCfg

// check if log level has changed in standalone agent config
Comment thread
khushijain21 marked this conversation as resolved.
Outdated
ll := currentCfg.Settings.LoggingConfig.Level
if ll != c.state.LogLevel {
// set log level for the coordinator
c.setLogLevel(ll)
// set global log level
logger.SetLevel(ll)
// set agent log level.
// this is used by other parts of the agent to report the log level eg. otel manager
err = c.agentInfo.SetLogLevel(ctx, ll.String())
if err != nil {
c.logger.Errorf("failed to set agent log level: %v", err)
}
c.logger.Infof("log level changed to %s", ll.String())
}

if c.vars != nil {
Comment thread
khushijain21 marked this conversation as resolved.
return c.refreshComponentModel(ctx)
}
Expand Down Expand Up @@ -1801,10 +1817,13 @@ func (c *Coordinator) processVars(ctx context.Context, vars []*transpiler.Vars)

// Called on the main Coordinator goroutine.
func (c *Coordinator) processLogLevel(ctx context.Context, ll logp.Level) {
c.setLogLevel(ll)
err := c.refreshComponentModel(ctx)
if err != nil {
c.logger.Errorf("updating log level: %s", err.Error())
// do not refresh component model if log level did not change
if c.state.LogLevel != ll {
c.setLogLevel(ll)
err := c.refreshComponentModel(ctx)
if err != nil {
c.logger.Errorf("updating log level: %s", err.Error())
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/otel/manager/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type collectorExecution interface {
// - errCh: Process exit errors are sent to the errCh channel
// - statusCh: Collector's status updates are sent to statusCh channel.
// - forceFetchStatusCh: Channel that is used to trigger a forced status update.
startCollector(ctx context.Context, baseLogger *logger.Logger, logger *logger.Logger, cfg *confmap.Conf, errCh chan error, statusCh chan *status.AggregateStatus, forceFetchStatusCh chan struct{}) (collectorHandle, error)
startCollector(ctx context.Context, logLevel string, baseLogger *logger.Logger, logger *logger.Logger, cfg *confmap.Conf, errCh chan error, statusCh chan *status.AggregateStatus, forceFetchStatusCh chan struct{}) (collectorHandle, error)
}

type collectorHandle interface {
Expand Down
35 changes: 32 additions & 3 deletions internal/pkg/otel/manager/execution_subprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ func newSubprocessExecution(logLevel logp.Level, collectorPath string, uuid stri
collectorPath: collectorPath,
collectorArgs: []string{
fmt.Sprintf("--%s", OtelSetSupervisedFlagName),
fmt.Sprintf("--%s=%s", OtelSupervisedLoggingLevelFlagName, logLevel.String()),
Comment thread
khushijain21 marked this conversation as resolved.
fmt.Sprintf("--%s=%s", OtelSupervisedMonitoringURLFlagName, monitoring.EDOTMonitoringEndpoint()),
},
logLevel: logLevel,
Expand All @@ -62,6 +61,7 @@ func newSubprocessExecution(logLevel logp.Level, collectorPath string, uuid stri
}, nil
}

// subprocessExecution implements collectorExecution by running the collector in a subprocess.
type subprocessExecution struct {
collectorPath string
collectorArgs []string
Expand All @@ -74,7 +74,20 @@ type subprocessExecution struct {

// startCollector starts a supervised collector and monitors its health. Process exit errors are sent to the
// processErrCh channel. Other run errors, such as not able to connect to the health endpoint, are sent to the runErrCh channel.
func (r *subprocessExecution) startCollector(ctx context.Context, baseLogger *logger.Logger, logger *logger.Logger, cfg *confmap.Conf, processErrCh chan error, statusCh chan *status.AggregateStatus, forceFetchStatusCh chan struct{}) (collectorHandle, error) {
func (r *subprocessExecution) startCollector(
ctx context.Context,
logLevel string,
baseLogger *logger.Logger,
logger *logger.Logger,
cfg *confmap.Conf,
processErrCh chan error,
statusCh chan *status.AggregateStatus,
forceFetchStatusCh chan struct{},
) (collectorHandle, error) {
if err := r.setLogLevelFromString(logLevel); err != nil {
Comment thread
khushijain21 marked this conversation as resolved.
Outdated
return nil, fmt.Errorf("failed to set log level for otel collector: %w", err)
}

if cfg == nil {
// configuration is required
return nil, errors.New("no configuration provided")
Expand Down Expand Up @@ -115,8 +128,12 @@ func (r *subprocessExecution) startCollector(ctx context.Context, baseLogger *lo
env := os.Environ()
// Set the environment variable for the collector metrics port. See comment at the constant definition for more information.
env = append(env, fmt.Sprintf("%s=%d", componentmonitoring.OtelCollectorMetricsPortEnvVarName, collectorMetricsPort))

// set collector args
collectorArgs := append(r.collectorArgs, fmt.Sprintf("--%s=%s", OtelSupervisedLoggingLevelFlagName, r.logLevel.String()))

processInfo, err := process.Start(r.collectorPath,
process.WithArgs(r.collectorArgs),
process.WithArgs(collectorArgs),
process.WithEnv(env),
process.WithCmdOptions(func(c *exec.Cmd) error {
c.Stdin = bytes.NewReader(confBytes)
Expand Down Expand Up @@ -241,6 +258,18 @@ func (r *subprocessExecution) startCollector(ctx context.Context, baseLogger *lo
return ctl, nil
}

func (r *subprocessExecution) setLogLevelFromString(logLevel string) error {
var lvl logp.Level
err := lvl.Unpack(logLevel)
if err != nil {
return fmt.Errorf("invalid log level '%s': %w", logLevel, err)
}
if r.logLevel != lvl {
r.logLevel = lvl
}
return nil
}

// cloneCollectorStatus creates a deep copy of the provided AggregateStatus.
func cloneCollectorStatus(aStatus *status.AggregateStatus) *status.AggregateStatus {
if aStatus == nil {
Expand Down
13 changes: 10 additions & 3 deletions internal/pkg/otel/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ func (m *OTelManager) Run(ctx context.Context) error {

newRetries := m.recoveryRetries.Add(1)
m.logger.Infof("collector recovery restarting, total retries: %d", newRetries)
m.proc, err = m.execution.startCollector(ctx, m.baseLogger, m.logger, m.mergedCollectorCfg, m.collectorRunErr, collectorStatusCh, forceFetchStatusCh)
m.proc, err = m.execution.startCollector(ctx, m.agentInfo.LogLevel(), m.baseLogger, m.logger, m.mergedCollectorCfg, m.collectorRunErr, collectorStatusCh, forceFetchStatusCh)
if err != nil {
// report a startup error (this gets reported as status)
m.reportStartupErr(ctx, err)
Expand Down Expand Up @@ -253,7 +253,7 @@ func (m *OTelManager) Run(ctx context.Context) error {

// in this rare case the collector stopped running but a configuration was
// provided and the collector stopped with a clean exit
m.proc, err = m.execution.startCollector(ctx, m.baseLogger, m.logger, m.mergedCollectorCfg, m.collectorRunErr, collectorStatusCh, forceFetchStatusCh)
m.proc, err = m.execution.startCollector(ctx, m.agentInfo.LogLevel(), m.baseLogger, m.logger, m.mergedCollectorCfg, m.collectorRunErr, collectorStatusCh, forceFetchStatusCh)
if err != nil {
// report a startup error (this gets reported as status)
m.reportStartupErr(ctx, err)
Expand Down Expand Up @@ -368,6 +368,13 @@ func buildMergedConfig(
if err != nil {
return nil, fmt.Errorf("failed to generate otel config: %w", err)
}

// get log level from agent info
Comment thread
khushijain21 marked this conversation as resolved.
Outdated
level := translate.GetOTelLogLevel(agentInfo.LogLevel())
Comment thread
khushijain21 marked this conversation as resolved.
Outdated
if err := componentOtelCfg.Merge(confmap.NewFromStringMap(map[string]any{"service::telemetry::logs::level": level})); err != nil {
Comment thread
cmacknz marked this conversation as resolved.
return nil, fmt.Errorf("failed to set log level in otel config: %w", err)
}

}

// If both configs are nil, return nil so the manager knows to stop the collector
Expand Down Expand Up @@ -451,7 +458,7 @@ func (m *OTelManager) applyMergedConfig(ctx context.Context, collectorStatusCh c
} else {
// either a new configuration or the first configuration
// that results in the collector being started
proc, err := m.execution.startCollector(ctx, m.baseLogger, m.logger, m.mergedCollectorCfg, collectorRunErr, collectorStatusCh, forceFetchStatusCh)
proc, err := m.execution.startCollector(ctx, m.agentInfo.LogLevel(), m.baseLogger, m.logger, m.mergedCollectorCfg, collectorRunErr, collectorStatusCh, forceFetchStatusCh)
if err != nil {
// failed to create the collector (this is different then
// it's failing to run). we do not retry creation on failure
Expand Down
5 changes: 3 additions & 2 deletions internal/pkg/otel/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ type testExecution struct {
handle collectorHandle
}

func (e *testExecution) startCollector(ctx context.Context, baseLogger *logger.Logger, logger *logger.Logger, cfg *confmap.Conf, errCh chan error, statusCh chan *status.AggregateStatus, forceFetchStatusCh chan struct{}) (collectorHandle, error) {
func (e *testExecution) startCollector(ctx context.Context, level string, baseLogger *logger.Logger, logger *logger.Logger, cfg *confmap.Conf, errCh chan error, statusCh chan *status.AggregateStatus, forceFetchStatusCh chan struct{}) (collectorHandle, error) {
e.mtx.Lock()
defer e.mtx.Unlock()

var err error
e.handle, err = e.exec.startCollector(ctx, baseLogger, logger, cfg, errCh, statusCh, forceFetchStatusCh)
e.handle, err = e.exec.startCollector(ctx, "info", baseLogger, logger, cfg, errCh, statusCh, forceFetchStatusCh)
return e.handle, err
}

Expand All @@ -118,6 +118,7 @@ type mockExecution struct {

func (e *mockExecution) startCollector(
ctx context.Context,
level string,
_ *logger.Logger,
_ *logger.Logger,
cfg *confmap.Conf,
Expand Down
18 changes: 18 additions & 0 deletions internal/pkg/otel/translate/otelconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,24 @@ func GetOtelConfig(
return otelConfig, nil
}

func GetOTelLogLevel(level string) string {
if level != "" {
switch strings.ToLower(level) {
case "debug":
return "DEBUG"
case "info":
return "INFO"
case "warning":
return "WARN"
case "error":
return "ERROR"
default:
return "INFO"
}
}
return "INFO"
}

// VerifyComponentIsOtelSupported verifies that the given component can be run in an Otel Collector. It returns an error
// indicating what the problem is, if it can't.
func VerifyComponentIsOtelSupported(comp *component.Component) error {
Expand Down
Loading