blob: 27593829e65f286b1273d2b5854a921881fd9a49 [file] [log] [blame]
/*
* Copyright 2017, OpenCensus Authors
*
* 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 io.opencensus.exporter.stats.stackdriver;
import static com.google.common.truth.Truth.assertThat;
import static io.opencensus.exporter.stats.stackdriver.StackdriverExporterWorker.CUSTOM_OPENCENSUS_DOMAIN;
import static io.opencensus.exporter.stats.stackdriver.StackdriverExporterWorker.DEFAULT_DISPLAY_NAME_PREFIX;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import com.google.api.MetricDescriptor;
import com.google.api.MonitoredResource;
import com.google.api.gax.rpc.UnaryCallable;
import com.google.cloud.monitoring.v3.MetricServiceClient;
import com.google.cloud.monitoring.v3.stub.MetricServiceStub;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.monitoring.v3.CreateMetricDescriptorRequest;
import com.google.monitoring.v3.CreateTimeSeriesRequest;
import com.google.monitoring.v3.TimeSeries;
import com.google.protobuf.Empty;
import io.opencensus.common.Duration;
import io.opencensus.common.Timestamp;
import io.opencensus.stats.Aggregation.Sum;
import io.opencensus.stats.AggregationData;
import io.opencensus.stats.AggregationData.SumDataLong;
import io.opencensus.stats.Measure.MeasureLong;
import io.opencensus.stats.View;
import io.opencensus.stats.View.AggregationWindow.Cumulative;
import io.opencensus.stats.View.AggregationWindow.Interval;
import io.opencensus.stats.View.Name;
import io.opencensus.stats.ViewData;
import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData;
import io.opencensus.stats.ViewManager;
import io.opencensus.tags.TagKey;
import io.opencensus.tags.TagValue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/** Unit tests for {@link StackdriverExporterWorker}. */
@RunWith(JUnit4.class)
public class StackdriverExporterWorkerTest {
private static final String PROJECT_ID = "projectId";
private static final Duration ONE_SECOND = Duration.create(1, 0);
private static final TagKey KEY = TagKey.create("KEY");
private static final TagValue VALUE = TagValue.create("VALUE");
private static final String MEASURE_NAME = "my measurement";
private static final String MEASURE_UNIT = "us";
private static final String MEASURE_DESCRIPTION = "measure description";
private static final MeasureLong MEASURE =
MeasureLong.create(MEASURE_NAME, MEASURE_DESCRIPTION, MEASURE_UNIT);
private static final Name VIEW_NAME = Name.create("my view");
private static final String VIEW_DESCRIPTION = "view description";
private static final Cumulative CUMULATIVE = Cumulative.create();
private static final Interval INTERVAL = Interval.create(ONE_SECOND);
private static final Sum SUM = Sum.create();
private static final MonitoredResource DEFAULT_RESOURCE =
MonitoredResource.newBuilder().setType("global").build();
@Mock private ViewManager mockViewManager;
@Mock private MetricServiceStub mockStub;
@Mock
private UnaryCallable<CreateMetricDescriptorRequest, MetricDescriptor>
mockCreateMetricDescriptorCallable;
@Mock private UnaryCallable<CreateTimeSeriesRequest, Empty> mockCreateTimeSeriesCallable;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
doReturn(mockCreateMetricDescriptorCallable).when(mockStub).createMetricDescriptorCallable();
doReturn(mockCreateTimeSeriesCallable).when(mockStub).createTimeSeriesCallable();
doReturn(null)
.when(mockCreateMetricDescriptorCallable)
.call(any(CreateMetricDescriptorRequest.class));
doReturn(null).when(mockCreateTimeSeriesCallable).call(any(CreateTimeSeriesRequest.class));
}
@Test
public void testConstants() {
assertThat(StackdriverExporterWorker.MAX_BATCH_EXPORT_SIZE).isEqualTo(200);
assertThat(StackdriverExporterWorker.CUSTOM_METRIC_DOMAIN).isEqualTo("custom.googleapis.com/");
assertThat(StackdriverExporterWorker.CUSTOM_OPENCENSUS_DOMAIN)
.isEqualTo("custom.googleapis.com/opencensus/");
assertThat(StackdriverExporterWorker.DEFAULT_DISPLAY_NAME_PREFIX).isEqualTo("OpenCensus/");
}
@Test
public void export() throws IOException {
View view =
View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE);
ViewData viewData =
ViewData.create(
view,
ImmutableMap.of(Arrays.asList(VALUE), SumDataLong.create(1)),
CumulativeData.create(Timestamp.fromMillis(100), Timestamp.fromMillis(200)));
doReturn(ImmutableSet.of(view)).when(mockViewManager).getAllExportedViews();
doReturn(viewData).when(mockViewManager).getView(VIEW_NAME);
StackdriverExporterWorker worker =
new StackdriverExporterWorker(
PROJECT_ID,
new FakeMetricServiceClient(mockStub),
ONE_SECOND,
mockViewManager,
DEFAULT_RESOURCE,
null);
worker.export();
verify(mockStub, times(1)).createMetricDescriptorCallable();
verify(mockStub, times(1)).createTimeSeriesCallable();
MetricDescriptor descriptor =
StackdriverExportUtils.createMetricDescriptor(
view, PROJECT_ID, CUSTOM_OPENCENSUS_DOMAIN, DEFAULT_DISPLAY_NAME_PREFIX);
List<TimeSeries> timeSeries =
StackdriverExportUtils.createTimeSeriesList(
viewData, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN);
verify(mockCreateMetricDescriptorCallable, times(1))
.call(
eq(
CreateMetricDescriptorRequest.newBuilder()
.setName("projects/" + PROJECT_ID)
.setMetricDescriptor(descriptor)
.build()));
verify(mockCreateTimeSeriesCallable, times(1))
.call(
eq(
CreateTimeSeriesRequest.newBuilder()
.setName("projects/" + PROJECT_ID)
.addAllTimeSeries(timeSeries)
.build()));
}
@Test
public void doNotExportForEmptyViewData() {
View view =
View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE);
ViewData empty =
ViewData.create(
view,
Collections.<List<TagValue>, AggregationData>emptyMap(),
CumulativeData.create(Timestamp.fromMillis(100), Timestamp.fromMillis(200)));
doReturn(ImmutableSet.of(view)).when(mockViewManager).getAllExportedViews();
doReturn(empty).when(mockViewManager).getView(VIEW_NAME);
StackdriverExporterWorker worker =
new StackdriverExporterWorker(
PROJECT_ID,
new FakeMetricServiceClient(mockStub),
ONE_SECOND,
mockViewManager,
DEFAULT_RESOURCE,
null);
worker.export();
verify(mockStub, times(1)).createMetricDescriptorCallable();
verify(mockStub, times(0)).createTimeSeriesCallable();
}
@Test
public void doNotExportIfFailedToRegisterView() {
View view =
View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE);
doReturn(ImmutableSet.of(view)).when(mockViewManager).getAllExportedViews();
doThrow(new IllegalArgumentException()).when(mockStub).createMetricDescriptorCallable();
StackdriverExporterWorker worker =
new StackdriverExporterWorker(
PROJECT_ID,
new FakeMetricServiceClient(mockStub),
ONE_SECOND,
mockViewManager,
DEFAULT_RESOURCE,
null);
assertThat(worker.registerView(view)).isFalse();
worker.export();
verify(mockStub, times(1)).createMetricDescriptorCallable();
verify(mockStub, times(0)).createTimeSeriesCallable();
}
@Test
public void skipDifferentViewWithSameName() throws IOException {
StackdriverExporterWorker worker =
new StackdriverExporterWorker(
PROJECT_ID,
new FakeMetricServiceClient(mockStub),
ONE_SECOND,
mockViewManager,
DEFAULT_RESOURCE,
null);
View view1 =
View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE);
assertThat(worker.registerView(view1)).isTrue();
verify(mockStub, times(1)).createMetricDescriptorCallable();
View view2 =
View.create(
VIEW_NAME,
"This is a different description.",
MEASURE,
SUM,
Arrays.asList(KEY),
CUMULATIVE);
assertThat(worker.registerView(view2)).isFalse();
verify(mockStub, times(1)).createMetricDescriptorCallable();
}
@Test
public void doNotCreateMetricDescriptorForRegisteredView() {
StackdriverExporterWorker worker =
new StackdriverExporterWorker(
PROJECT_ID,
new FakeMetricServiceClient(mockStub),
ONE_SECOND,
mockViewManager,
DEFAULT_RESOURCE,
null);
View view =
View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE);
assertThat(worker.registerView(view)).isTrue();
verify(mockStub, times(1)).createMetricDescriptorCallable();
assertThat(worker.registerView(view)).isTrue();
verify(mockStub, times(1)).createMetricDescriptorCallable();
}
@Test
public void doNotCreateMetricDescriptorForIntervalView() {
StackdriverExporterWorker worker =
new StackdriverExporterWorker(
PROJECT_ID,
new FakeMetricServiceClient(mockStub),
ONE_SECOND,
mockViewManager,
DEFAULT_RESOURCE,
null);
View view =
View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), INTERVAL);
assertThat(worker.registerView(view)).isFalse();
verify(mockStub, times(0)).createMetricDescriptorCallable();
}
@Test
public void getDomain() {
assertThat(StackdriverExporterWorker.getDomain(null))
.isEqualTo("custom.googleapis.com/opencensus/");
assertThat(StackdriverExporterWorker.getDomain(""))
.isEqualTo("custom.googleapis.com/opencensus/");
assertThat(StackdriverExporterWorker.getDomain("custom.googleapis.com/myorg/"))
.isEqualTo("custom.googleapis.com/myorg/");
assertThat(StackdriverExporterWorker.getDomain("external.googleapis.com/prometheus/"))
.isEqualTo("external.googleapis.com/prometheus/");
assertThat(StackdriverExporterWorker.getDomain("myorg")).isEqualTo("myorg/");
}
@Test
public void getDisplayNamePrefix() {
assertThat(StackdriverExporterWorker.getDisplayNamePrefix(null)).isEqualTo("OpenCensus/");
assertThat(StackdriverExporterWorker.getDisplayNamePrefix("")).isEqualTo("");
assertThat(StackdriverExporterWorker.getDisplayNamePrefix("custom.googleapis.com/myorg/"))
.isEqualTo("custom.googleapis.com/myorg/");
assertThat(
StackdriverExporterWorker.getDisplayNamePrefix("external.googleapis.com/prometheus/"))
.isEqualTo("external.googleapis.com/prometheus/");
assertThat(StackdriverExporterWorker.getDisplayNamePrefix("myorg")).isEqualTo("myorg/");
}
/*
* MetricServiceClient.createMetricDescriptor() and MetricServiceClient.createTimeSeries() are
* final methods and cannot be mocked. We have to use a mock MetricServiceStub in order to verify
* the output.
*/
private static final class FakeMetricServiceClient extends MetricServiceClient {
protected FakeMetricServiceClient(MetricServiceStub stub) {
super(stub);
}
}
}