-
Notifications
You must be signed in to change notification settings - Fork 304
Support reading configurations from files #8338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c512b78
dc449e0
6d72f81
92c81fd
635ba8a
d5bf963
9f03e04
06d572d
a03562c
ac7b387
908a72d
abfc789
38355fe
aebebbe
90b52e9
cdd8df8
1fed1da
9f2b252
2da99f2
ae6036b
e3d6c80
a7bf5ba
0c8ef6a
049da8b
39fa0e2
53dec92
96881d0
09e22a7
519c443
9a519e1
a9f968f
7c93f15
36a7e8a
9598e11
bf9efad
a34a546
a3be88d
99cb07b
cf99c4f
3d1a1d8
41fd3bc
9dd51fe
f143632
ea8d9f7
4366cab
eb7618b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package datadog.trace.bootstrap.config.provider; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Paths; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Stream; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class StableConfigParser { | ||
private static final Logger log = LoggerFactory.getLogger(StableConfigParser.class); | ||
// Match config_id:<value> | ||
private static final Pattern idPattern = Pattern.compile("^config_id\\s*:(.*)$"); | ||
// Match 'apm_configuration_default:' | ||
private static final Pattern apmConfigPattern = Pattern.compile("^apm_configuration_default:$"); | ||
// Match indented (2 spaces) key-value pairs, either with double quotes or without | ||
private static final Pattern keyValPattern = | ||
Pattern.compile("^\\s{2}([^:]+):\\s*(\"[^\"]*\"|[^\"\\n]*)$");; | ||
|
||
public static StableConfigSource.StableConfig parse(String filePath) throws IOException { | ||
File file = new File(filePath); | ||
if (!file.exists()) { | ||
log.debug("Stable configuration file not available at specified path: {}", file); | ||
return StableConfigSource.StableConfig.EMPTY; | ||
} | ||
Map<String, String> configMap = new HashMap<>(); | ||
String[] configId = new String[1]; | ||
try (Stream<String> lines = Files.lines(Paths.get(filePath))) { | ||
mtoffl01 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
int apmConfigNotFound = -1, apmConfigStarted = 0, apmConfigComplete = 1; | ||
int[] apmConfigFound = {apmConfigNotFound}; | ||
lines.forEach( | ||
line -> { | ||
Matcher matcher = idPattern.matcher(line); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there only one configId per file? If so then we can store this in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there expected to only be one config_id per file? — Theoretically yes, but neither the spec nor the tests specify how to handle multiple the scenario where multiple config_ids are present. I'm reaching out to the channel now to see if we want to standardize on this behavior. |
||
if (matcher.find()) { | ||
// Do not allow duplicate config_id keys | ||
if (configId[0] != null) { | ||
throw new RuntimeException("Duplicate config_id keys found; file may be malformed"); | ||
} | ||
configId[0] = trimQuotes(matcher.group(1).trim()); | ||
return; // go to next line | ||
} | ||
// TODO: Do not allow duplicate apm_configuration_default keys; and/or return early once | ||
// apmConfigFound[0] == apmConfigComplete | ||
if (apmConfigFound[0] == apmConfigNotFound | ||
&& apmConfigPattern.matcher(line).matches()) { | ||
apmConfigFound[0] = apmConfigStarted; | ||
return; // go to next line | ||
} | ||
if (apmConfigFound[0] == apmConfigStarted) { | ||
Matcher keyValueMatcher = keyValPattern.matcher(line); | ||
if (keyValueMatcher.matches()) { | ||
configMap.put( | ||
keyValueMatcher.group(1).trim(), | ||
trimQuotes(keyValueMatcher.group(2).trim())); // Store key-value pair in map | ||
} else { | ||
// If we encounter a non-indented or non-key-value line, stop processing | ||
apmConfigFound[0] = apmConfigComplete; | ||
} | ||
} | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a shame that the Java 8 stream API doesn't have the It's possible to mimic those with a custom but TBH I think the approach taken here is fine given the limited API available to us in Java 8 |
||
return new StableConfigSource.StableConfig(configId[0], configMap); | ||
} | ||
} | ||
|
||
private static String trimQuotes(String value) { | ||
if (value.length() > 1 && (value.startsWith("'") && value.endsWith("'")) | ||
|| (value.startsWith("\"") && value.endsWith("\""))) { | ||
return value.substring(1, value.length() - 1); | ||
mtoffl01 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
return value; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package datadog.trace.bootstrap.config.provider; | ||
|
||
import static datadog.trace.util.Strings.propertyNameToEnvironmentVariableName; | ||
|
||
import datadog.trace.api.ConfigOrigin; | ||
import java.util.Collections; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public final class StableConfigSource extends ConfigProvider.Source { | ||
private static final Logger log = LoggerFactory.getLogger(StableConfigSource.class); | ||
|
||
public static final String USER_STABLE_CONFIG_PATH = | ||
"/etc/datadog-agent/application_monitoring.yaml"; | ||
public static final String MANAGED_STABLE_CONFIG_PATH = | ||
"/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml"; | ||
public static final StableConfigSource USER = | ||
new StableConfigSource(USER_STABLE_CONFIG_PATH, ConfigOrigin.USER_STABLE_CONFIG); | ||
public static final StableConfigSource MANAGED = | ||
new StableConfigSource( | ||
StableConfigSource.MANAGED_STABLE_CONFIG_PATH, ConfigOrigin.MANAGED_STABLE_CONFIG); | ||
|
||
private final ConfigOrigin fileOrigin; | ||
|
||
private final StableConfig config; | ||
|
||
StableConfigSource(String file, ConfigOrigin origin) { | ||
this.fileOrigin = origin; | ||
StableConfig cfg; | ||
try { | ||
cfg = StableConfigParser.parse(file); | ||
} catch (Throwable e) { | ||
log.debug("Stable configuration file not readable at specified path: {}", file); | ||
cfg = StableConfig.EMPTY; | ||
} | ||
this.config = cfg; | ||
} | ||
|
||
@Override | ||
public String get(String key) { | ||
if (this.config == StableConfig.EMPTY) { | ||
return null; | ||
} | ||
return this.config.get(propertyNameToEnvironmentVariableName(key)); | ||
mtoffl01 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
@Override | ||
public ConfigOrigin origin() { | ||
return fileOrigin; | ||
} | ||
|
||
public Set<String> getKeys() { | ||
return this.config.getKeys(); | ||
} | ||
|
||
public String getConfigId() { | ||
return this.config.getConfigId(); | ||
} | ||
|
||
public static class StableConfig { | ||
public static final StableConfig EMPTY = new StableConfig(null, Collections.emptyMap()); | ||
private final Map<String, String> apmConfiguration; | ||
private final String configId; | ||
|
||
StableConfig(String configId, Map<String, String> configMap) { | ||
this.configId = configId; | ||
this.apmConfiguration = configMap; | ||
} | ||
|
||
public String get(String key) { | ||
return this.apmConfiguration.get(key); | ||
} | ||
|
||
public Set<String> getKeys() { | ||
return this.apmConfiguration.keySet(); | ||
} | ||
|
||
public String getConfigId() { | ||
return this.configId; | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.