From 106f256e591e2c4fa36babc38b9d4e5e2ce91ee1 Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Fri, 15 Jul 2016 17:14:52 +0200 Subject: [PATCH] Add examples and snippets for Logging --- gcloud-java-examples/README.md | 13 + .../examples/logging/LoggingExample.java | 577 ++++++++++++++++++ .../snippets/CreateAndListMetrics.java | 54 ++ .../logging/snippets/CreateAndListSinks.java | 54 ++ .../snippets/WriteAndListLogEntries.java | 61 ++ gcloud-java/pom.xml | 5 + 6 files changed, 764 insertions(+) create mode 100644 gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/LoggingExample.java create mode 100644 gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListMetrics.java create mode 100644 gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListSinks.java create mode 100644 gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/WriteAndListLogEntries.java diff --git a/gcloud-java-examples/README.md b/gcloud-java-examples/README.md index 588236d8d7fe..c2d7f3417594 100644 --- a/gcloud-java-examples/README.md +++ b/gcloud-java-examples/README.md @@ -100,6 +100,19 @@ To run examples from your command line: mvn exec:java -Dexec.mainClass="com.google.cloud.examples.dns.DnsExample" -Dexec.args="delete some-sample-zone" ``` + * Here's an example run of `LoggingExample`. + + Before running the example, go to the [Google Developers Console][developers-console] to ensure + that Logging API is enabled. + ``` + target/appassembler/bin/LoggingExample create metric test-metric severity>=ERROR + target/appassembler/bin/LoggingExample list metrics + target/appassembler/bin/LoggingExample create sink test-sink bucket test-bucket severity>=ERROR + target/appassembler/bin/LoggingExample list sinks + target/appassembler/bin/LoggingExample write test-log-name ERROR test-message test-key test-value + target/appassembler/bin/LoggingExample list entries + ``` + * Here's an example run of `ResourceManagerExample`. Be sure to change the placeholder project ID "your-project-id" with your own globally unique project ID. diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/LoggingExample.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/LoggingExample.java new file mode 100644 index 000000000000..965eab30a2f0 --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/LoggingExample.java @@ -0,0 +1,577 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.examples.logging; + +import com.google.cloud.MonitoredResource; +import com.google.cloud.MonitoredResourceDescriptor; +import com.google.cloud.logging.LogEntry; +import com.google.cloud.logging.Logging; +import com.google.cloud.logging.Logging.EntryListOption; +import com.google.cloud.logging.LoggingOptions; +import com.google.cloud.logging.Metric; +import com.google.cloud.logging.MetricInfo; +import com.google.cloud.logging.Payload.StringPayload; +import com.google.cloud.logging.Severity; +import com.google.cloud.logging.Sink; +import com.google.cloud.logging.SinkInfo; +import com.google.cloud.logging.SinkInfo.Destination; +import com.google.cloud.logging.SinkInfo.Destination.BucketDestination; +import com.google.cloud.logging.SinkInfo.Destination.DatasetDestination; +import com.google.cloud.logging.SinkInfo.Destination.TopicDestination; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * An example of using Stackdriver Logging. + * + *

This example demonstrates a simple/typical Logging usage. + * + *

See the + * + * README for compilation instructions. Run this code with + *

{@code target/appassembler/bin/LoggingExample
+ *  -Dexec.args="[]
+ *  create metric  
+ *  create sink  bucket|dataset|topic  ?
+ *  list metrics
+ *  list sinks
+ *  list resource-descriptors
+ *  list entries ?
+ *  delete metric 
+ *  delete sink 
+ *  delete log 
+ *  into metric 
+ *  info sink 
+ *  write    ( )*"}
+ * + *

The first parameter is an optional {@code project_id} (logged-in project will be used if not + * supplied). Second parameter is a Logging operation and can be used to demonstrate its usage. For + * operations that apply to more than one entity (`list`, `create`, `info` and `delete`) the third + * parameter specifies the entity. + */ +public class LoggingExample { + + private static final Map CREATE_ACTIONS = new HashMap<>(); + private static final Map INFO_ACTIONS = new HashMap<>(); + private static final Map LIST_ACTIONS = new HashMap<>(); + private static final Map DELETE_ACTIONS = new HashMap<>(); + private static final Map ACTIONS = new HashMap<>(); + + private abstract static class LoggingAction { + + abstract void run(Logging logging, T arg) throws Exception; + + abstract T parse(String... args) throws Exception; + + protected String params() { + return ""; + } + } + + private static class Tuple { + + private final X x; + private final Y y; + + private Tuple(X x, Y y) { + this.x = x; + this.y = y; + } + + public static Tuple of(X x, Y y) { + return new Tuple<>(x, y); + } + + X x() { + return x; + } + + Y y() { + return y; + } + } + + private static class ParentAction extends LoggingAction> { + + private final Map subActions; + + ParentAction(Map subActions) { + this.subActions = ImmutableMap.copyOf(subActions); + } + + @Override + @SuppressWarnings("unchecked") + void run(Logging logging, Tuple subaction) throws Exception { + subaction.x().run(logging, subaction.y()); + } + + @Override + Tuple parse(String... args) throws Exception { + if (args.length >= 1) { + LoggingAction action = subActions.get(args[0]); + if (action != null) { + Object actionArguments = action.parse(Arrays.copyOfRange(args, 1, args.length)); + return Tuple.of(action, actionArguments); + } else { + throw new IllegalArgumentException("Unrecognized entity '" + args[0] + "'."); + } + } + throw new IllegalArgumentException("Missing required entity."); + } + + @Override + public String params() { + StringBuilder builder = new StringBuilder(); + for (Map.Entry entry : subActions.entrySet()) { + builder.append('\n').append(entry.getKey()); + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + builder.append(' ').append(param); + } + } + return builder.toString(); + } + } + + private abstract static class NoArgsAction extends LoggingAction { + @Override + Void parse(String... args) throws Exception { + if (args.length == 0) { + return null; + } + throw new IllegalArgumentException("This action takes no arguments."); + } + } + + /** + * This class demonstrates how to list Logging metrics. + * + * @see + * List metrics + */ + private static class ListMetricsAction extends NoArgsAction { + @Override + public void run(Logging logging, Void arg) { + Iterator metricIterator = logging.listMetrics().iterateAll(); + while (metricIterator.hasNext()) { + System.out.println(metricIterator.next()); + } + } + } + + private abstract static class MetricAction extends LoggingAction { + @Override + String parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return args[0]; + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required metric name."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Logging metric. + * + * @see + * Get metric + */ + private static class MetricInfoAction extends MetricAction { + @Override + public void run(Logging logging, String metric) { + System.out.printf("Metric info: %s%n", logging.getMetric(metric)); + } + } + + /** + * This class demonstrates how to delete a Logging metric. + * + * @see + * Delete a metric + */ + private static class DeleteMetricAction extends MetricAction { + @Override + public void run(Logging logging, String metric) { + logging.deleteMetric(metric); + System.out.printf("Deleted metric %s%n", metric); + } + } + + /** + * This class demonstrates how to create a Logging metric. + * + * @see + * Create a metric + */ + private static class CreateMetricAction extends LoggingAction { + @Override + public void run(Logging logging, MetricInfo metric) { + System.out.printf("Created metric %s%n", logging.create(metric)); + } + + @Override + MetricInfo parse(String... args) throws Exception { + String message; + if (args.length == 2) { + return MetricInfo.of(args[0], args[1]); + } else if (args.length > 2) { + message = "Too many arguments."; + } else { + message = "Missing required metric name or filter."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return " "; + } + } + + /** + * This class demonstrates how to list Logging sinks. + * + * @see + * List sinks + */ + private static class ListSinksAction extends NoArgsAction { + @Override + public void run(Logging logging, Void arg) { + Iterator sinkIterator = logging.listSinks().iterateAll(); + while (sinkIterator.hasNext()) { + System.out.println(sinkIterator.next()); + } + } + } + + private abstract static class SinkAction extends LoggingAction { + @Override + String parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return args[0]; + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required sink name."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + /** + * This class demonstrates how to retrieve information on a Logging sink. + * + * @see + * Get sink + */ + private static class SinkInfoAction extends SinkAction { + @Override + public void run(Logging logging, String sink) { + System.out.printf("Sink info: %s%n", logging.getSink(sink)); + } + } + + /** + * This class demonstrates how to delete a Logging sink. + * + * @see + * Delete a sink + */ + private static class DeleteSinkAction extends SinkAction { + @Override + public void run(Logging logging, String sink) { + logging.deleteSink(sink); + System.out.printf("Deleted sink %s%n", sink); + } + } + + /** + * This class demonstrates how to create a Logging sink. + * + * @see + * Create a sink + */ + private static class CreateSinkAction extends LoggingAction { + @Override + public void run(Logging logging, SinkInfo sink) { + System.out.printf("Created sink %s%n", logging.create(sink)); + } + + @Override + SinkInfo parse(String... args) throws Exception { + if (args.length >= 3) { + if (args.length > 4) { + throw new IllegalArgumentException("Too many arguments."); + } + String name = args[0]; + Destination destination; + switch (args[1]) { + case "bucket": + destination = BucketDestination.of(args[2]); + break; + case "dataset": + destination = DatasetDestination.of(args[2]); + break; + case "topic": + destination = TopicDestination.of(args[2]); + break; + default: + throw new IllegalArgumentException("Second argument must be bucket|dataset|topic."); + } + SinkInfo.Builder builder = SinkInfo.builder(name, destination); + if (args.length == 4) { + builder.filter(args[3]); + } + return builder.build(); + } + throw new IllegalArgumentException("Missing required sink name, destination or filter."); + } + + @Override + public String params() { + return " bucket|dataset|topic ?"; + } + } + + /** + * This class demonstrates how to list Logging monitored resource descriptors. + * + * @see + * List monitored resource descriptor + */ + private static class ListResourceDescriptorsAction extends NoArgsAction { + @Override + public void run(Logging logging, Void arg) { + Iterator monitoredResourceIterator = + logging.listMonitoredResourceDescriptors().iterateAll(); + while (monitoredResourceIterator.hasNext()) { + System.out.println(monitoredResourceIterator.next()); + } + } + } + + /** + * This class demonstrates how to write Logging entries. + * + * @see + * Write log entries + */ + private static class WriteEntryAction extends LoggingAction { + + @Override + public void run(Logging logging, LogEntry entry) { + MonitoredResource resource = MonitoredResource.builder("global") + .addLabel("project_id", logging.options().projectId()) + .build(); + LogEntry entryWithResource = entry.toBuilder().resource(resource).build(); + logging.write(Collections.singleton(entryWithResource)); + System.out.printf("Written entry %s%n", entryWithResource); + } + + @Override + LogEntry parse(String... args) throws Exception { + if (args.length >= 3) { + if ((args.length & 0x1) != 0x1) { + throw new IllegalArgumentException("Labels must be a list of key-value pairs."); + } + String logName = args[0]; + Severity severity = Severity.valueOf(args[1].toUpperCase()); + String message = args[2]; + Map labels = Maps.newHashMapWithExpectedSize((args.length - 3) / 2); + for (int i = 3; i < args.length; i += 2) { + labels.put(args[i], args[i + 1]); + } + return LogEntry.builder(StringPayload.of(message)) + .logName(logName) + .severity(severity) + .labels(labels) + .build(); + } else { + throw new IllegalArgumentException("Missing required arguments."); + } + } + + @Override + public String params() { + return " ( )*"; + } + } + + /** + * This class demonstrates how to list Logging entries. + * + * @see + * List log entries + */ + private static class ListEntriesAction extends LoggingAction { + @Override + public void run(Logging logging, String filter) { + Iterator entryIterator; + if (filter == null) { + entryIterator = logging.listLogEntries().iterateAll(); + } else { + entryIterator = logging.listLogEntries(EntryListOption.filter(filter)).iterateAll(); + } + while (entryIterator.hasNext()) { + System.out.println(entryIterator.next()); + } + } + + @Override + String parse(String... args) throws Exception { + if (args.length == 0) { + return null; + } else if (args.length == 1) { + return args[0]; + } + throw new IllegalArgumentException("Too many arguments."); + } + + @Override + public String params() { + return "?"; + } + } + + /** + * This class demonstrates how to delete a Logging log. + * + * @see + * Delete a log + */ + private static class DeleteLogAction extends LoggingAction { + @Override + public void run(Logging logging, String logName) { + logging.deleteLog(logName); + System.out.printf("Deleted log %s%n", logName); + } + + @Override + String parse(String... args) throws Exception { + String message; + if (args.length == 1) { + return args[0]; + } else if (args.length > 1) { + message = "Too many arguments."; + } else { + message = "Missing required log name."; + } + throw new IllegalArgumentException(message); + } + + @Override + public String params() { + return ""; + } + } + + static { + CREATE_ACTIONS.put("metric", new CreateMetricAction()); + CREATE_ACTIONS.put("sink", new CreateSinkAction()); + INFO_ACTIONS.put("metric", new MetricInfoAction()); + INFO_ACTIONS.put("sink", new SinkInfoAction()); + LIST_ACTIONS.put("metrics", new ListMetricsAction()); + LIST_ACTIONS.put("sinks", new ListSinksAction()); + LIST_ACTIONS.put("entries", new ListEntriesAction()); + LIST_ACTIONS.put("resource-descriptors", new ListResourceDescriptorsAction()); + DELETE_ACTIONS.put("metric", new DeleteMetricAction()); + DELETE_ACTIONS.put("sink", new DeleteSinkAction()); + DELETE_ACTIONS.put("log", new DeleteLogAction()); + ACTIONS.put("create", new ParentAction(CREATE_ACTIONS)); + ACTIONS.put("info", new ParentAction(INFO_ACTIONS)); + ACTIONS.put("list", new ParentAction(LIST_ACTIONS)); + ACTIONS.put("delete", new ParentAction(DELETE_ACTIONS)); + ACTIONS.put("write", new WriteEntryAction()); + } + + private static void printUsage() { + StringBuilder actionAndParams = new StringBuilder(); + for (Map.Entry entry : ACTIONS.entrySet()) { + actionAndParams.append("\n\t").append(entry.getKey()); + + String param = entry.getValue().params(); + if (param != null && !param.isEmpty()) { + actionAndParams.append(' ').append(param.replace("\n", "\n\t\t")); + } + } + System.out.printf("Usage: %s [] operation [entity] *%s%n", + LoggingExample.class.getSimpleName(), actionAndParams); + } + + @SuppressWarnings("unchecked") + public static void main(String... args) throws Exception { + if (args.length < 1) { + System.out.println("Missing required project id and action"); + printUsage(); + return; + } + LoggingOptions.Builder optionsBuilder = LoggingOptions.builder(); + LoggingAction action; + String actionName; + if (args.length >= 2 && !ACTIONS.containsKey(args[0])) { + actionName = args[1]; + optionsBuilder.projectId(args[0]); + action = ACTIONS.get(args[1]); + args = Arrays.copyOfRange(args, 2, args.length); + } else { + actionName = args[0]; + action = ACTIONS.get(args[0]); + args = Arrays.copyOfRange(args, 1, args.length); + } + if (action == null) { + System.out.println("Unrecognized action."); + printUsage(); + return; + } + try (Logging logging = optionsBuilder.build().service()) { + Object arg; + try { + arg = action.parse(args); + } catch (IllegalArgumentException ex) { + System.out.printf("Invalid input for action '%s'. %s%n", actionName, ex.getMessage()); + System.out.printf("Expected: %s%n", action.params()); + return; + } catch (Exception ex) { + System.out.println("Failed to parse arguments."); + ex.printStackTrace(); + return; + } + action.run(logging, arg); + } + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListMetrics.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListMetrics.java new file mode 100644 index 000000000000..57590c71f15b --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListMetrics.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.examples.logging.snippets; + +import com.google.cloud.Page; +import com.google.cloud.logging.Logging; +import com.google.cloud.logging.LoggingOptions; +import com.google.cloud.logging.Metric; +import com.google.cloud.logging.MetricInfo; + +import java.util.Iterator; + +/** + * A snippet for Stackdriver Logging showing how to create a metric. The snippet also shows how to + * list all metrics. + * + * @see Log-based metrics + * + */ +public class CreateAndListMetrics { + + public static void main(String... args) { + // Create a service object + // Credentials are inferred from the environment + Logging logging = LoggingOptions.defaultInstance().service(); + + // Create a metric + MetricInfo metricInfo = MetricInfo.builder("test-metric", "severity >= ERROR") + .description("Log entries with severity higher or equal to ERROR") + .build(); + logging.create(metricInfo); + + // List metrics + Page metrics = logging.listMetrics(); + Iterator metricIterator = metrics.iterateAll(); + while (metricIterator.hasNext()) { + System.out.println(metricIterator.next()); + } + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListSinks.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListSinks.java new file mode 100644 index 000000000000..b691175e8519 --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/CreateAndListSinks.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.examples.logging.snippets; + +import com.google.cloud.Page; +import com.google.cloud.logging.Logging; +import com.google.cloud.logging.LoggingOptions; +import com.google.cloud.logging.Sink; +import com.google.cloud.logging.SinkInfo; +import com.google.cloud.logging.SinkInfo.Destination.DatasetDestination; + +import java.util.Iterator; + +/** + * A snippet for Stackdriver Logging showing how to create a sink to backs log entries to BigQuery. + * The snippet also shows how to list all sinks. + * + * @see Sinks + */ +public class CreateAndListSinks { + + public static void main(String... args) { + // Create a service object + // Credentials are inferred from the environment + Logging logging = LoggingOptions.defaultInstance().service(); + + // Create a sink to back log entries to a BigQuery dataset + SinkInfo sinkInfo = SinkInfo.builder("test-sink", DatasetDestination.of("test-dataset")) + .filter("severity >= ERROR") + .build(); + logging.create(sinkInfo); + + // List sinks + Page sinks = logging.listSinks(); + Iterator sinkIterator = sinks.iterateAll(); + while (sinkIterator.hasNext()) { + System.out.println(sinkIterator.next()); + } + } +} diff --git a/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/WriteAndListLogEntries.java b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/WriteAndListLogEntries.java new file mode 100644 index 000000000000..f4a1bac85ac1 --- /dev/null +++ b/gcloud-java-examples/src/main/java/com/google/cloud/examples/logging/snippets/WriteAndListLogEntries.java @@ -0,0 +1,61 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.examples.logging.snippets; + +import com.google.cloud.MonitoredResource; +import com.google.cloud.Page; +import com.google.cloud.logging.LogEntry; +import com.google.cloud.logging.Logging; +import com.google.cloud.logging.Logging.EntryListOption; +import com.google.cloud.logging.LoggingOptions; +import com.google.cloud.logging.Payload.StringPayload; + +import java.util.Collections; +import java.util.Iterator; + +/** + * A snippet for Stackdriver Logging showing how to write a log entry. The snippet also shows how to + * list all log entries with a given log name. + * + * @see Sinks + */ +public class WriteAndListLogEntries { + + public static void main(String... args) { + // Create a service object + // Credentials are inferred from the environment + LoggingOptions options = LoggingOptions.defaultInstance(); + Logging logging = options.service(); + + // Create a log entry + LogEntry firstEntry = LogEntry.builder(StringPayload.of("message")) + .logName("test-log") + .resource(MonitoredResource.builder("global") + .addLabel("project_id", options.projectId()) + .build()) + .build(); + logging.write(Collections.singleton(firstEntry)); + + // List log entries + Page entries = logging.listLogEntries( + EntryListOption.filter("logName=projects/" + options.projectId() + "/logs/test-log")); + Iterator entryIterator = entries.iterateAll(); + while (entryIterator.hasNext()) { + System.out.println(entryIterator.next()); + } + } +} diff --git a/gcloud-java/pom.xml b/gcloud-java/pom.xml index ec9c81aca11c..0ea720f48df0 100644 --- a/gcloud-java/pom.xml +++ b/gcloud-java/pom.xml @@ -39,6 +39,11 @@ gcloud-java-dns ${project.version} + + ${project.groupId} + gcloud-java-logging + ${project.version} + ${project.groupId} gcloud-java-resourcemanager