Skip to content

Commit e94af89

Browse files
authored
Define file configuration file format and env var substitution (#3744)
Part of incorporating [OTEP #225](open-telemetry/oteps#225) into the specification. Followup to #3437. The adds the YAML file format, and leaves an open TODO for the JSON format discussed in the original OTEP. It also define environment variable substitution. IMO its necessary to define environment variable substitution at the same time as file format because they interact in ways that aren't immediately obvious and need to be prototyped. The opentelemetry-java implementation of file configuration already accepts YAML encoding and performs environment variable substitution as described in this PR. It does not support JSON, and I don't think we should unless there is good reason. I omitted the JSON file format because I don't know of any prototypes that permit it. We should add JSON once a language implements it and explores how environment variable substitution works with JSON.
1 parent 3d60131 commit e94af89

File tree

1 file changed

+101
-6
lines changed

1 file changed

+101
-6
lines changed

specification/configuration/file-configuration.md

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ linkTitle: File
1212
- [Configuration Model](#configuration-model)
1313
* [Stability Definition](#stability-definition)
1414
- [Configuration file](#configuration-file)
15+
* [YAML file format](#yaml-file-format)
16+
* [Environment variable substitution](#environment-variable-substitution)
1517
- [SDK Configuration](#sdk-configuration)
1618
* [In-Memory Configuration Model](#in-memory-configuration-model)
1719
* [Operations](#operations)
@@ -46,12 +48,86 @@ TODO: define stability guarantees and backwards compatibility
4648

4749
## Configuration file
4850

49-
A configuration file is a file representation of
51+
A configuration file is a serialized file-based representation of
5052
the [Configuration Model](#configuration-model).
5153

52-
TODO: define acceptable file formats
54+
Configuration files SHOULD use one the following serialization formats:
5355

54-
TODO: define environment variable substitution
56+
### YAML file format
57+
58+
[YAML](https://yaml.org/spec/1.2.2/) configuration files SHOULD follow YAML spec
59+
revision >= 1.2.
60+
61+
YAML configuration files MUST use file extensions `.yaml` or `.yml`.
62+
63+
TODO: decide if JSON file format is required
64+
65+
### Environment variable substitution
66+
67+
Configuration files support environment variables substitution for references
68+
which match the following regular expression:
69+
70+
```regexp
71+
\$\{(?<ENV_NAME>[a-zA-Z_][a-zA-Z0-9_]*)}
72+
```
73+
74+
The `ENV_NAME` MUST start with an alphabetic or `_` character, and is followed
75+
by 0 or more alphanumeric or `_` characters.
76+
77+
For example, `${API_KEY}` is valid, while `${1API_KEY}` and `${API_$KEY}` are
78+
invalid.
79+
80+
Environment variable substitution MUST only apply to scalar values. Mapping keys
81+
are not candidates for substitution.
82+
83+
If a referenced environment variable is not defined, it MUST be replaced with an
84+
empty value.
85+
86+
Node types MUST be interpreted after environment variable substitution takes
87+
place. This ensures the environment string representation of boolean, integer,
88+
or floating point fields can be properly converted to expected types.
89+
90+
It MUST NOT be possible to inject YAML structures by environment variables. For
91+
example, references to `INVALID_MAP_VALUE` environment variable below.
92+
93+
For example, consider the following environment variables,
94+
and [YAML](#yaml-file-format) configuration file:
95+
96+
```shell
97+
export STRING_VALUE="value"
98+
export BOOl_VALUE="true"
99+
export INT_VALUE="1"
100+
export FLOAT_VALUE="1.1"
101+
export INVALID_MAP_VALUE"value\nkey:value" # An invalid attempt to inject a map key into the YAML
102+
```
103+
104+
```yaml
105+
string_key: ${STRING_VALUE} # Valid reference to STRING_VALUE
106+
other_string_key: "${STRING_VALUE}" # Valid reference to STRING_VALUE inside double quotes
107+
another_string_key: "${BOOl_VALUE}" # Valid reference to BOOl_VALUE inside double quotes
108+
yet_another_string_key: ${INVALID_MAP_VALUE} # Valid reference to INVALID_MAP_VALUE, but YAML structure from INVALID_MAP_VALUE MUST NOT be injected
109+
bool_key: ${BOOl_VALUE} # Valid reference to BOOl_VALUE
110+
int_key: ${INT_VALUE} # Valid reference to INT_VALUE
111+
float_key: ${FLOAT_VALUE} # Valid reference to FLOAT_VALUE
112+
combo_string_key: foo ${STRING_VALUE} ${FLOAT_VALUE} # Valid reference to STRING_VALUE and FLOAT_VALUE
113+
undefined_key: ${UNDEFINED_KEY} # Invalid reference, UNDEFINED_KEY is not defined and is replaced with ""
114+
${STRING_VALUE}: value # Invalid reference, substitution is not valid in mapping keys and reference is ignored
115+
```
116+
117+
Environment variable substitution results in the following YAML:
118+
119+
```yaml
120+
string_key: value # Interpreted as type string, tag URI tag:yaml.org,2002:str
121+
other_string_key: "value" # Interpreted as type string, tag URI tag:yaml.org,2002:str
122+
another_string_key: "true" # Interpreted as type string, tag URI tag:yaml.org,2002:str
123+
yet_another_string_key: "value\nkey:value" # Interpreted as type string, tag URI tag:yaml.org,2002:str
124+
bool_key: true # Interpreted as type bool, tag URI tag:yaml.org,2002:bool
125+
int_key: 1 # Interpreted as type int, tag URI tag:yaml.org,2002:int
126+
float_key: 1.1 # Interpreted as type float, tag URI tag:yaml.org,2002:float
127+
combo_string_key: foo value 1.1 # Interpreted as type string, tag URI tag:yaml.org,2002:str
128+
undefined_key: # Interpreted as type null, tag URI tag:yaml.org,2002:null
129+
${STRING_VALUE}: value # Interpreted as type string, tag URI tag:yaml.org,2002:str
130+
```
55131
56132
## SDK Configuration
57133
@@ -81,10 +157,19 @@ with OpAmp
81157

82158
Parse and validate a [configuration file](#configuration-file).
83159

160+
Parse MUST perform [environment variable substitution](#environment-variable-substitution).
161+
162+
Parse MUST interpret null as equivalent to unset.
163+
84164
**Parameters:**
85165

86166
* `file`: The [configuration file](#configuration-file) to parse. This MAY be a
87167
file path, or language specific file data structure, or a stream of a file's content.
168+
* `file_format`: The file format of the `file` (e.g. [yaml](#yaml-file-format)).
169+
Implementations MAY accept a `file_format` parameter, or infer it from
170+
the `file` extension, or include file format specific overloads of `parse`,
171+
e.g. `parseYaml(file)`. If `parse` accepts `file_format`, the API SHOULD be
172+
structured so a user is obligated to provide it.
88173

89174
**Returns:** [configuration model](#in-memory-configuration-model)
90175

@@ -94,12 +179,19 @@ This SHOULD return an error if:
94179
* The parsed `file` content does not conform to
95180
the [configuration model](#configuration-model) schema.
96181

97-
TODO: define behavior if some portion of configuration model is not supported
98-
99182
#### Create
100183

101184
Interpret [configuration model](#in-memory-configuration-model) and return SDK components.
102185

186+
If a field is null or unset and a default value is defined, Create MUST ensure
187+
the SDK component is configured with the default value. If a field is null or
188+
unset and no default value is defined, Create SHOULD return an error. For
189+
example, if configuring
190+
the [span batching processor](../trace/sdk.md#batching-processor) and
191+
the `scheduleDelayMillis` field is null or unset, the component is configured
192+
with the default value of `5000`. However, if the `exporter` field is null or
193+
unset, Create fails fast since there is no default value for `exporter`.
194+
103195
**Parameters:**
104196

105197
* `configuration` - The configuration model.
@@ -115,7 +207,10 @@ The multiple responses MAY be returned using a tuple, or some other data
115207
structure encapsulating the components.
116208

117209
This SHOULD return an error if it encounters an error in `configuration` (i.e.
118-
fail fast).
210+
fail fast) in accordance with
211+
initialization [error handling principles](../error-handling.md#basic-error-handling-principles).
212+
213+
TODO: define behavior if some portion of configuration model is not supported
119214

120215
## References
121216

0 commit comments

Comments
 (0)