// Copyright 2016 Twitter. 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.twitter.heron.metricsmgr;
import java.io.IOException;
import com.google.protobuf.Message;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.twitter.heron.api.metric.MultiCountMetric;
import com.twitter.heron.common.basics.Communicator;
import com.twitter.heron.common.basics.NIOLooper;
import com.twitter.heron.common.basics.SysUtils;
import com.twitter.heron.common.basics.TestCommunicator;
import com.twitter.heron.common.network.HeronClient;
import com.twitter.heron.common.network.HeronServerTester;
import com.twitter.heron.common.network.StatusCode;
import com.twitter.heron.proto.system.Metrics;
import com.twitter.heron.spi.metricsmgr.metrics.ExceptionInfo;
import com.twitter.heron.spi.metricsmgr.metrics.MetricsInfo;
import com.twitter.heron.spi.metricsmgr.metrics.MetricsRecord;
import static com.twitter.heron.common.network.HeronServerTester.RESPONSE_RECEIVED_TIMEOUT;
import static org.junit.Assert.fail;
/**
* MetricsManagerServer Tester.
*/
public class MetricsManagerServerTest {
private static final String METRIC_NAME = "metric-name";
private static final String METRIC_VALUE = "metric-value";
private static final int METRICS_COUNT = 20;
private static final int MESSAGE_SIZE = 10;
private static final String STACK_TRACE = "stackTrace";
private static final String LAST_TIME = "lastTime";
private static final String FIRST_TIME = "firstTime";
private static final String LOGGING = "logging";
private static final int EXCEPTION_COUNT = 20;
private MetricsManagerServer metricsManagerServer;
private HeronServerTester serverTester;
@Before
public void before() throws IOException {
metricsManagerServer = new MetricsManagerServer(new NIOLooper(), HeronServerTester.SERVER_HOST,
SysUtils.getFreePort(), HeronServerTester.TEST_SOCKET_OPTIONS, new MultiCountMetric());
serverTester = new HeronServerTester(metricsManagerServer,
new MetricsManagerClientRequestHandler(),
new HeronServerTester.SuccessResponseHandler(Metrics.MetricPublisherRegisterResponse.class,
new MetricsManagerClientResponseHandler(MESSAGE_SIZE)), RESPONSE_RECEIVED_TIMEOUT);
}
@After
public void after() {
serverTester.stop();
}
/**
* Method: addSinkCommunicator(Communicator<MetricsRecord> communicator)
*/
@Test
public void testAddSinkCommunicator() {
Communicator<MetricsRecord> sinkCommunicator = new Communicator<>();
metricsManagerServer.addSinkCommunicator(sinkCommunicator);
Assert.assertTrue(metricsManagerServer.removeSinkCommunicator(sinkCommunicator));
}
/**
* Method: removeSinkCommunicator(Communicator<MetricsRecord> communicator)
*/
@Test
public void testRemoveSinkCommunicator() {
Communicator<MetricsRecord> sinkCommunicator = new Communicator<>();
metricsManagerServer.addSinkCommunicator(sinkCommunicator);
Assert.assertTrue(metricsManagerServer.removeSinkCommunicator(sinkCommunicator));
}
/**
* Method: addSinkCommunicator(Communicator<MetricsRecord> communicator)
*/
@Test
public void testMetricsManagerServer() throws InterruptedException {
TestCommunicator<MetricsRecord> sinkCommunicator =
new TestCommunicator<>(MESSAGE_SIZE);
metricsManagerServer.addSinkCommunicator(sinkCommunicator);
serverTester.start();
try {
sinkCommunicator.awaitOffers(RESPONSE_RECEIVED_TIMEOUT);
} catch (InterruptedException e) {
fail(String.format("awaitOffers failed to release until timeout of %s was reached.",
RESPONSE_RECEIVED_TIMEOUT));
}
int messages = 0;
while (!sinkCommunicator.isEmpty()) {
int exceptions = 0;
int metrics = 0;
MetricsRecord record = sinkCommunicator.poll();
Assert.assertEquals("hostname:0/component/instance-id", record.getSource());
Assert.assertEquals("default", record.getContext());
for (MetricsInfo info : record.getMetrics()) {
Assert.assertEquals(METRIC_NAME, info.getName());
Assert.assertEquals(METRIC_VALUE, info.getValue());
metrics++;
}
Assert.assertEquals(METRICS_COUNT, metrics);
for (ExceptionInfo info : record.getExceptions()) {
Assert.assertEquals(STACK_TRACE, info.getStackTrace());
Assert.assertEquals(LAST_TIME, info.getLastTime());
Assert.assertEquals(FIRST_TIME, info.getFirstTime());
Assert.assertEquals(LOGGING, info.getLogging());
Assert.assertEquals(EXCEPTION_COUNT, info.getCount());
exceptions++;
}
Assert.assertEquals(METRICS_COUNT, exceptions);
messages++;
}
Assert.assertEquals(MESSAGE_SIZE, messages);
}
private class MetricsManagerClientRequestHandler implements HeronServerTester.TestRequestHandler {
@Override
public Message getRequestMessage() {
Metrics.MetricPublisher publisher = Metrics.MetricPublisher.newBuilder().
setHostname("hostname").
setPort(0).
setComponentName("component").
setInstanceId("instance-id").
setInstanceIndex(1).
build();
return Metrics.MetricPublisherRegisterRequest.newBuilder().setPublisher(publisher).build();
}
@Override
public Message.Builder getResponseBuilder() {
return Metrics.MetricPublisherRegisterResponse.newBuilder();
}
}
private class MetricsManagerClientResponseHandler
implements HeronServerTester.TestResponseHandler {
private int maxMessages;
MetricsManagerClientResponseHandler(int maxMessages) {
this.maxMessages = maxMessages;
}
@Override
public void handleResponse(HeronClient client, StatusCode status,
Object ctx, Message response) {
for (int i = 0; i < maxMessages; i++) {
sendMessage(client);
}
}
private void sendMessage(HeronClient client) {
Metrics.MetricPublisherPublishMessage.Builder builder =
Metrics.MetricPublisherPublishMessage.newBuilder();
for (int j = 0; j < METRICS_COUNT; j++) {
builder.addMetrics(
Metrics.MetricDatum.newBuilder()
.setName(METRIC_NAME)
.setValue(METRIC_VALUE).build());
}
for (int j = 0; j < METRICS_COUNT; j++) {
builder.addExceptions(
Metrics.ExceptionData.newBuilder()
.setStacktrace(STACK_TRACE)
.setLasttime(LAST_TIME)
.setFirsttime(FIRST_TIME)
.setCount(EXCEPTION_COUNT)
.setLogging(LOGGING).build());
}
client.sendMessage(builder.build());
}
}
}