// ================================================================================================= // Copyright 2011 Twitter, Inc. // ------------------------------------------------------------------------------------------------- // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this work except in compliance with the License. // You may obtain a copy of the License in the LICENSE file, or 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.common.application.modules; import java.util.logging.Logger; import com.google.common.base.Supplier; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; import com.twitter.common.application.ShutdownRegistry; import com.twitter.common.args.Arg; import com.twitter.common.args.CmdLine; import com.twitter.common.base.Command; import com.twitter.common.quantity.Amount; import com.twitter.common.quantity.Time; import com.twitter.common.stats.JvmStats; import com.twitter.common.stats.Stat; import com.twitter.common.stats.StatImpl; import com.twitter.common.stats.StatRegistry; import com.twitter.common.stats.Stats; import com.twitter.common.stats.TimeSeriesRepository; import com.twitter.common.stats.TimeSeriesRepositoryImpl; import com.twitter.common.util.BuildInfo; import static com.google.common.base.Preconditions.checkNotNull; /** * Binding module for injections related to the in-process stats system. * * This modules supports two command line arguments: * <ul> * <li>{@code stat_sampling_interval} - Statistic value sampling interval. * <li>{@code stat_retention_period} - Time for a stat to be retained in memory before expring. * </ul> * * Bindings required by this module: * <ul> * <li>{@code ShutdownRegistry} - Shutdown hook registry. * <li>{@code BuildInfo} - Build information for the application. * </ul> * * @author William Farner */ public class StatsModule extends AbstractModule { @CmdLine(name = "stat_sampling_interval", help = "Statistic value sampling interval.") private static final Arg<Amount<Long, Time>> SAMPLING_INTERVAL = Arg.create(Amount.of(1L, Time.SECONDS)); @CmdLine(name = "stat_retention_period", help = "Time for a stat to be retained in memory before expiring.") private static final Arg<Amount<Long, Time>> RETENTION_PERIOD = Arg.create(Amount.of(1L, Time.HOURS)); public static Amount<Long, Time> getSamplingInterval() { return SAMPLING_INTERVAL.get(); } @Override protected void configure() { requireBinding(ShutdownRegistry.class); requireBinding(BuildInfo.class); // Bindings for TimeSeriesRepositoryImpl. bind(StatRegistry.class).toInstance(Stats.STAT_REGISTRY); bind(new TypeLiteral<Amount<Long, Time>>() { }) .annotatedWith(Names.named(TimeSeriesRepositoryImpl.SAMPLE_RETENTION_PERIOD)) .toInstance(RETENTION_PERIOD.get()); bind(new TypeLiteral<Amount<Long, Time>>() { }) .annotatedWith(Names.named(TimeSeriesRepositoryImpl.SAMPLE_PERIOD)) .toInstance(SAMPLING_INTERVAL.get()); bind(TimeSeriesRepository.class).to(TimeSeriesRepositoryImpl.class).in(Singleton.class); bind(new TypeLiteral<Supplier<Iterable<Stat<?>>>>() { }).toInstance( new Supplier<Iterable<Stat<?>>>() { @Override public Iterable<Stat<?>> get() { return Stats.getVariables(); } } ); LifecycleModule.bindStartupAction(binder(), StartStatPoller.class); } public static final class StartStatPoller implements Command { private static final Logger LOG = Logger.getLogger(StartStatPoller.class.getName()); private final ShutdownRegistry shutdownRegistry; private final BuildInfo buildInfo; private final TimeSeriesRepository timeSeriesRepository; @Inject StartStatPoller( ShutdownRegistry shutdownRegistry, BuildInfo buildInfo, TimeSeriesRepository timeSeriesRepository) { this.shutdownRegistry = checkNotNull(shutdownRegistry); this.buildInfo = checkNotNull(buildInfo); this.timeSeriesRepository = checkNotNull(timeSeriesRepository); } @Override public void execute() { LOG.info("Build information: " + buildInfo.getProperties()); for (final BuildInfo.Key key : BuildInfo.Key.values()) { Stats.exportString(new StatImpl<String>(Stats.normalizeName(key.value)) { @Override public String read() { return buildInfo.getProperties().getProperty(key.value); } }); } JvmStats.export(); timeSeriesRepository.start(shutdownRegistry); } } }