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

Add option to configure GCP logging extension's logging target #455

Merged
merged 3 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.LogHandlerBuildItem;
import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem;

public class LoggingBuildSteps {

private static final String FEATURE = "google-cloud-logging";
private static final String QUARKUS_CONSOLE_LOGGING_CONFIG_KEY = "quarkus.log.console.enable";

@BuildStep
public FeatureBuildItem feature() {
Expand All @@ -38,4 +40,15 @@ public UnremovableBeanBuildItem helperClasses() {
public LogHandlerBuildItem handler(LoggingConfiguration config, LoggingHandlerFactory factory) {
return new LogHandlerBuildItem(factory.create(config));
}

@BuildStep
public RunTimeConfigurationDefaultBuildItem configurationDefaultBuildItem(LoggingConfiguration config) {
boolean enableConsoleLogging = true;
// We should use configuration only if the GCP logging extension is enabled
if (config.enabled) {
enableConsoleLogging = config.enableConsoleLogging;
}
return new RunTimeConfigurationDefaultBuildItem(QUARKUS_CONSOLE_LOGGING_CONFIG_KEY,
Boolean.toString(enableConsoleLogging));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Map;
import java.util.Optional;

import com.google.cloud.logging.LoggingHandler.LogTarget;
import com.google.cloud.logging.Severity;
import com.google.cloud.logging.Synchronicity;

Expand All @@ -11,7 +12,7 @@
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;

@ConfigRoot(name = "google.cloud.logging", phase = ConfigPhase.RUN_TIME)
@ConfigRoot(name = "google.cloud.logging", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
public class LoggingConfiguration {

/**
Expand All @@ -26,6 +27,12 @@ public class LoggingConfiguration {
@ConfigItem(defaultValue = "true")
public boolean enabled;

/**
* Enable or disable default Quarkus console logging.
*/
@ConfigItem
public boolean enableConsoleLogging;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This config property is not used anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it is used, inside LoggingBuildSteps, where we configure if we want to disable Quarkus console logging

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes but it is not used in runtime code so it seems useless, the logTarget is enough IMHO

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is not useless because it disables console logging with which we avoid duplicated logs. This GCP extension is currently registering another log handler, which causes us to have 2 logging handlers and 2 log outputs. With this option, we have the option to disable this by default so that user does not have to disable them manually (but they still have the option to keep console logging if they want).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Just understood what you did!

If someone want to disable console login, he can use the quarkus.log.console.enable property, I don't see the point of providing another config property that will set this one for him.

Copy link
Contributor Author

@zanmagerl zanmagerl Jun 28, 2023

Choose a reason for hiding this comment

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

Sure I just thought it would be nice to have this disabled by default, but ok. Maybe would be beneficial to put this somewhere in the docs so users are not confused if they get doubled logs :)


/**
* Configure base formatting to be either plain text or
* structured json. Allowed values: TEXT|JSON
Expand Down Expand Up @@ -74,6 +81,14 @@ public class LoggingConfiguration {
@ConfigItem
public StructuredConfig structured;

/**
* Configures if logs should be written to stdout or stderr instead of using Google Cloud Operations API.
* Useful if app is deployed to managed Google Cloud Platform environment with installed logger agent.
* Possible values: STDOUT, STDERR and CLOUD_LOGGING.
*/
@ConfigItem(defaultValue = "CLOUD_LOGGING")
public LogTarget logTarget;
loicmathieu marked this conversation as resolved.
Show resolved Hide resolved

@ConfigGroup
public static class StructuredConfig {

Expand Down Expand Up @@ -198,4 +213,5 @@ public enum LogFormat {
TEXT,
JSON
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,20 @@ public void doPublish(ExtLogRecord record) {
TraceInfo trace = traceExtractor.extract(record);
LogEntry logEntry = transform(record, trace);
if (logEntry != null) {
l.write(ImmutableList.of(logEntry), defaultWriteOptions);
switch (config.logTarget) {
case STDOUT:
System.out.println(logEntry.toStructuredJsonString());
break;
case STDERR:
System.err.println(logEntry.toStructuredJsonString());
break;
case CLOUD_LOGGING:
l.write(ImmutableList.of(logEntry), defaultWriteOptions);
break;
}
}
} catch (Exception ex) {
getErrorManager().error("Failed to publish record to GCP", ex, ErrorManager.WRITE_FAILURE);
getErrorManager().error("Failed to write logs", ex, ErrorManager.WRITE_FAILURE);
}
}

Expand Down Expand Up @@ -138,7 +148,7 @@ private void initDefaultWriteOptions() {
private MonitoredResource createMonitoredResource() {
MonitoredResource.Builder b = MonitoredResource.newBuilder(this.config.resource.type);
if (this.config.resource.label != null) {
this.config.resource.label.forEach((k, v) -> b.addLabel(k, v));
this.config.resource.label.forEach(b::addLabel);
}
return b.build();
}
Expand Down