/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 gobblin.runtime;
import java.util.Properties;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.hadoop.conf.Configuration;
import org.slf4j.MDC;
import org.slf4j.Logger;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.AbstractIdleService;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import gobblin.configuration.ConfigurationKeys;
import gobblin.metrics.GobblinMetrics;
import gobblin.runtime.fork.Fork;
import gobblin.util.ExecutorsUtils;
/**
* An abstract implementation of {@link TaskStateTracker} that provides basic common functionality for
* platform-specific implementations.
*
* @author Yinan Li
*/
public abstract class AbstractTaskStateTracker extends AbstractIdleService implements TaskStateTracker {
// This is used to schedule and run task metrics updaters
private final ListeningScheduledExecutorService taskMetricsUpdaterExecutor;
private final Logger logger;
public AbstractTaskStateTracker(int coreThreadPoolSize, Logger logger) {
Preconditions.checkArgument(coreThreadPoolSize > 0, "Thread pool size should be positive");
this.taskMetricsUpdaterExecutor = ExecutorsUtils.loggingDecorator(
new ScheduledThreadPoolExecutor(coreThreadPoolSize,
ExecutorsUtils.newThreadFactory(Optional.of(logger), Optional.of("TaskStateTracker-%d"))));
this.logger = logger;
}
public AbstractTaskStateTracker(Properties properties, Logger logger) {
this(Integer.parseInt(properties.getProperty(ConfigurationKeys.TASK_STATE_TRACKER_THREAD_POOL_CORE_SIZE_KEY,
Integer.toString(ConfigurationKeys.DEFAULT_TASK_STATE_TRACKER_THREAD_POOL_CORE_SIZE))), logger);
}
public AbstractTaskStateTracker(Configuration configuration, Logger logger) {
this(Integer.parseInt(configuration.get(ConfigurationKeys.TASK_STATE_TRACKER_THREAD_POOL_CORE_SIZE_KEY,
Integer.toString(ConfigurationKeys.DEFAULT_TASK_STATE_TRACKER_THREAD_POOL_CORE_SIZE))), logger);
}
@Override
protected void startUp() throws Exception {
this.logger.info("Starting the task state tracker");
}
@Override
protected void shutDown() throws Exception {
this.logger.info("Stopping the task state tracker");
ExecutorsUtils.shutdownExecutorService(this.taskMetricsUpdaterExecutor, Optional.of(this.logger));
}
/**
* Schedule a {@link TaskMetricsUpdater}.
*
* @param taskMetricsUpdater the {@link TaskMetricsUpdater} to schedule
* @param task the {@link Task} that the {@link TaskMetricsUpdater} is associated to
* @return a {@link java.util.concurrent.ScheduledFuture} corresponding to the scheduled {@link TaskMetricsUpdater}
*/
protected ScheduledFuture<?> scheduleTaskMetricsUpdater(Runnable taskMetricsUpdater, Task task) {
return this.taskMetricsUpdaterExecutor.scheduleAtFixedRate(taskMetricsUpdater,
task.getTaskContext().getStatusReportingInterval(), task.getTaskContext().getStatusReportingInterval(),
TimeUnit.MILLISECONDS);
}
/**
* A base class providing a default implementation for updating task metrics.
*
* @deprecated see {@link gobblin.instrumented.writer.InstrumentedDataWriterBase}.
*/
@Deprecated
protected class TaskMetricsUpdater implements Runnable {
protected final Task task;
public TaskMetricsUpdater(Task task) {
this.task = task;
}
@Override
public void run() {
MDC.put(ConfigurationKeys.TASK_KEY_KEY, task.getTaskKey());
updateTaskMetrics();
// Log record queue stats/metrics of each fork
for (Optional<Fork> fork : this.task.getForks()) {
if (fork.isPresent() && fork.get().queueStats().isPresent()) {
AbstractTaskStateTracker.this.logger.debug(String.format("Queue stats of fork %d of task %s: %s",
fork.get().getIndex(), this.task.getTaskId(), fork.get().queueStats().get().toString()));
}
}
}
protected void updateTaskMetrics() {
if (GobblinMetrics.isEnabled(this.task.getTaskState().getWorkunit())) {
this.task.updateRecordMetrics();
this.task.updateByteMetrics();
}
}
}
}