/*
* 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.api;
import java.net.URI;
import java.util.Collection;
import com.codahale.metrics.Gauge;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.Service;
import gobblin.annotation.Alpha;
import gobblin.instrumented.GobblinMetricsKeys;
import gobblin.instrumented.Instrumentable;
import gobblin.metrics.ContextAwareCounter;
import gobblin.metrics.ContextAwareGauge;
import gobblin.metrics.GobblinTrackingEvent;
import lombok.Getter;
/**
* A catalog of all the {@link JobSpec}s a Gobblin instance is currently aware of.
*/
@Alpha
public interface JobCatalog extends JobCatalogListenersContainer, Instrumentable {
/** Returns an immutable {@link Collection} of {@link JobSpec}s that are known to the catalog. */
Collection<JobSpec> getJobs();
/** Metrics for the job catalog; null if
* ({@link #isInstrumentationEnabled()}) is false. */
StandardMetrics getMetrics();
/**
* Get a {@link JobSpec} by uri.
* @throws JobSpecNotFoundException if no such JobSpec exists
**/
JobSpec getJobSpec(URI uri) throws JobSpecNotFoundException;
public static class StandardMetrics implements JobCatalogListener {
public static final String NUM_ACTIVE_JOBS_NAME = "numActiveJobs";
public static final String NUM_ADDED_JOBS = "numAddedJobs";
public static final String NUM_DELETED_JOBS = "numDeletedJobs";
public static final String NUM_UPDATED_JOBS = "numUpdatedJobs";
public static final String TRACKING_EVENT_NAME = "JobCatalogEvent";
public static final String JOB_ADDED_OPERATION_TYPE = "JobAdded";
public static final String JOB_DELETED_OPERATION_TYPE = "JobDeleted";
public static final String JOB_UPDATED_OPERATION_TYPE = "JobUpdated";
@Getter private final ContextAwareGauge<Integer> numActiveJobs;
@Getter private final ContextAwareCounter numAddedJobs;
@Getter private final ContextAwareCounter numDeletedJobs;
@Getter private final ContextAwareCounter numUpdatedJobs;
public StandardMetrics(final JobCatalog parent) {
this.numAddedJobs = parent.getMetricContext().contextAwareCounter(NUM_ADDED_JOBS);
this.numDeletedJobs = parent.getMetricContext().contextAwareCounter(NUM_DELETED_JOBS);
this.numUpdatedJobs = parent.getMetricContext().contextAwareCounter(NUM_UPDATED_JOBS);
this.numActiveJobs = parent.getMetricContext().newContextAwareGauge(NUM_ACTIVE_JOBS_NAME,
new Gauge<Integer>() {
@Override public Integer getValue() {
return parent.getJobs().size();
}
});
parent.addListener(this);
}
@Override public void onAddJob(JobSpec addedJob) {
this.numAddedJobs.inc();
submitTrackingEvent(addedJob, JOB_ADDED_OPERATION_TYPE);
}
private void submitTrackingEvent(JobSpec job, String operType) {
submitTrackingEvent(job.getUri(), job.getVersion(), operType);
}
private void submitTrackingEvent(URI jobSpecURI, String jobSpecVersion, String operType) {
GobblinTrackingEvent e = GobblinTrackingEvent.newBuilder()
.setName(TRACKING_EVENT_NAME)
.setNamespace(JobCatalog.class.getName())
.setMetadata(ImmutableMap.<String, String>builder()
.put(GobblinMetricsKeys.OPERATION_TYPE_META, operType)
.put(GobblinMetricsKeys.JOB_SPEC_URI_META, jobSpecURI.toString())
.put(GobblinMetricsKeys.JOB_SPEC_VERSION_META, jobSpecVersion)
.build())
.build();
this.numAddedJobs.getContext().submitEvent(e);
}
@Override
public void onDeleteJob(URI deletedJobURI, String deletedJobVersion) {
this.numDeletedJobs.inc();
submitTrackingEvent(deletedJobURI, deletedJobVersion, JOB_DELETED_OPERATION_TYPE);
}
@Override
public void onUpdateJob(JobSpec updatedJob) {
this.numUpdatedJobs.inc();
submitTrackingEvent(updatedJob, JOB_UPDATED_OPERATION_TYPE);
}
}
}