influxdata / telegraf

Agent for collecting, processing, aggregating, and writing metrics, logs, and other arbitrary data.
https://influxdata.com/telegraf
MIT License
14.63k stars 5.58k forks source link

evaluate environment variables in [processors.starlark.constants] #16029

Closed pagules closed 1 week ago

pagules commented 2 weeks ago

Use Case

[[processors.starlark]]
  script = "/etc/telegraf/telegraf.d/example/apply_metric_json.star"

  [processors.starlark.constants]
    project = "${PROJECT}"
    structure = "${STRUCTURE}" 

Expected behavior

According to the documentation, environment variables can be used anywhere in the configuration file (Use environment variables anywhere in the configuration file by enclosing them in ${}. For strings, variables must be in quotes (for example, test_${STR_VAR}). For numbers and Booleans, variables must be unquoted (for example, ${INT_VAR}, ${BOOL_VAR}))). So the values of the constants project and structure should be available in the starlark script.

Actual behavior

But this is not the case. The starlark script which I use to extract metrics from a complex JSON object returns an error, when the scripts call the decode function of the starlark json-module to decode the content of the ${STRUCTURE} variable , which should be a JSON string.
Error message:

2024-10-15T04:03:27Z E! [processors.starlark] Error in json.decode: json.decode: at offset 0, unexpected character '$' 

results in an error. Obviously the strings ${PROJECT} and ${STRUCTURE} are passed to the script instead of the variable values. Both of the variables are working as expected in other plugins of the telegraf.conf file. If I pass the constants as hard coded string literal but not as an environment variable to the starlark script, it returns extracted metrics as expected and works fine.

Additional info

The behavior was noticed in Docker version telegraf:1.31-alpine Supporting environment variables within [processors.starlark.constants] would make the use of starlark scripting much more flexible.

srebhan commented 2 weeks ago

Sorry but I cannot reproduce your issue! Using

[[inputs.mock]]
  metric_name = "mock"
  [inputs.mock.tags]
    "name" = "mocker"
  [[inputs.mock.constant]]
    name = "constant"
    value = 42

[[processors.starlark]]
  source = '''
load("logging.star", "log")

def apply(metric):
  log.debug("project:   {}".format(project))
  log.debug("structure: {}".format(structure))

  metric.tags["project"] = project
  metric.tags["structure"] = structure
  return metric
'''
  [processors.starlark.constants]
    project = "${PROJECT}"
    structure = "${STRUCTURE}"

and executing

$ PROJECT="foo" STRUCTURE="bar"  ./telegraf --config test_configs/starlark_issue_16029.conf --debug --test                                                    209ms  Wed 16 Oct 2024 01:52:52 PM CEST
2024-10-16T11:53:57Z I! Loading config: test_configs/starlark_issue_16029.conf
2024-10-16T11:53:57Z I! Starting Telegraf 1.33.0-b37b6d12 brought to you by InfluxData the makers of InfluxDB
2024-10-16T11:53:57Z I! Available plugins: 236 inputs, 9 aggregators, 33 processors, 26 parsers, 62 outputs, 6 secret-stores
2024-10-16T11:53:57Z I! Loaded inputs: mock
2024-10-16T11:53:57Z I! Loaded aggregators:
2024-10-16T11:53:57Z I! Loaded processors: starlark
2024-10-16T11:53:57Z I! Loaded secretstores:
2024-10-16T11:53:57Z W! Outputs are not used in testing mode!
2024-10-16T11:53:57Z I! Tags enabled: host=Hugin
2024-10-16T11:53:57Z D! [agent] Initializing plugins
2024-10-16T11:53:57Z D! [agent] Starting service inputs
2024-10-16T11:53:57Z D! [agent] Stopping service inputs
2024-10-16T11:53:57Z D! [agent] Input channel closed
2024-10-16T11:53:57Z D! [processors.starlark] project:   foo
2024-10-16T11:53:57Z D! [processors.starlark] structure: bar
2024-10-16T11:53:57Z D! [agent] Processor channel closed
2024-10-16T11:53:57Z D! [agent] Stopped Successfully
> mock,host=Hugin,name=mocker,project=foo,structure=bar constant=42i 1729079637000000000

replaces the env-vars as you can see...

It seems like your environment variables are not set in which case Telegraf will keep the literal.

pagules commented 1 week ago

You are right, because the ${PROJECT} variable is evaluated correctly in other places in the conf file, I totally overlooked the fact that the ${STRUCTURE} variable was not set in my container, while it was set correctly in others. I did not check this properly. Many thanks for your support.