Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ final class WriteOption extends Option {
enum OptionType implements Option.OptionType {
LOG_NAME,
RESOURCE,
LABELS;
LABELS,
LOG_DESTINATION;

@SuppressWarnings("unchecked")
<T> T get(Map<Option.OptionType, ?> options) {
Expand Down Expand Up @@ -105,6 +106,14 @@ public static WriteOption resource(MonitoredResource resource) {
public static WriteOption labels(Map<String, String> labels) {
return new WriteOption(OptionType.LABELS, ImmutableMap.copyOf(labels));
}

/**
* Returns an option to specify a log destination resource path (see {@link LogDestinationName}
* for details)
*/
public static WriteOption destination(LogDestinationName destination) {
return new WriteOption(OptionType.LOG_DESTINATION, destination);
}
}

/** Fields according to which log entries can be sorted. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
import com.google.cloud.logging.Logging.WriteOption;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -172,7 +174,7 @@ public LoggingHandler(String log, LoggingOptions options) {
* a default resource is created based on the project ID and deployment environment.
*/
public LoggingHandler(String log, LoggingOptions options, MonitoredResource monitoredResource) {
this(log, options, monitoredResource, null);
this(log, options, monitoredResource, null, null);
}

/**
Expand All @@ -190,6 +192,27 @@ public LoggingHandler(
LoggingOptions options,
MonitoredResource monitoredResource,
List<LoggingEnhancer> enhancers) {
this(log, options, monitoredResource, enhancers, null);
}

/**
* Creates a handler that publishes messages to Cloud Logging.
*
* @param log the name of the log to which log entries are written
* @param options options for the Cloud Logging service
* @param monitoredResource the monitored resource to which log entries refer. If it is null then
* a default resource is created based on the project ID and deployment environment.
* @param enhancers List of {@link LoggingEnhancer} instances used to enhance any{@link LogEntry}
* instances built by this handler.
* @param destination the log destination {@link LogDestinationName} (see 'logName' parameter in
* https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry)
*/
public LoggingHandler(
String log,
LoggingOptions options,
MonitoredResource monitoredResource,
List<LoggingEnhancer> enhancers,
LogDestinationName destination) {
try {
loggingOptions = options != null ? options : LoggingOptions.getDefaultInstance();
LoggingConfig config = new LoggingConfig(getClass().getName());
Expand All @@ -204,17 +227,20 @@ public LoggingHandler(
MonitoredResource resource =
firstNonNull(
monitoredResource, config.getMonitoredResource(loggingOptions.getProjectId()));
defaultWriteOptions =
new WriteOption[] {
WriteOption.logName(logName),
WriteOption.resource(resource),
WriteOption.labels(
ImmutableMap.of(
LEVEL_NAME_KEY,
baseLevel.getName(),
LEVEL_VALUE_KEY,
String.valueOf(baseLevel.intValue())))
};
List<WriteOption> writeOptions = new ArrayList<WriteOption>();
writeOptions.add(WriteOption.logName(logName));
writeOptions.add(WriteOption.resource(resource));
writeOptions.add(
WriteOption.labels(
ImmutableMap.of(
LEVEL_NAME_KEY,
baseLevel.getName(),
LEVEL_VALUE_KEY,
String.valueOf(baseLevel.intValue()))));
if (destination != null) {
writeOptions.add(WriteOption.destination(destination));
}
defaultWriteOptions = Iterables.toArray(writeOptions, WriteOption.class);

getLogging().setFlushSeverity(severityFor(flushLevel));
getLogging().setWriteSynchronicity(config.getSynchronicity());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static com.google.cloud.logging.Logging.ListOption.OptionType.PAGE_SIZE;
import static com.google.cloud.logging.Logging.ListOption.OptionType.PAGE_TOKEN;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.LABELS;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.LOG_DESTINATION;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.LOG_NAME;
import static com.google.cloud.logging.Logging.WriteOption.OptionType.RESOURCE;

Expand Down Expand Up @@ -738,11 +739,13 @@ private static WriteLogEntriesRequest writeLogEntriesRequest(
LoggingOptions serviceOptions,
Iterable<LogEntry> logEntries,
Map<Option.OptionType, ?> options) {
String projectId = serviceOptions.getProjectId();
WriteLogEntriesRequest.Builder builder = WriteLogEntriesRequest.newBuilder();
String logName = LOG_NAME.get(options);
String projectId = serviceOptions.getProjectId();

LogName logName = getLogName(projectId, LOG_NAME.get(options), LOG_DESTINATION.get(options));

if (logName != null) {
builder.setLogName(LogName.ofProjectLogName(projectId, logName).toString());
builder.setLogName(logName.toString());
}
MonitoredResource resource = RESOURCE.get(options);
if (resource != null) {
Expand All @@ -752,10 +755,25 @@ private static WriteLogEntriesRequest writeLogEntriesRequest(
if (labels != null) {
builder.putAllLabels(labels);
}

builder.addAllEntries(Iterables.transform(logEntries, LogEntry.toPbFunction(projectId)));
return builder.build();
}

private static LogName getLogName(
String projectId, String logName, LogDestinationName destination) {
if (logName == null) {
return null;
}

// If no destination specified, fallback to project based log name
if (destination == null) {
return LogName.ofProjectLogName(projectId, logName);
}

return destination.toLogName(logName);
}

public void write(Iterable<LogEntry> logEntries, WriteOption... options) {
if (inWriteCall.get() != null) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,28 @@ public void testPublishCustomResource() {
handler.publish(newLogRecord(Level.FINEST, MESSAGE));
}

@Test
public void testPublishCustomResourceWithFolder() {
testPublishCustomResourceWithDestination(FINEST_ENTRY, LogDestinationName.folder("folder"));
}

@Test
public void testPublishCustomResourceWithBilling() {
testPublishCustomResourceWithDestination(
FINEST_ENTRY, LogDestinationName.billingAccount("billing"));
}

@Test
public void testPublishCustomResourceWithOrganization() {
testPublishCustomResourceWithDestination(
FINEST_ENTRY, LogDestinationName.organization("organization"));
}

@Test
public void testPublishCustomResourceWithProject() {
testPublishCustomResourceWithDestination(FINEST_ENTRY, LogDestinationName.project(PROJECT));
}

@Test
public void testPublishKubernetesContainerResource() {
expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
Expand Down Expand Up @@ -582,4 +604,27 @@ public void testClose() throws Exception {
handler.close();
handler.close();
}

private void testPublishCustomResourceWithDestination(
LogEntry entry, LogDestinationName destination) {
expect(options.getProjectId()).andReturn(PROJECT).anyTimes();
expect(options.getService()).andReturn(logging);
logging.setFlushSeverity(Severity.ERROR);
expectLastCall().once();
logging.setWriteSynchronicity(Synchronicity.ASYNC);
expectLastCall().once();
MonitoredResource resource = MonitoredResource.of("custom", ImmutableMap.<String, String>of());
logging.write(
ImmutableList.of(entry),
WriteOption.logName(LOG_NAME),
WriteOption.resource(resource),
WriteOption.labels(BASE_SEVERITY_MAP),
WriteOption.destination(destination));
expectLastCall().once();
replay(options, logging);
Handler handler = new LoggingHandler(LOG_NAME, options, resource, null, destination);
handler.setLevel(Level.ALL);
handler.setFormatter(new TestFormatter());
handler.publish(newLogRecord(Level.FINEST, MESSAGE));
}
}
Loading