co.cask.cdap.app.mapreduce.LocalMRJobInfoFetcherTest.java Source code

Java tutorial

Introduction

Here is the source code for co.cask.cdap.app.mapreduce.LocalMRJobInfoFetcherTest.java

Source

/*
 * Copyright  2015 Cask Data, Inc.
 *
 * 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 co.cask.cdap.app.mapreduce;

import co.cask.cdap.api.metrics.MetricStore;
import co.cask.cdap.api.metrics.MetricType;
import co.cask.cdap.api.metrics.MetricValues;
import co.cask.cdap.app.metrics.MapReduceMetrics;
import co.cask.cdap.common.conf.CConfiguration;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.data2.datafabric.dataset.service.DatasetService;
import co.cask.cdap.data2.datafabric.dataset.service.executor.DatasetOpExecutor;
import co.cask.cdap.internal.guice.AppFabricTestModule;
import co.cask.cdap.proto.Id;
import co.cask.cdap.proto.MRJobInfo;
import co.cask.cdap.proto.MRTaskInfo;
import co.cask.cdap.proto.ProgramType;
import co.cask.tephra.TransactionManager;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.hadoop.mapreduce.TaskCounter;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.List;
import java.util.Map;

public class LocalMRJobInfoFetcherTest {
    private static Injector injector;
    private static MetricStore metricStore;

    @BeforeClass
    public static void beforeClass() throws Exception {
        CConfiguration conf = CConfiguration.create();
        conf.set(Constants.AppFabric.OUTPUT_DIR, System.getProperty("java.io.tmpdir"));
        conf.set(Constants.AppFabric.TEMP_DIR, System.getProperty("java.io.tmpdir"));
        injector = startMetricsService(conf);
        metricStore = injector.getInstance(MetricStore.class);
    }

    public static Injector startMetricsService(CConfiguration conf) {
        Injector injector = Guice.createInjector(new AppFabricTestModule(conf));
        injector.getInstance(TransactionManager.class).startAndWait();
        injector.getInstance(DatasetOpExecutor.class).startAndWait();
        injector.getInstance(DatasetService.class).startAndWait();
        return injector;
    }

    @Test
    public void testGetMRJobInfo() throws Exception {
        Id.Program programId = Id.Program.from("fooNamespace", "testApp", ProgramType.MAPREDUCE, "fooMapReduce");
        Id.Run runId = new Id.Run(programId, "run10878");

        Map<String, String> runContext = ImmutableMap.of(Constants.Metrics.Tag.NAMESPACE,
                programId.getNamespaceId(), Constants.Metrics.Tag.APP, programId.getApplicationId(),
                Constants.Metrics.Tag.MAPREDUCE, programId.getId(), Constants.Metrics.Tag.RUN_ID, runId.getId());

        Map<String, String> mapTypeContext = addToContext(runContext, Constants.Metrics.Tag.MR_TASK_TYPE,
                MapReduceMetrics.TaskType.Mapper.getId());

        Map<String, String> reduceTypeContext = addToContext(runContext, Constants.Metrics.Tag.MR_TASK_TYPE,
                MapReduceMetrics.TaskType.Reducer.getId());

        String mapTask1Name = "task_m_01";
        Map<String, String> mapTask1Context = addToContext(mapTypeContext, Constants.Metrics.Tag.INSTANCE_ID,
                mapTask1Name);

        String mapTask2Name = "task_m_02";
        Map<String, String> mapTask2Context = addToContext(mapTypeContext, Constants.Metrics.Tag.INSTANCE_ID,
                mapTask2Name);

        String reduceTaskName = "task_r_01";
        Map<String, String> reduceTaskContext = addToContext(reduceTypeContext, Constants.Metrics.Tag.INSTANCE_ID,
                reduceTaskName);

        // Imitate a MapReduce Job running (gauge mapper and reducer metrics)
        long measureTime = System.currentTimeMillis() / 1000;
        gauge(mapTypeContext, MapReduceMetrics.METRIC_COMPLETION, measureTime, 76L);
        gauge(reduceTypeContext, MapReduceMetrics.METRIC_COMPLETION, measureTime, 52L);

        gauge(mapTask1Context, MapReduceMetrics.METRIC_TASK_COMPLETION, measureTime, 100L);
        gauge(mapTask1Context, MapReduceMetrics.METRIC_TASK_INPUT_RECORDS, measureTime, 32L);
        gauge(mapTask1Context, MapReduceMetrics.METRIC_TASK_OUTPUT_RECORDS, measureTime, 320L);

        gauge(mapTask2Context, MapReduceMetrics.METRIC_TASK_COMPLETION, measureTime, 12L);
        gauge(mapTask2Context, MapReduceMetrics.METRIC_TASK_INPUT_RECORDS, measureTime, 6L);
        gauge(mapTask2Context, MapReduceMetrics.METRIC_TASK_OUTPUT_RECORDS, measureTime, 60L);

        // gauge job-level counters for mappers
        gauge(mapTypeContext, MapReduceMetrics.METRIC_INPUT_RECORDS, measureTime, 38L);
        gauge(mapTypeContext, MapReduceMetrics.METRIC_OUTPUT_RECORDS, measureTime, 380L);

        gauge(reduceTaskContext, MapReduceMetrics.METRIC_TASK_COMPLETION, measureTime, 76L);
        gauge(reduceTaskContext, MapReduceMetrics.METRIC_TASK_INPUT_RECORDS, measureTime, 320L);
        gauge(reduceTaskContext, MapReduceMetrics.METRIC_TASK_OUTPUT_RECORDS, measureTime, 1L);

        // gauge job-level counters for reducers
        gauge(reduceTypeContext, MapReduceMetrics.METRIC_INPUT_RECORDS, measureTime, 320L);
        gauge(reduceTypeContext, MapReduceMetrics.METRIC_OUTPUT_RECORDS, measureTime, 1L);

        LocalMRJobInfoFetcher localMRJobInfoFetcher = injector.getInstance(LocalMRJobInfoFetcher.class);
        MRJobInfo mrJobInfo = localMRJobInfoFetcher.getMRJobInfo(runId);

        // Incomplete because MapReduceMetricsInfo does not provide task-level state and start/end times.
        Assert.assertFalse(mrJobInfo.isComplete());

        // Check job-level counters
        Map<String, Long> jobCounters = mrJobInfo.getCounters();
        Assert.assertEquals((Long) 38L, jobCounters.get(TaskCounter.MAP_INPUT_RECORDS.name()));
        Assert.assertEquals((Long) 380L, jobCounters.get(TaskCounter.MAP_OUTPUT_RECORDS.name()));
        Assert.assertEquals((Long) 320L, jobCounters.get(TaskCounter.REDUCE_INPUT_RECORDS.name()));
        Assert.assertEquals((Long) 1L, jobCounters.get(TaskCounter.REDUCE_OUTPUT_RECORDS.name()));

        // Ensure all tasks show up
        List<MRTaskInfo> mapTasks = mrJobInfo.getMapTasks();
        List<MRTaskInfo> reduceTasks = mrJobInfo.getReduceTasks();
        Assert.assertEquals(2, mapTasks.size());
        Assert.assertEquals(1, reduceTasks.size());

        MRTaskInfo mapTask1 = findByTaskId(mapTasks, mapTask1Name);
        MRTaskInfo mapTask2 = findByTaskId(mapTasks, mapTask2Name);
        MRTaskInfo reduceTask = findByTaskId(reduceTasks, reduceTaskName);

        // Check task-level counters
        Map<String, Long> mapTask1Counters = mapTask1.getCounters();
        Assert.assertEquals((Long) 32L, mapTask1Counters.get(TaskCounter.MAP_INPUT_RECORDS.name()));
        Assert.assertEquals((Long) 320L, mapTask1Counters.get(TaskCounter.MAP_OUTPUT_RECORDS.name()));

        Map<String, Long> mapTask2Counters = mapTask2.getCounters();
        Assert.assertEquals((Long) 6L, mapTask2Counters.get(TaskCounter.MAP_INPUT_RECORDS.name()));
        Assert.assertEquals((Long) 60L, mapTask2Counters.get(TaskCounter.MAP_OUTPUT_RECORDS.name()));

        Map<String, Long> reduceTaskCounters = reduceTask.getCounters();
        Assert.assertEquals((Long) 320L, reduceTaskCounters.get(TaskCounter.REDUCE_INPUT_RECORDS.name()));
        Assert.assertEquals((Long) 1L, reduceTaskCounters.get(TaskCounter.REDUCE_OUTPUT_RECORDS.name()));

        // Checking progress
        float permittedProgressDelta = 0.01F;
        Assert.assertEquals(0.76F, mrJobInfo.getMapProgress(), permittedProgressDelta);
        Assert.assertEquals(0.52F, mrJobInfo.getReduceProgress(), permittedProgressDelta);

        Assert.assertEquals(1.0F, mapTask1.getProgress(), permittedProgressDelta);
        Assert.assertEquals(0.12F, mapTask2.getProgress(), permittedProgressDelta);
        Assert.assertEquals(0.76F, reduceTask.getProgress(), permittedProgressDelta);

    }

    private void gauge(Map<String, String> context, String metric, long timestamp, Long value) throws Exception {
        metricStore.add(new MetricValues(context, metric, timestamp, value, MetricType.GAUGE));
    }

    // Returned copied map, with new key-value pair.
    private Map<String, String> addToContext(Map<String, String> context, String key, String value) {
        return ImmutableMap.<String, String>builder().putAll(context).put(key, value).build();
    }

    private MRTaskInfo findByTaskId(List<MRTaskInfo> taskInfos, String taskId) {
        for (MRTaskInfo taskInfo : taskInfos) {
            if (taskInfo.getTaskId().equals(taskId)) {
                return taskInfo;
            }
        }
        throw new IllegalArgumentException(
                String.format("TaskId: %s not found in list of TaskInfos: %s", taskId, taskInfos));
    }
}