Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
18 changes: 18 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ type AgentConfig struct {
// Ignored if "logformat" is not "structured".
StructuredLogMessageKey string `toml:"structured_log_message_key"`

// When set to true and using logformat = "structured", the tags of each
// input plugin are added to the log output as a "tags" JSON field.
StructuredLogAddInputTags bool `toml:"structured_log_add_input_tags"`

// The file will be rotated after the time interval specified. When set
// to 0 no time based rotation is performed.
LogfileRotationInterval Duration `toml:"logfile_rotation_interval"`
Expand Down Expand Up @@ -570,6 +574,19 @@ func (c *Config) LoadAll(configFiles ...string) error {
}
}

// When loading multiple config files (e.g. via --config-directory), the
// [agent] section may be parsed after some input files, meaning
// buildInput saw StructuredLogAddInputTags=false and skipped the logger
// attribute. Therefore, it needs to be parsed again after loading all configs.
if c.Agent.StructuredLogAddInputTags {
for _, input := range c.Inputs {
if !input.Config.AddTagsToStructuredLogs && len(input.Config.Tags) > 0 {
input.Config.AddTagsToStructuredLogs = true
input.Log().AddAttribute("tags", input.Config.Tags)
}
}
}

// Sort the processors according to their `order` setting while
// using a stable sort to keep the file loading / file position order.
sort.Stable(c.Processors)
Expand Down Expand Up @@ -1690,6 +1707,7 @@ func (c *Config) buildInput(name, source string, tbl *ast.Table) (*models.InputC
Source: source,
AlwaysIncludeLocalTags: c.Agent.AlwaysIncludeLocalTags,
AlwaysIncludeGlobalTags: c.Agent.AlwaysIncludeGlobalTags,
AddTagsToStructuredLogs: c.Agent.StructuredLogAddInputTags,
}
cp.Interval, _ = c.getFieldDuration(tbl, "interval")
cp.Precision, _ = c.getFieldDuration(tbl, "precision")
Expand Down
22 changes: 22 additions & 0 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,28 @@ The agent table configures Telegraf and the defaults used across all plugins.
Message key for structured logs, to override the default of "msg".
Ignored if `logformat` is not "structured".

- **structured_log_add_input_tags**:
To add input configuration tags to the log output.
Example:

```json
{
"time":"2026-03-27T09:14:36.078389805Z",
"level":"INFO",
"msg":"Error connecting to target. Restarting in 10s...",
"category":"inputs",
"plugin":"execd",
"tags":{
"server_host":"10.0.1.20",
"friendly_name":"friendly_server_name",
"log_source":"telegraf",
"metric_type":"logs"
}
}
Comment on lines +319 to +331
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{
"time":"2026-03-27T09:14:36.078389805Z",
"level":"INFO",
"msg":"Error connecting to target. Restarting in 10s...",
"category":"inputs",
"plugin":"execd",
"tags":{
"server_host":"10.0.1.20",
"friendly_name":"friendly_server_name",
"log_source":"telegraf",
"metric_type":"logs"
}
}
{
"time":"2026-03-27T09:14:36.078389805Z",
"level":"INFO",
"msg":"Error connecting to target. Restarting in 10s...",
"category":"inputs",
"plugin":"execd",
"tags":{
"server_host":"10.0.1.20",
"friendly_name":"friendly_server_name",
"log_source":"telegraf",
"metric_type":"logs"
}
}

```

Ignored if `logformat` is not "structured".

- **logfile**:
Name of the file to be logged to or stderr if unset or empty. This
setting is ignored for the "eventlog" format.
Expand Down
7 changes: 7 additions & 0 deletions models/running_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ func NewRunningInput(input telegraf.Input, config *InputConfig) *RunningInput {
if err := logger.SetLogLevel(config.LogLevel); err != nil {
logger.Error(err)
}
if config.AddTagsToStructuredLogs && len(config.Tags) > 0 {
logger.AddAttribute("tags", config.Tags)
}
SetLoggerOnPlugin(input, logger)
SetStatisticsOnPlugin(input, logger, tags)

Expand Down Expand Up @@ -110,6 +113,10 @@ type InputConfig struct {
Filter Filter
AlwaysIncludeLocalTags bool
AlwaysIncludeGlobalTags bool

// When true and using logformat = "structured", the input's tags are
// added to the log output as a "tags" JSON field.
AddTagsToStructuredLogs bool
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means it is configurable per input? Then it needs to be documented in the Input Plugins section of CONFIGURATION.md as well.

}

func (*RunningInput) metricFiltered(metric telegraf.Metric) {
Expand Down
Loading