com.google.api.control.model.ReportingRule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of endpoints-management-control Show documentation
Show all versions of endpoints-management-control Show documentation
Provide access control for managed services
/*
* 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.api.control.model;
import com.google.api.LabelDescriptor;
import com.google.api.LogDescriptor;
import com.google.api.Logging.LoggingDestination;
import com.google.api.MetricDescriptor;
import com.google.api.MonitoredResourceDescriptor;
import com.google.api.Monitoring;
import com.google.api.Monitoring.MonitoringDestination;
import com.google.api.Service;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
* ReportingRule determines how to fill a report request.
*/
public class ReportingRule {
private static final Logger log = Logger.getLogger(ReportingRule.class.getName());
/**
* MetricSupporter defines a method that determines is a metric is supported
*/
public static interface MetricTest {
boolean isSupported(MetricDescriptor m);
}
/**
* LabelSupporter defines a method that determines if a metric is supported
*/
public static interface LabelTest {
boolean isSupported(LabelDescriptor l);
}
private static final MetricTest KNOWN_METRICS = new MetricTest() {
@Override
public boolean isSupported(MetricDescriptor m) {
return KnownMetrics.isSupported(m);
}
};
private static final LabelTest KNOWN_LABELS = new LabelTest() {
@Override
public boolean isSupported(LabelDescriptor l) {
return KnownLabels.isSupported(l);
}
};
/**
* 'Constructor' that uses a {@code Service}.
*
* @param s the {@code Service} whose metric, labels and logs configurations are used to
* configure the {@code ReportingRule}
* @return {@code ReportingRule}
*/
public static ReportingRule fromService(Service s) {
return fromService(s, KNOWN_METRICS, KNOWN_LABELS);
}
/**
* 'Constructor' that uses names of known {@code KnownMetrics} and {@code KnownLabels}.
*
* Names that don't correspond to actual instances are ignored, as are instances where there is
* not yet an update function that will modify a {@code ReportRequest}
*
* @param logs the {@code logs} for which entries will be added {@code ReportRequests}
* @param metricNames the names of the {@code KnownMetrics} to use
* @param labelNames the names of the {@code KnownLabels} to use
* @return {@code ReportingRule}
*/
public static ReportingRule fromKnownInputs(@Nullable String[] logs,
@Nullable Set metricNames, @Nullable Set labelNames) {
log.fine(String.format("creating rule from log names %s, metric names %s, labelNames %s",
Arrays.toString(logs), metricNames, labelNames));
Map namedRuleMetrics = Maps.newHashMap();
if (metricNames != null) {
for (KnownMetrics m : KnownMetrics.values()) {
if (m.getUpdater() == null || !metricNames.contains(m.getName())) {
continue;
}
log.fine(String.format("Adding metric named '%s' to the rule", m.getName()));
namedRuleMetrics.put(m.getName(), m);
}
}
Map namedRuleLabels = Maps.newHashMap();
if (labelNames != null) {
for (KnownLabels k : KnownLabels.values()) {
if (k.getUpdater() == null || !labelNames.contains(k.getName())) {
continue;
}
log.fine(String.format("Adding label named '%s' to the rule", k.getName()));
namedRuleLabels.put(k.getName(), k);
}
}
return new ReportingRule(logs,
namedRuleMetrics.values().toArray(new KnownMetrics[namedRuleMetrics.size()]),
namedRuleLabels.values().toArray(new KnownLabels[namedRuleLabels.size()]));
}
/**
* 'Constructor' that uses a {@code Service}.
*
* @param s the {@code Service} whose metric, labels and logs configurations are used to configure
* the {@code ReportingRule}
*
* @param checkMetrics used to determine which {@code MetricDescriptors} are allowed
* @param checkLabels used to determine which {@code LabelDescriptors} are allowed
*
* @return {@code ReportingRule}
*/
private static ReportingRule fromService(Service s, ReportingRule.MetricTest checkMetrics,
ReportingRule.LabelTest checkLabels) {
List resourceDescs = s.getMonitoredResourcesList();
Map labels = Maps.newHashMap();
Set logs = Sets.newHashSet();
if (s.hasLogging()) {
List producers = s.getLogging().getProducerDestinationsList();
logs = addLoggingDestinations(producers, resourceDescs, s.getLogsList(), labels, checkLabels);
}
Set metrics = Sets.newHashSet();
if (s.hasMonitoring()) {
Monitoring monitoring = s.getMonitoring();
addMonitoringDestinations(monitoring.getConsumerDestinationsList(), resourceDescs,
s.getMetricsList(), metrics, checkMetrics, labels, checkLabels);
addMonitoringDestinations(monitoring.getProducerDestinationsList(), resourceDescs,
s.getMetricsList(), metrics, checkMetrics, labels, checkLabels);
}
return ReportingRule.fromKnownInputs(logs.toArray(new String[logs.size()]), metrics,
labels.keySet());
}
/**
* Constructor that uses {@code KnownMetrics} and {@code KnownLabels} instance directly
*
* @param logs the {@code logs} for which entries will be added {@code ReportRequests}
* @param metrics the {@code KnownMetrics} used to add metrics to {@code ReportRequests}
* @param labels the {@code KnownLabels} used to add labels to {@code ReportRequests}
*/
private ReportingRule(@Nullable String[] logs, @Nullable KnownMetrics[] metrics,
@Nullable KnownLabels[] labels) {
if (logs == null) {
this.logs = new String[] {};
} else {
this.logs = logs;
}
if (metrics == null) {
this.metrics = new KnownMetrics[] {};
} else {
this.metrics = metrics;
}
if (labels == null) {
this.labels = new KnownLabels[] {};
} else {
this.labels = labels;
}
}
/**
* @return the {@code logs} for which entries will be added {@code ReportRequests}
*/
public String[] getLogs() {
return logs;
}
/**
* @return the {@code KnownMetrics} used to add metrics to {@code ReportRequests}
*/
public KnownMetrics[] getMetrics() {
return metrics;
}
/**
* @return the {@code KnownLabels} used to add labels to {@code ReportRequests}
*/
public KnownLabels[] getLabels() {
return labels;
}
private final String[] logs;
private final KnownMetrics[] metrics;
private final KnownLabels[] labels;
private static Set addLoggingDestinations(List destinations,
List resourceDescs, List logDescs,
Map labels, ReportingRule.LabelTest checkLabels) {
Set logs = Sets.newHashSet();
for (LoggingDestination d : destinations) {
if (!addLabelsForAMonitoredResource(resourceDescs, d.getMonitoredResource(), labels,
checkLabels)) {
continue;
}
for (String name : d.getLogsList()) {
if (addLabelsForALog(logDescs, name, labels, checkLabels)) {
logs.add(name);
}
}
}
return logs;
}
private static void addMonitoringDestinations(List destinations,
List resourceDescs, List metricDests,
Set metrics, ReportingRule.MetricTest checkMetric, Map labels,
ReportingRule.LabelTest checkLabel) {
for (MonitoringDestination d : destinations) {
if (!addLabelsForAMonitoredResource(resourceDescs, d.getMonitoredResource(), labels,
checkLabel)) {
continue;
}
for (String metric : d.getMetricsList()) {
MetricDescriptor metricDest = findMetricDescriptor(metricDests, metric, checkMetric);
if (metricDest == null
|| !addLabelsFromDescriptors(metricDest.getLabelsList(), labels, checkLabel)) {
continue; // skip unrecognized or bad metric, or it has bad labels
}
metrics.add(metric);
}
}
}
private static boolean addLabelsFromDescriptors(List labelDescs,
Map labels, ReportingRule.LabelTest check) {
for (LabelDescriptor d : labelDescs) {
LabelDescriptor existing = labels.get(d.getKey());
if (existing != null && !existing.getValueType().equals(d.getValueType())) {
log.log(Level.WARNING,
String.format("halted label scan: conflicting label in %s", d.getKey()));
return false;
}
}
for (LabelDescriptor d : labelDescs) {
if (check.isSupported(d)) {
labels.put(d.getKey(), d);
}
}
return true;
}
private static boolean addLabelsForALog(List logDescs, String name,
Map labels, ReportingRule.LabelTest check) {
for (LogDescriptor d : logDescs) {
if (d.getName().equals(name)) {
return addLabelsFromDescriptors(d.getLabelsList(), labels, check);
}
}
log.log(Level.WARNING, String.format("bad log label scan: log %s was not found", name));
return false;
}
private static boolean addLabelsForAMonitoredResource(
List resourceDescs, String resourceType,
Map labels, ReportingRule.LabelTest check) {
for (MonitoredResourceDescriptor d : resourceDescs) {
if (d.getType().equals(resourceType)) {
return addLabelsFromDescriptors(d.getLabelsList(), labels, check);
}
}
log.log(Level.WARNING,
String.format("bad monitored resource label scan: resource %s was not found", resourceType));
return false;
}
private static MetricDescriptor findMetricDescriptor(List metricDests,
String metric, ReportingRule.MetricTest check) {
for (MetricDescriptor d : metricDests) {
if (!d.getName().equals(metric)) {
continue;
}
if (check.isSupported(d)) {
return d;
}
}
return null;
}
}