Skip to content
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

[GP-4275] Add logging level to logging infrastructure #1308

Merged
merged 1 commit into from
Jun 27, 2024
Merged
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
2 changes: 2 additions & 0 deletions changes/add_logging-level.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Logging level for Definer log infrastructure (eg Loki plugin)

12 changes: 11 additions & 1 deletion docs/plugin-loki.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@ ending `.loki` with the following:
"url": "http://your.loki.server/loki/api/v1/push",
"labels": {
"environment": "foo"
}
},
"level": INFO
}

The `"url"` property is the URL of the Loki server to push logs into. The
optional `"labels"` object will apply static labels to all values logged from
this instance.

The `"level"` property is one of:
1. FATAL
2. ERROR
3. WARN
4. INFO
5. DEBUG

All messages at or above the setting in severity will be logged to Loki.

## For Plugin Developers
The PluginManager passes each `PluginFileType` an implementation of `Definer` which has
a method `log(String, Map<String,String>)`. If the Loki plugin is installed, then the PluginManager will route log
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import ca.on.oicr.gsi.prometheus.LatencyHistogram;
import ca.on.oicr.gsi.shesmu.cromwell.WorkflowIdAndStatus;
import ca.on.oicr.gsi.shesmu.plugin.Definer;
import ca.on.oicr.gsi.shesmu.plugin.FrontEndIcon;
import ca.on.oicr.gsi.shesmu.plugin.MultiPartBodyPublisher;
import ca.on.oicr.gsi.shesmu.plugin.Utils;
import ca.on.oicr.gsi.shesmu.plugin.*;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionCommand;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionCommand.Preference;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionServices;
Expand Down Expand Up @@ -373,7 +370,7 @@ private void showError(HttpResponse<?> response, URI url)
final List<String> errors = new ArrayList<>();
final Map<String, String> labels = new TreeMap<>();
labels.put("url", url.getHost());
owner.log("HTTP error: " + response.statusCode(), labels);
owner.log("HTTP error: " + response.statusCode(), LogLevel.ERROR, labels);
errors.add("HTTP error: " + response.statusCode());
this.errors = errors;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ca.on.oicr.gsi.shesmu.jira;

import ca.on.oicr.gsi.shesmu.plugin.Definer;
import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionState;
import java.io.IOException;
import java.net.URISyntaxException;
Expand Down Expand Up @@ -61,7 +62,8 @@ public ActionState perform(
Map<String, String> lokiLabels = new HashMap<>();
lokiLabels.put("issue", issue.getKey());
lokiLabels.put("verb", "close");
((Definer<JiraConnection>) definer).log(errorBuilder.toString(), lokiLabels);
((Definer<JiraConnection>) definer)
.log(errorBuilder.toString(), LogLevel.ERROR, lokiLabels);
return ActionState.FAILED;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ca.on.oicr.gsi.shesmu.jira.Issue.Field;
import ca.on.oicr.gsi.shesmu.plugin.Definer;
import ca.on.oicr.gsi.shesmu.plugin.FrontEndIcon;
import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import ca.on.oicr.gsi.shesmu.plugin.Tuple;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionState;
import ca.on.oicr.gsi.shesmu.plugin.action.ShesmuAction;
Expand Down Expand Up @@ -456,7 +457,8 @@ boolean transition(
.append(transitionResult.body());
Map<String, String> lokiLabels = new HashMap<>();
lokiLabels.put("issue", issue.getKey());
((Definer<JiraConnection>) definer).log(errorBuilder.toString(), lokiLabels);
((Definer<JiraConnection>) definer)
.log(errorBuilder.toString(), LogLevel.ERROR, lokiLabels);
return false;
} else {
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ca.on.oicr.gsi.shesmu.loki;

import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.util.Map;

Expand All @@ -8,6 +9,7 @@
public class Configuration {
private Map<String, String> labels = Map.of();
private String url;
private LogLevel level;

public Map<String, String> getLabels() {
return labels;
Expand All @@ -24,4 +26,12 @@ public void setLabels(Map<String, String> labels) {
public void setUrl(String url) {
this.url = url;
}

public LogLevel getLevel() {
return level;
}

public void setLevel(LogLevel level) {
this.level = level;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ca.on.oicr.gsi.Pair;
import ca.on.oicr.gsi.prometheus.LatencyHistogram;
import ca.on.oicr.gsi.shesmu.plugin.Definer;
import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import ca.on.oicr.gsi.shesmu.plugin.json.JsonPluginFile;
import ca.on.oicr.gsi.status.SectionRenderer;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -58,6 +59,7 @@ public void configuration(SectionRenderer renderer) {
configuration.ifPresent(
configuration -> {
renderer.link("Instance", configuration.getUrl(), configuration.getUrl());
renderer.line("Level", configuration.getLevel().toString());
for (final var entry : configuration.getLabels().entrySet()) {
renderer.line("Label: " + entry.getKey(), entry.getValue());
}
Expand Down Expand Up @@ -160,9 +162,10 @@ protected synchronized Optional<Integer> update(Configuration configuration) {
}

@Override
public synchronized void writeLog(String message, Map<String, String> attributes) {
public synchronized void writeLog(
String message, LogLevel level, Map<String, String> attributes) {
final var now = Instant.now();
buffer.computeIfAbsent(attributes, k -> new ArrayList<>()).add(new Pair<>(now, message));
flush(now);
if (level.compareTo(this.configuration.get().getLevel()) >= 0) flush(now);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ca.on.oicr.gsi.prometheus.LatencyHistogram;
import ca.on.oicr.gsi.shesmu.plugin.AlgebraicValue;
import ca.on.oicr.gsi.shesmu.plugin.Definer;
import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import ca.on.oicr.gsi.shesmu.plugin.Tuple;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionState;
import ca.on.oicr.gsi.shesmu.plugin.action.ShesmuAction;
Expand Down Expand Up @@ -176,7 +177,7 @@ public Thread drainOutput(
labels.put("type", "refiller");
labels.put("stream", stream);
final var errorDrainThread =
new Thread(() -> errorReader.lines().forEach(l -> definer.log(l, labels)));
new Thread(() -> errorReader.lines().forEach(l -> definer.log(l, LogLevel.ERROR, labels)));
errorDrainThread.start();
return errorDrainThread;
}
Expand Down Expand Up @@ -314,7 +315,7 @@ public boolean refill(String name, String command, ArrayNode data) {
labels.put("command", command);
labels.put("name", name);
labels.put("type", "refiller");
definer.log("Expected OK or UPDATE, but got no output", labels);
definer.log("Expected OK or UPDATE, but got no output", LogLevel.ERROR, labels);
} else {
switch (response) {
case "UPDATE":
Expand Down Expand Up @@ -355,7 +356,10 @@ public boolean refill(String name, String command, ArrayNode data) {
labels.put("command", command);
labels.put("name", name);
labels.put("type", "refiller");
definer.log("Expected OK or UPDATE, but got invalid response: " + response, labels);
definer.log(
"Expected OK or UPDATE, but got invalid response: " + response,
LogLevel.ERROR,
labels);
break;
}
}
Expand Down Expand Up @@ -509,7 +513,7 @@ protected Optional<Object> fetch(Tuple key, Instant lastUpdated) throws Exceptio
labels.put("command", command);
labels.put("name", name);
labels.put("type", "function");
errorReader.lines().forEach(l -> definer.log(l, labels));
errorReader.lines().forEach(l -> definer.log(l, LogLevel.ERROR, labels));
process.join();
if (process.getExitStatus() == null || process.getExitStatus() != 0) {
return Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,5 +296,5 @@ <R> String defineStaticSigner(
* @param message the log message to write
* @param labels the labels associated with this message
*/
void log(String message, Map<String, String> labels);
void log(String message, LogLevel level, Map<String, String> labels);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ca.on.oicr.gsi.shesmu.plugin;

public enum LogLevel {
DEBUG,
INFO,
WARN,
ERROR,
FATAL
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,10 @@ public void stop() {}
* service. To write logs, use {@link Definer#log(String, Map)}
*
* @param message the log message to write
* @param level the logging level of this message
* @param attributes the labels associated with this message
*/
public void writeLog(String message, Map<String, String> attributes) {
public void writeLog(String message, LogLevel level, Map<String, String> attributes) {
// Do nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ public void writeJavaScriptRenderer(PrintStream writer) {}
* service. To write logs, use {@link Definer#log(String, Map)}
*
* @param message the log message to write
* @param level the logging level of this message
* @param attributes the labels associated with this message
*/
public void writeLog(String message, Map<String, String> attributes) {
public void writeLog(String message, LogLevel level, Map<String, String> attributes) {
// Do nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import ca.on.oicr.gsi.shesmu.core.StandardDefinitions;
import ca.on.oicr.gsi.shesmu.plugin.ErrorableStream;
import ca.on.oicr.gsi.shesmu.plugin.FrontEndIcon;
import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import ca.on.oicr.gsi.shesmu.plugin.SourceLocation;
import ca.on.oicr.gsi.shesmu.plugin.action.Action;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionCommand.Preference;
Expand Down Expand Up @@ -3137,7 +3138,7 @@ public void start() {
processor.start(executor, compiler);
System.out.println("Starting scheduler...");
master.start(executor);
pluginManager.log("Shesmu started.", Map.of());
pluginManager.log("Shesmu started.", LogLevel.INFO, Map.of());
}

private <L, V> void storeEntries(ObjectNode entries, LabelledKeyValueCache<?, ?, ?> cache) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ca.on.oicr.gsi.prometheus.LatencyHistogram;
import ca.on.oicr.gsi.shesmu.Server;
import ca.on.oicr.gsi.shesmu.core.input.shesmu.ShesmuIntrospectionValue;
import ca.on.oicr.gsi.shesmu.plugin.LogLevel;
import ca.on.oicr.gsi.shesmu.plugin.SourceLocation;
import ca.on.oicr.gsi.shesmu.plugin.SourceLocation.SourceLocationLinker;
import ca.on.oicr.gsi.shesmu.plugin.Utils;
Expand Down Expand Up @@ -769,7 +770,8 @@ public CommandStatistics command(
@Override
public Boolean accepted() {
labels.put("command", c.command());
pluginManager.log("Performed command", labels);
pluginManager.log(
"Performed command", LogLevel.INFO, labels);
return true;
}

Expand All @@ -787,7 +789,8 @@ public Boolean murder(Filter filter) {
@Override
public Boolean purge() {
labels.put("command", c.command());
pluginManager.log("Performed command", labels);
pluginManager.log(
"Performed command", LogLevel.INFO, labels);
purge.add(e.getKey());
stateCount
.labels(
Expand All @@ -800,7 +803,8 @@ public Boolean purge() {
@Override
public Boolean reset() {
labels.put("command", c.command());
pluginManager.log("Performed command", labels);
pluginManager.log(
"Performed command", LogLevel.INFO, labels);
if (e.getValue().lastState != ActionState.UNKNOWN) {
stateCount
.labels(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,8 @@
import ca.on.oicr.gsi.shesmu.compiler.definitions.SignatureDefinition;
import ca.on.oicr.gsi.shesmu.compiler.definitions.SignatureVariableForDynamicSigner;
import ca.on.oicr.gsi.shesmu.compiler.definitions.SignatureVariableForStaticSigner;
import ca.on.oicr.gsi.shesmu.plugin.Definer;
import ca.on.oicr.gsi.shesmu.plugin.ErrorableStream;
import ca.on.oicr.gsi.shesmu.plugin.Parser;
import ca.on.oicr.gsi.shesmu.plugin.PluginFile;
import ca.on.oicr.gsi.shesmu.plugin.PluginFileType;
import ca.on.oicr.gsi.shesmu.plugin.RequiredServices;
import ca.on.oicr.gsi.shesmu.plugin.*;
import ca.on.oicr.gsi.shesmu.plugin.SourceLocation.SourceLocationLinker;
import ca.on.oicr.gsi.shesmu.plugin.SupplementaryInformation;
import ca.on.oicr.gsi.shesmu.plugin.Utils;
import ca.on.oicr.gsi.shesmu.plugin.action.Action;
import ca.on.oicr.gsi.shesmu.plugin.action.ActionState;
import ca.on.oicr.gsi.shesmu.plugin.action.CustomActionParameter;
Expand Down Expand Up @@ -851,11 +844,11 @@ public Stream<String> isOverloaded(Set<String> services) {
}

@Override
public void log(String message, Map<String, String> labels) {
public void log(String message, LogLevel level, Map<String, String> labels) {
final Map<String, String> amendedLabels = new TreeMap<>(labels);
amendedLabels.put("plugin", instance.fileName().toString());
amendedLabels.put("plugin_type", FormatTypeWrapper.this.fileFormat.getClass().toString());
PluginManager.this.log(message, amendedLabels);
PluginManager.this.log(message, level, amendedLabels);
}

public Stream<RefillerDefinition> refillers() {
Expand Down Expand Up @@ -1210,12 +1203,12 @@ public final Stream<ConfigurationSection> listConfiguration() {
return configuration.stream().map(FileWrapper::configuration);
}

public void log(String message, Map<String, String> attributes) {
fileFormat.writeLog(message, attributes);
public void log(String message, LogLevel level, Map<String, String> attributes) {
fileFormat.writeLog(message, level, attributes);
for (final var reference : this.wrappers.values()) {
final var wrapper = reference.get();
if (wrapper != null) {
wrapper.instance.writeLog(message, attributes);
wrapper.instance.writeLog(message, level, attributes);
}
}
}
Expand Down Expand Up @@ -2051,14 +2044,14 @@ public Stream<ConfigurationSection> listConfiguration() {
return formatTypes.stream().flatMap(FormatTypeWrapper::listConfiguration);
}

public void log(String message, Map<String, String> attributes) {
public void log(String message, LogLevel level, Map<String, String> attributes) {
if (LOG_REENTRANT_CHECK.get()) {
throw new IllegalStateException("Trying to log while logging.");
}
LOG_REENTRANT_CHECK.set(true);
try {
for (final var format : this.formatTypes) {
format.log(message, attributes);
format.log(message, level, attributes);
}
} finally {
LOG_REENTRANT_CHECK.set(false);
Expand Down
Loading