Skip to content

Instantly share code, notes, and snippets.

@markoradinovic
Forked from fastnsilver/JettyConfig.java
Created January 16, 2016 20:22
Show Gist options
  • Save markoradinovic/09c5eddbe507497556d6 to your computer and use it in GitHub Desktop.
Save markoradinovic/09c5eddbe507497556d6 to your computer and use it in GitHub Desktop.
A possible way to bring together AWS CloudWatch and ServoMetrics observers in a Jetty Container
@Configuration
public class JettyConfig {
@Autowired
private MetricRegistry metricRegistry;
public Server jettyServer(int maxThreads, int minThreads, int idleTimeout) {
QueuedThreadPool threadPool = new InstrumentedQueuedThreadPool(metricRegistry);
threadPool.setMaxThreads(maxThreads);
threadPool.setMinThreads(minThreads);
threadPool.setIdleTimeout(idleTimeout);
return new Server(threadPool);
}
// @see http://wiki.eclipse.org/Jetty/Howto/High_Load
// @see http://jdpgrailsdev.github.io/blog/2014/10/07/spring_boot_jetty_thread_pool.html
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory(
@Value("${server.port:8080}") final int port,
@Value("${jetty.threadPool.maxThreads:1000}") final int maxThreads,
@Value("${jetty.threadPool.minThreads:100}") final int minThreads,
@Value("${jetty.threadPool.idleTimeout:60000}") final int idleTimeout) {
final JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory(port);
factory.addServerCustomizers(customizer -> { jettyServer(maxThreads, minThreads, idleTimeout); });
return factory;
}
}
/**
* {@link MetricObserver} to convert Servo metrics into Spring Boot {@link Metric}
* instances.
*/
public final class ServoMetricObserver extends BaseMetricObserver {
private final MetricWriter metrics;
public ServoMetricObserver(MetricWriter metrics) {
super("spring-boot");
this.metrics = metrics;
}
@Override
public void updateImpl(List<com.netflix.servo.Metric> servoMetrics) {
for (com.netflix.servo.Metric servoMetric : servoMetrics) {
MonitorConfig config = servoMetric.getConfig();
String type = config.getTags().getValue("type");
String key = new StringBuilder(type).append(".servo.")
.append(config.getName()).toString().toLowerCase();
if (servoMetric.hasNumberValue()) {
this.metrics.set(new Metric<Number>(key,
servoMetric.getNumberValue(), new Date(servoMetric
.getTimestamp())));
}
}
}
}
/**
* Modeled after {@link org.springframework.cloud.netflix.servo.ServoMetricCollector}
* Scans for {@link com.netflix.servo.publish.MetricObserver} implementations on classpath and
* adds them to {@link com.netflix.servo.publish.PollRunnable} making this
* implementation open for extension
*/
public class UnifiedMetricCollector {
private final Logger log = LoggerFactory.getLogger(getClass());
@Value("${spring.aws.cloudwatch.metrics.polling.timeUnit:SECONDS}")
private String timeUnit;
@Value("${spring.aws.cloudwatch.metrics.polling.interval:5}")
private int pollingInterval;
@Autowired
private ListableBeanFactory beanFactory;
public UnifiedMetricCollector() {
PollRunnable task = new PollRunnable(new MonitorRegistryMetricPoller(),
BasicMetricFilter.MATCH_ALL, true, beanFactory.getBeansOfType(MetricObserver.class).values());
if (!PollScheduler.getInstance().isStarted()) {
try {
PollScheduler.getInstance().start();
}
catch (Exception e) {
// Can fail due to race condition with evil singletons (if more than one
// app in same JVM)
log.error("Could not start servo metrics poller", e);
return;
}
}
PollScheduler.getInstance().addPoller(task, pollingInterval, TimeUnit.valueOf(timeUnit.toUpperCase()));
}
@PreDestroy
public void destroy() throws Exception {
log.info("Stopping Servo PollScheduler");
if (PollScheduler.getInstance().isStarted()) {
try {
PollScheduler.getInstance().stop();
}
catch (Exception e) {
log.error("Could not stop servo metrics poller", e);
}
}
}
}
@Configuration
@ConditionalOnMissingBean(value={ServoMetricsAutoConfiguration.class})
@ConditionalOnWebApplication
@ConditionalOnClass({ Monitors.class, MetricReader.class })
@ConditionalOnBean(MetricReader.class)
@AutoConfigureBefore(EndpointAutoConfiguration.class)
@AutoConfigureAfter({ MetricRepositoryAutoConfiguration.class })
public class UnifiedMetricsConfig {
@Configuration
@ConditionalOnAwsCloudEnvironment
@EnableContextCredentials
static class AwsCloudWatchMetricsConfig {
@Value("${spring.application.name}")
private String applicationName;
@Autowired
private AWSCredentials awsCredentials;
@Bean
@ConditionalOnMissingBean
MetricObserver cloudWatchMetricObserver() {
return new CloudWatchMetricObserver(applicationName, "servo.cloudwatch", new AmazonCloudWatchAsyncClient(awsCredentials));
}
}
@Bean
@ConditionalOnMissingBean
public MetricObserver servoMetricObserver(MetricWriter metrics) {
return new ServoMetricObserver(metrics);
}
@Bean
@ConditionalOnMissingBean
public UnifiedMetricCollector unifiedMetricCollector() {
return new UnifiedMetricCollector();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment