mirror of
https://github.com/google/nomulus.git
synced 2025-05-02 13:07:50 +02:00
268 lines
10 KiB
Java
268 lines
10 KiB
Java
// Copyright 2017 The Nomulus Authors. 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 google.registry.monitoring.metrics.example;
|
|
|
|
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
|
import com.google.api.client.http.HttpTransport;
|
|
import com.google.api.client.http.javanet.NetHttpTransport;
|
|
import com.google.api.client.json.JsonFactory;
|
|
import com.google.api.client.json.jackson2.JacksonFactory;
|
|
import com.google.api.services.monitoring.v3.Monitoring;
|
|
import com.google.api.services.monitoring.v3.MonitoringScopes;
|
|
import com.google.api.services.monitoring.v3.model.MonitoredResource;
|
|
import com.google.common.base.Supplier;
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableMap;
|
|
import com.google.common.collect.ImmutableSet;
|
|
import google.registry.monitoring.metrics.EventMetric;
|
|
import google.registry.monitoring.metrics.IncrementableMetric;
|
|
import google.registry.monitoring.metrics.LabelDescriptor;
|
|
import google.registry.monitoring.metrics.LinearFitter;
|
|
import google.registry.monitoring.metrics.Metric;
|
|
import google.registry.monitoring.metrics.MetricRegistryImpl;
|
|
import google.registry.monitoring.metrics.MetricReporter;
|
|
import google.registry.monitoring.metrics.MetricWriter;
|
|
import google.registry.monitoring.metrics.SettableMetric;
|
|
import google.registry.monitoring.metrics.stackdriver.StackdriverWriter;
|
|
import java.io.IOException;
|
|
import java.util.Random;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.logging.Handler;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.LogManager;
|
|
import java.util.logging.Logger;
|
|
|
|
/** A sample application which uses the Metrics API to count sheep while sleeping. */
|
|
public final class SheepCounterExample {
|
|
|
|
/**
|
|
* The code below for using a custom {@link LogManager} is only necessary to enable logging at JVM
|
|
* shutdown to show the shutdown logs of {@link MetricReporter} in this small standalone
|
|
* application.
|
|
*
|
|
* <p>It is NOT necessary for normal use of the Metrics library.
|
|
*/
|
|
static {
|
|
// must be called before any Logger method is used.
|
|
System.setProperty("java.util.logging.manager", DelayedShutdownLogManager.class.getName());
|
|
}
|
|
|
|
private static final Logger logger = Logger.getLogger(SheepCounterExample.class.getName());
|
|
|
|
/**
|
|
* The time interval, in seconds, between when the {@link MetricReporter} will read {@link Metric}
|
|
* instances and enqueue them to the {@link MetricWriter}.
|
|
*
|
|
* @see MetricReporter
|
|
*/
|
|
private static final long METRICS_REPORTING_INTERVAL = 30L;
|
|
|
|
/**
|
|
* The maximum queries per second to the Stackdriver API. Contact Cloud Support to raise this from
|
|
* the default value if necessary.
|
|
*/
|
|
private static final int STACKDRIVER_MAX_QPS = 30;
|
|
|
|
/**
|
|
* The maximum number of {@link com.google.api.services.monitoring.v3.model.TimeSeries} that can
|
|
* be bundled into a single {@link
|
|
* com.google.api.services.monitoring.v3.model.CreateTimeSeriesRequest}. This must be at most 200.
|
|
* Setting this lower will cause the {@link StackdriverWriter} to {@link
|
|
* StackdriverWriter#flush()} more frequently.
|
|
*/
|
|
private static final int STACKDRIVER_MAX_POINTS_PER_REQUEST = 200;
|
|
|
|
// Create some metrics to track your ZZZs.
|
|
private static final ImmutableList<String> SHEEP_COLORS =
|
|
ImmutableList.of("Green", "Yellow", "Red", "Blue");
|
|
private static final ImmutableList<String> SHEEP_SPECIES =
|
|
ImmutableList.of("Domestic", "Bighorn");
|
|
private static final ImmutableSet<LabelDescriptor> SHEEP_ATTRIBUTES =
|
|
ImmutableSet.of(
|
|
LabelDescriptor.create("color", "Sheep Color"),
|
|
LabelDescriptor.create("species", "Sheep Species"));
|
|
|
|
/**
|
|
* Counters are good for tracking monotonically increasing values, like request counts or error
|
|
* counts. Or, in this case, sheep.
|
|
*/
|
|
private static final IncrementableMetric sheepCounter =
|
|
MetricRegistryImpl.getDefault()
|
|
.newIncrementableMetric(
|
|
"/sheep", "Counts sheep over time.", "Number of Sheep", SHEEP_ATTRIBUTES);
|
|
|
|
/**
|
|
* Settable metrics are good for state indicators. For example, you could use one to track the
|
|
* lifecycle of a {@link com.google.common.util.concurrent.Service}. In this case, we are just
|
|
* using it to track the sleep state of this application.
|
|
*/
|
|
private static final SettableMetric<Boolean> isSleeping =
|
|
MetricRegistryImpl.getDefault()
|
|
.newSettableMetric(
|
|
"/is_sleeping",
|
|
"Tracks sleep state.",
|
|
"Sleeping?",
|
|
ImmutableSet.<LabelDescriptor>of(),
|
|
Boolean.class);
|
|
|
|
/**
|
|
* Gauge metrics never need to be accessed, so the assignment here is unnecessary. You only need
|
|
* it if you plan on calling {@link Metric#getTimestampedValues()} to read the values of the
|
|
* metric in the code yourself.
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
private static final Metric<Double> sleepQuality =
|
|
MetricRegistryImpl.getDefault()
|
|
.newGauge(
|
|
"/sleep_quality",
|
|
"Quality of the sleep.",
|
|
"Quality",
|
|
ImmutableSet.<LabelDescriptor>of(),
|
|
new Supplier<ImmutableMap<ImmutableList<String>, Double>>() {
|
|
@Override
|
|
public ImmutableMap<ImmutableList<String>, Double> get() {
|
|
return ImmutableMap.of(ImmutableList.<String>of(), new Random().nextDouble());
|
|
}
|
|
},
|
|
Double.class);
|
|
|
|
/**
|
|
* Event metrics track aspects of an "event." Here, we track the fluffiness of the sheep we've
|
|
* seen.
|
|
*/
|
|
private static final EventMetric sheepFluffiness =
|
|
MetricRegistryImpl.getDefault()
|
|
.newEventMetric(
|
|
"/sheep_fluffiness",
|
|
"Measures the fluffiness of seen sheep.",
|
|
"Fill Power",
|
|
SHEEP_ATTRIBUTES,
|
|
LinearFitter.create(5, 20.0, 20.0));
|
|
|
|
private static Monitoring createAuthorizedMonitoringClient() throws IOException {
|
|
// Grab the Application Default Credentials from the environment.
|
|
// Generate these with 'gcloud beta auth application-default login'
|
|
GoogleCredential credential =
|
|
GoogleCredential.getApplicationDefault().createScoped(MonitoringScopes.all());
|
|
|
|
// Create and return the CloudMonitoring service object
|
|
HttpTransport httpTransport = new NetHttpTransport();
|
|
JsonFactory jsonFactory = new JacksonFactory();
|
|
return new Monitoring.Builder(httpTransport, jsonFactory, credential)
|
|
.setApplicationName("Monitoring Sample")
|
|
.build();
|
|
}
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
if (args.length < 1) {
|
|
System.err.println("Missing required project argument");
|
|
System.err.printf(
|
|
"Usage: java %s gcp-project-id [verbose]\n", SheepCounterExample.class.getName());
|
|
return;
|
|
}
|
|
String project = args[0];
|
|
|
|
// Turn up the logging verbosity
|
|
if (args.length > 1) {
|
|
Logger log = LogManager.getLogManager().getLogger("");
|
|
log.setLevel(Level.ALL);
|
|
for (Handler h : log.getHandlers()) {
|
|
h.setLevel(Level.ALL);
|
|
}
|
|
}
|
|
|
|
// Create a sample resource. In this case, a GCE Instance.
|
|
// See https://cloud.google.com/monitoring/api/resources for a list of resource types.
|
|
MonitoredResource monitoredResource =
|
|
new MonitoredResource()
|
|
.setType("gce_instance")
|
|
.setLabels(
|
|
ImmutableMap.of(
|
|
"instance_id", "test-instance",
|
|
"zone", "us-central1-f"));
|
|
|
|
// Set up the Metrics infrastructure.
|
|
MetricWriter stackdriverWriter =
|
|
new StackdriverWriter(
|
|
createAuthorizedMonitoringClient(),
|
|
project,
|
|
monitoredResource,
|
|
STACKDRIVER_MAX_QPS,
|
|
STACKDRIVER_MAX_POINTS_PER_REQUEST);
|
|
final MetricReporter reporter =
|
|
new MetricReporter(
|
|
stackdriverWriter, METRICS_REPORTING_INTERVAL, Executors.defaultThreadFactory());
|
|
reporter.startAsync().awaitRunning();
|
|
|
|
// Set up a handler to stop sleeping on SIGINT.
|
|
Runtime.getRuntime()
|
|
.addShutdownHook(
|
|
new Thread(
|
|
new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
reporter.stopAsync().awaitTerminated();
|
|
// Allow the LogManager to cleanup the loggers.
|
|
DelayedShutdownLogManager.resetFinally();
|
|
}
|
|
}));
|
|
|
|
System.err.println("Send SIGINT (Ctrl+C) to stop sleeping.");
|
|
while (true) {
|
|
// Count some Googley sheep.
|
|
int colorIndex = new Random().nextInt(SHEEP_COLORS.size());
|
|
int speciesIndex = new Random().nextInt(SHEEP_SPECIES.size());
|
|
sheepCounter.incrementBy(1, SHEEP_COLORS.get(colorIndex), SHEEP_SPECIES.get(speciesIndex));
|
|
sheepFluffiness.record(
|
|
new Random().nextDouble() * 200,
|
|
SHEEP_COLORS.get(colorIndex),
|
|
SHEEP_SPECIES.get(speciesIndex));
|
|
isSleeping.set(true);
|
|
|
|
logger.info("zzz...");
|
|
Thread.sleep(5000);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Special {@link LogManager} with a no-op {@link LogManager#reset()} so that logging can proceed
|
|
* as usual until stopped in in another runtime shutdown hook.
|
|
*
|
|
* <p>The class is marked public because it is loaded by the JVM classloader at runtime.
|
|
*/
|
|
@SuppressWarnings("WeakerAccess")
|
|
public static class DelayedShutdownLogManager extends LogManager {
|
|
|
|
private static DelayedShutdownLogManager instance;
|
|
|
|
public DelayedShutdownLogManager() {
|
|
instance = this;
|
|
}
|
|
|
|
/** A no-op implementation. */
|
|
@Override
|
|
public void reset() {
|
|
/* don't reset yet. */
|
|
}
|
|
|
|
static void resetFinally() {
|
|
instance.delayedReset();
|
|
}
|
|
|
|
private void delayedReset() {
|
|
super.reset();
|
|
}
|
|
}
|
|
}
|