Repository: zest-java Updated Branches: refs/heads/develop 812f1446c -> ef0c40c0c
ZEST-192 Introduce Codahale Metrics extension Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/8453ce39 Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/8453ce39 Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/8453ce39 Branch: refs/heads/develop Commit: 8453ce39785d97052cdb246634012fbc094ffb31 Parents: 812f144 Author: Paul Merlin <[email protected]> Authored: Mon Nov 7 14:53:47 2016 +0100 Committer: Paul Merlin <[email protected]> Committed: Mon Nov 7 14:55:47 2016 +0100 ---------------------------------------------------------------------- extensions/metrics-codahale/build.gradle | 37 ++ extensions/metrics-codahale/dev-status.xml | 39 +++ .../src/docs/metrics-codahale.txt | 55 +++ .../zest/metrics/codahale/CodahaleCounter.java | 60 ++++ .../zest/metrics/codahale/CodahaleGauge.java | 41 +++ .../metrics/codahale/CodahaleHealthCheck.java | 66 ++++ .../metrics/codahale/CodahaleHistogram.java | 41 +++ .../zest/metrics/codahale/CodahaleMeter.java | 47 +++ .../codahale/CodahaleMetricsAssembler.java | 122 +++++++ .../codahale/CodahaleMetricsDeclaration.java | 36 ++ .../metrics/codahale/CodahaleMetricsMixin.java | 269 +++++++++++++++ .../codahale/CodahaleMetricsProvider.java | 35 ++ .../zest/metrics/codahale/CodahaleTimer.java | 41 +++ .../apache/zest/metrics/codahale/package.html | 24 ++ .../metrics/codahale/CodahaleMetricsTest.java | 79 +++++ .../test/metrics/AbstractZestMetricsTest.java | 339 +++++++++++++++++++ libraries.gradle | 5 + libraries/metrics/build.gradle | 1 + libraries/metrics/src/docs/metrics.txt | 2 +- .../metrics/CodahaleTimingCaptureTest.java | 59 ++++ manual/src/docs/userguide/extensions.txt | 4 + .../src/resources/js/progressive-enhancement.js | 2 +- settings.gradle | 1 + 23 files changed, 1403 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/build.gradle b/extensions/metrics-codahale/build.gradle new file mode 100644 index 0000000..c43f760 --- /dev/null +++ b/extensions/metrics-codahale/build.gradle @@ -0,0 +1,37 @@ +/* + * 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. + * + * + */ + +description = "Apache Zest⢠Codahale Metrics Extension" + +jar { manifest { name = "Apache Zest⢠Extension - Metrics - Codahale" }} + +dependencies { + + compile project(":org.apache.zest.core:org.apache.zest.core.bootstrap") + compile libraries.codahale_metrics + + testCompile project(":org.apache.zest.core:org.apache.zest.core.testsupport") + testCompile project(":org.apache.zest.libraries:org.apache.zest.library.jmx") + testCompile project(":org.apache.zest.libraries:org.apache.zest.library.metrics") + + testRuntime project( ":org.apache.zest.core:org.apache.zest.core.runtime" ) + testRuntime libraries.logback + +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/dev-status.xml ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/dev-status.xml b/extensions/metrics-codahale/dev-status.xml new file mode 100644 index 0000000..fb63508 --- /dev/null +++ b/extensions/metrics-codahale/dev-status.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!-- + ~ 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. + ~ + ~ + --> + +<module xmlns="http://zest.apache.org/schemas/2008/dev-status/1" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://zest.apache.org/schemas/2008/dev-status/1 + http://zest.apache.org/schemas/2008/dev-status/1/dev-status.xsd"> + <status> + <!--none,early,beta,stable,mature--> + <codebase>stable</codebase> + + <!-- none, brief, good, complete --> + <documentation>brief</documentation> + + <!-- none, some, good, complete --> + <unittests>some</unittests> + </status> + <licenses> + <license>ALv2</license> + </licenses> +</module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/docs/metrics-codahale.txt ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/docs/metrics-codahale.txt b/extensions/metrics-codahale/src/docs/metrics-codahale.txt new file mode 100644 index 0000000..6e29384 --- /dev/null +++ b/extensions/metrics-codahale/src/docs/metrics-codahale.txt @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////// + * 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. +/////////////////////////////////////////////////////////////// + +[[extension-metrics-metrics, Codahale Metrics]] += Codahale Metrics = + +[devstatus] +-------------- +source=extensions/metrics-codahale/dev-status.xml +-------------- + +Metrics extension backed by the http://metrics.dropwizard.io/[Codahale] metrics library +maintained by the http://www.dropwizard.io/[Dropwizard] folks. + +include::../../build/docs/buildinfo/artifact.txt[] + +== Assembly == + +Assembly is done using the provided Assembler: + +[snippet,java] +---- +source=extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java +tag=assembly +---- + +== Reporting to Ganglia or Graphite == + +Dropwizard provide metrics reporter for Ganglia or Graphite, see the http://metrics.dropwizard.io/[official documentation] +for details. + +To register reporters you need a handle to the underlying `MetricsRegistry`, the `CodahaleMetricsProvider` service +provide accessor to it: + +[snippet,java] +---- +source=extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java +tag=registry +---- http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java new file mode 100644 index 0000000..63098ef --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleCounter.java @@ -0,0 +1,60 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.Counter; +import org.apache.zest.api.metrics.MetricsCounter; + +public class CodahaleCounter + implements MetricsCounter +{ + private Counter counter; + + public CodahaleCounter( Counter counter ) + { + + this.counter = counter; + } + + @Override + public void increment() + { + counter.inc(); + } + + @Override + public void increment( int steps ) + { + counter.inc( steps ); + } + + @Override + public void decrement() + { + counter.dec(); + } + + @Override + public void decrement( int steps ) + { + counter.dec( steps ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java new file mode 100644 index 0000000..33abca3 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleGauge.java @@ -0,0 +1,41 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.Gauge; +import org.apache.zest.api.metrics.MetricsGauge; + +public class CodahaleGauge<T> + implements MetricsGauge<T> +{ + private Gauge<T> gauge; + + public CodahaleGauge( Gauge<T> gauge ) + { + this.gauge = gauge; + } + + @Override + public T value() + { + return gauge.getValue(); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java new file mode 100644 index 0000000..ac73c78 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHealthCheck.java @@ -0,0 +1,66 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.health.HealthCheck; +import org.apache.zest.api.metrics.MetricsHealthCheck; + +public class CodahaleHealthCheck + implements MetricsHealthCheck +{ + private final MetricsHealthCheck check; + + public CodahaleHealthCheck( MetricsHealthCheck check ) + { + this.check = check; + } + + @Override + public Result check() + throws Exception + { + return check.check(); + } + + static Result wrap( HealthCheck.Result result ) + { + return new Result( result.isHealthy(), result.getMessage(), result.getError() ); + } + + static HealthCheck.Result unwrap( Result result ) + { + String message = result.getMessage(); + if( result.isHealthy() ) + { + if( message != null ) + { + return HealthCheck.Result.healthy( message ); + } + return HealthCheck.Result.healthy(); + } + Throwable error = result.getException(); + if( error != null ) + { + return HealthCheck.Result.unhealthy( error ); + } + return HealthCheck.Result.unhealthy( message ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java new file mode 100644 index 0000000..def8635 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleHistogram.java @@ -0,0 +1,41 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.Histogram; +import org.apache.zest.api.metrics.MetricsHistogram; + +public class CodahaleHistogram + implements MetricsHistogram +{ + private Histogram histogram; + + public CodahaleHistogram( Histogram histogram ) + { + this.histogram = histogram; + } + + @Override + public void update( long newValue ) + { + histogram.update( newValue ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java new file mode 100644 index 0000000..63b5d39 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMeter.java @@ -0,0 +1,47 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.Meter; +import org.apache.zest.api.metrics.MetricsMeter; + +public class CodahaleMeter + implements MetricsMeter +{ + private Meter meter; + + public CodahaleMeter( Meter meter ) + { + this.meter = meter; + } + + @Override + public void mark() + { + meter.mark(); + } + + @Override + public void mark( int numberOfEvents ) + { + meter.mark( numberOfEvents ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java new file mode 100644 index 0000000..be10795 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsAssembler.java @@ -0,0 +1,122 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.ConsoleReporter; +import com.codahale.metrics.CsvReporter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Reporter; +import com.codahale.metrics.Slf4jReporter; +import org.apache.zest.bootstrap.Assemblers; +import org.apache.zest.bootstrap.AssemblyException; +import org.apache.zest.bootstrap.ModuleAssembly; +import org.apache.zest.bootstrap.ServiceDeclaration; + +import java.io.File; +import java.io.PrintStream; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +public class CodahaleMetricsAssembler + extends Assemblers.VisibilityIdentity<CodahaleMetricsAssembler> +{ + private final CodahaleMetricsDeclaration declaration = new CodahaleMetricsDeclaration(); + + public CodahaleMetricsAssembler withPrefix( String prefix ) + { + declaration.prefix = prefix; + return this; + } + + public CodahaleMetricsAssembler withFullyQualifiedClassNames() + { + declaration.fqcn = true; + return this; + } + + public CodahaleMetricsAssembler withSimpleClassNames() + { + declaration.fqcn = false; + return this; + } + + public CodahaleMetricsAssembler withJmx() + { + declaration.jmx = true; + return this; + } + + public CodahaleMetricsAssembler withoutJmx() + { + declaration.jmx = false; + return this; + } + + public CodahaleMetricsAssembler withConsoleReporter( PrintStream out, long period, TimeUnit timeunit ) + { + declaration.reportersFactories.add( metricRegistry -> { + ConsoleReporter reporter = ConsoleReporter.forRegistry( metricRegistry ).outputTo( out ).build(); + reporter.start( period, timeunit ); + return reporter; + }); + return this; + } + + public CodahaleMetricsAssembler withSlf4jReporter( Slf4jReporter.LoggingLevel level, long period, TimeUnit timeunit ) + { + declaration.reportersFactories.add( metricRegistry -> { + Slf4jReporter reporter = Slf4jReporter.forRegistry( metricRegistry ).withLoggingLevel( level ).build(); + reporter.start( period, timeunit ); + return reporter; + }); + return this; + } + + public CodahaleMetricsAssembler withCsvReporter( File outDirectory, long period, TimeUnit timeunit ) + { + declaration.reportersFactories.add( metricRegistry -> { + CsvReporter reporter = CsvReporter.forRegistry( metricRegistry ).build( outDirectory ); + reporter.start( period, timeunit ); + return reporter; + }); + return this; + } + + public CodahaleMetricsAssembler withReporter( Function<MetricRegistry, Reporter> factory ) + { + declaration.reportersFactories.add( factory ); + return this; + } + + @Override + public void assemble( ModuleAssembly module ) + throws AssemblyException + { + ServiceDeclaration service = module.services( CodahaleMetricsProvider.class ) + .setMetaInfo( declaration ) + .instantiateOnStartup() + .visibleIn( visibility() ); + if( hasIdentity() ) + { + service.identifiedBy( identity() ); + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java new file mode 100644 index 0000000..dde2d13 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsDeclaration.java @@ -0,0 +1,36 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Reporter; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +class CodahaleMetricsDeclaration +{ + String prefix; + + boolean fqcn = false; + + boolean jmx = true; + + final List<Function<MetricRegistry, Reporter>> reportersFactories = new ArrayList<>(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java new file mode 100644 index 0000000..553fc15 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsMixin.java @@ -0,0 +1,269 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.Gauge; +import com.codahale.metrics.JmxReporter; +import com.codahale.metrics.MetricFilter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Reporter; +import com.codahale.metrics.health.HealthCheck; +import com.codahale.metrics.health.HealthCheckRegistry; +import org.apache.zest.api.activation.PassivationException; +import org.apache.zest.api.injection.scope.Structure; +import org.apache.zest.api.injection.scope.Uses; +import org.apache.zest.api.metrics.Metric; +import org.apache.zest.api.metrics.MetricsCounter; +import org.apache.zest.api.metrics.MetricsCounterFactory; +import org.apache.zest.api.metrics.MetricsGauge; +import org.apache.zest.api.metrics.MetricsGaugeFactory; +import org.apache.zest.api.metrics.MetricsHealthCheck; +import org.apache.zest.api.metrics.MetricsHealthCheckFactory; +import org.apache.zest.api.metrics.MetricsHistogram; +import org.apache.zest.api.metrics.MetricsHistogramFactory; +import org.apache.zest.api.metrics.MetricsMeter; +import org.apache.zest.api.metrics.MetricsMeterFactory; +import org.apache.zest.api.metrics.MetricsTimer; +import org.apache.zest.api.metrics.MetricsTimerFactory; +import org.apache.zest.api.service.ServiceDescriptor; +import org.apache.zest.api.structure.Application; +import org.apache.zest.spi.metrics.MetricsProviderAdapter; + +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Stream; + +import static com.codahale.metrics.MetricRegistry.name; + +public class CodahaleMetricsMixin extends MetricsProviderAdapter + implements CodahaleMetricsProvider +{ + @Structure + private Application app; + + @Uses + private ServiceDescriptor descriptor; + + private final List<Reporter> reporters = new ArrayList<>(); + + private MetricRegistry metricRegistry; + private HealthCheckRegistry healthCheckRegistry; + private String prefix; + private boolean fqcn; + + @Override + public void activateService() { + metricRegistry = new MetricRegistry(); + healthCheckRegistry = new HealthCheckRegistry(); + CodahaleMetricsDeclaration declaration = descriptor.metaInfo( CodahaleMetricsDeclaration.class ); + prefix = declaration.prefix != null ? declaration.prefix : app.name(); + fqcn = declaration.fqcn; + if( declaration.jmx ) + { + JmxReporter jmxReporter = JmxReporter.forRegistry( metricRegistry ).build(); + jmxReporter.start(); + reporters.add( jmxReporter ); + } + for( Function<MetricRegistry, Reporter> reporterFactory : declaration.reportersFactories) + { + reporters.add( reporterFactory.apply( metricRegistry ) ); + } + } + + @Override + public void passivateService() throws PassivationException { + List<Exception> errors = new ArrayList<>(); + for( Reporter reporter : reporters ) + { + if( Closeable.class.isAssignableFrom( reporter.getClass() ) ) + try + { + ( (Closeable) reporter ).close(); + } + catch ( IOException ex ) + { + errors.add( ex ); + } + } + reporters.clear(); + try + { + metricRegistry.removeMatching( MetricFilter.ALL ); + } + catch( Exception ex ) + { + errors.add( ex ); + } + metricRegistry = null; + for( String healthCheckName : healthCheckRegistry.getNames() ) + { + healthCheckRegistry.unregister( healthCheckName ); + } + healthCheckRegistry = null; + prefix = null; + if( !errors.isEmpty() ) + { + throw new PassivationException( errors ); + } + } + + @Override + public MetricRegistry metricRegistry() + { + return metricRegistry; + } + + @Override + public HealthCheckRegistry healthCheckRegistry() + { + return healthCheckRegistry; + } + + @Override + protected MetricsTimerFactory createMetricsTimerFactory() + { + return new MetricsTimerFactory() + { + @Override + public MetricsTimer createTimer( String name ) + { + return new CodahaleTimer( metricRegistry.timer( name( prefix, name ) ) ); + } + + @Override + public Stream<Metric> registered() + { + return metricRegistry.getTimers().values().stream().map( CodahaleTimer::new ); + } + }; + } + + @Override + protected MetricsMeterFactory createMetricsMeterFactory() + { + return new MetricsMeterFactory() + { + @Override + public MetricsMeter createMeter( String name ) + { + return new CodahaleMeter( metricRegistry.meter( name( prefix, name ) ) ); + } + + @Override + public Stream<Metric> registered() + { + return metricRegistry.getMeters().values().stream().map( CodahaleMeter::new ); + } + }; + } + + @Override + protected MetricsHistogramFactory createMetricsHistogramFactory() + { + return new MetricsHistogramFactory() + { + @Override + public MetricsHistogram createHistogram( String name ) + { + return new CodahaleHistogram( metricRegistry.histogram( name( prefix, name ) ) ); + } + + @Override + public Stream<Metric> registered() + { + return metricRegistry.getHistograms().values().stream().map( CodahaleHistogram::new ); + } + }; + } + + @Override + protected MetricsHealthCheckFactory createMetricsHealthCheckFactory() + { + return new MetricsHealthCheckFactory() + { + @Override + public MetricsHealthCheck registerHealthCheck( String name, MetricsHealthCheck check ) + { + HealthCheck codahaleCheck = new HealthCheck() { + @Override + protected Result check() throws Exception { + return CodahaleHealthCheck.unwrap( check.check() ); + } + }; + healthCheckRegistry.register( name( prefix, name ), codahaleCheck ); + return new CodahaleHealthCheck( check ); + } + + @Override + public Stream<Metric> registered() + { + return healthCheckRegistry.getNames().stream().map( name -> new MetricsHealthCheck() { + @Override + public Result check() throws Exception { + return CodahaleHealthCheck.wrap( healthCheckRegistry.runHealthCheck( name ) ); + } + }); + } + }; + } + + @Override + protected MetricsGaugeFactory createMetricsGaugeFactory() + { + return new MetricsGaugeFactory() + { + @Override + public <T> MetricsGauge<T> registerGauge( String name, final MetricsGauge<T> gauge ) + { + Gauge<T> codahaleGauge = gauge::value; + metricRegistry.register( name( prefix, name ), codahaleGauge ); + return new CodahaleGauge<>( codahaleGauge ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public Stream<Metric> registered() + { + return metricRegistry.getGauges().values().stream().map( CodahaleGauge::new ); + } + }; + } + + @Override + protected MetricsCounterFactory createMetricsCounterFactory() + { + return new MetricsCounterFactory() + { + @Override + public MetricsCounter createCounter( String name ) + { + return new CodahaleCounter( metricRegistry.counter( name( prefix, name) ) ); + } + + @Override + public Stream<Metric> registered() + { + return metricRegistry.getCounters().values().stream().map( CodahaleCounter::new ); + } + }; + } + +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java new file mode 100644 index 0000000..e6a23d9 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleMetricsProvider.java @@ -0,0 +1,35 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.health.HealthCheckRegistry; +import org.apache.zest.api.metrics.MetricsProvider; +import org.apache.zest.api.mixin.Mixins; +import org.apache.zest.api.service.ServiceActivation; + +@Mixins( CodahaleMetricsMixin.class ) +public interface CodahaleMetricsProvider + extends MetricsProvider, ServiceActivation +{ + MetricRegistry metricRegistry(); + + HealthCheckRegistry healthCheckRegistry(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java new file mode 100644 index 0000000..f1b2522 --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/CodahaleTimer.java @@ -0,0 +1,41 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.Timer; +import org.apache.zest.api.metrics.MetricsTimer; + +public class CodahaleTimer + implements MetricsTimer +{ + private Timer timer; + + public CodahaleTimer( Timer timer ) + { + this.timer = timer; + } + + @Override + public Context start() + { + return timer.time()::stop; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html new file mode 100644 index 0000000..5a46cfb --- /dev/null +++ b/extensions/metrics-codahale/src/main/java/org/apache/zest/metrics/codahale/package.html @@ -0,0 +1,24 @@ +<!-- + ~ 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. + ~ + ~ + --> +<html> + <body> + <h2>Codahale Metrics.</h2> + </body> +</html> http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java b/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java new file mode 100644 index 0000000..ebac646 --- /dev/null +++ b/extensions/metrics-codahale/src/test/java/org/apache/zest/metrics/codahale/CodahaleMetricsTest.java @@ -0,0 +1,79 @@ +/* + * 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 org.apache.zest.metrics.codahale; + +import com.codahale.metrics.MetricRegistry; +import org.apache.zest.api.activation.ActivationException; +import org.apache.zest.api.activation.PassivationException; +import org.apache.zest.api.structure.Module; +import org.apache.zest.bootstrap.Assembler; +import org.apache.zest.bootstrap.Assemblers; +import org.apache.zest.test.metrics.AbstractZestMetricsTest; +import org.apache.zest.test.metrics.MetricValuesProvider; +import org.junit.Test; + +import java.util.Collection; + +public class CodahaleMetricsTest extends AbstractZestMetricsTest +{ + @Override + protected Assemblers.Visible<? extends Assembler> metricsAssembler() + { + // START SNIPPET: assembly + return new CodahaleMetricsAssembler(); + // END SNIPPET: assembly + } + + @Test + public void uowTimerCodahale() throws PassivationException, ActivationException + { + assertUowTimer( codahaleMetricValuesProvider() ); + } + + @Test + public void timingCaptureCodahale() throws PassivationException, ActivationException + { + assertTimingCapture( codahaleMetricValuesProvider() ); + } + + private MetricValuesProvider codahaleMetricValuesProvider() + { + Module module = metricsModule(); + // START SNIPPET: registry + CodahaleMetricsProvider metricsProvider = module.findService( CodahaleMetricsProvider.class ).get(); + // END SNIPPET: registry + return new MetricValuesProvider() + { + @Override + public Collection<String> registeredMetricNames() + { + // START SNIPPET: registry + MetricRegistry metricRegistry = metricsProvider.metricRegistry(); + // END SNIPPET: registry + return metricRegistry.getNames(); + } + + @Override + public long timerCount( String timerName ) + { + MetricRegistry metricRegistry = metricsProvider.metricRegistry(); + return metricRegistry.timer( timerName ).getCount(); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java ---------------------------------------------------------------------- diff --git a/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java b/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java new file mode 100644 index 0000000..4fb767f --- /dev/null +++ b/extensions/metrics-codahale/src/test/java/org/apache/zest/test/metrics/AbstractZestMetricsTest.java @@ -0,0 +1,339 @@ +/* + * 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 org.apache.zest.test.metrics; + +import org.apache.zest.api.activation.ActivationException; +import org.apache.zest.api.activation.PassivationException; +import org.apache.zest.api.association.ManyAssociation; +import org.apache.zest.api.common.Visibility; +import org.apache.zest.api.concern.Concerns; +import org.apache.zest.api.entity.EntityBuilder; +import org.apache.zest.api.identity.Identity; +import org.apache.zest.api.identity.StringIdentity; +import org.apache.zest.api.injection.scope.Structure; +import org.apache.zest.api.mixin.Mixins; +import org.apache.zest.api.property.Property; +import org.apache.zest.api.service.ServiceActivation; +import org.apache.zest.api.structure.Module; +import org.apache.zest.api.unitofwork.NoSuchEntityException; +import org.apache.zest.api.unitofwork.UnitOfWork; +import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern; +import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation; +import org.apache.zest.bootstrap.ApplicationAssembly; +import org.apache.zest.bootstrap.Assembler; +import org.apache.zest.bootstrap.Assemblers; +import org.apache.zest.bootstrap.AssemblyException; +import org.apache.zest.bootstrap.LayerAssembly; +import org.apache.zest.bootstrap.ModuleAssembly; +import org.apache.zest.library.metrics.TimingCapture; +import org.apache.zest.library.metrics.TimingCaptureAllConcern; +import org.apache.zest.library.metrics.TimingCaptureConcern; +import org.apache.zest.test.AbstractZestBaseTest; +import org.apache.zest.test.EntityTestAssembler; +import org.apache.zest.test.metrics.MetricValuesProvider; +import org.apache.zest.test.util.JmxFixture; +import org.junit.Test; + +import java.util.Collection; + +import static java.util.stream.Collectors.toList; +import static org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY; +import static org.apache.zest.api.usecase.UsecaseBuilder.newUsecase; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertThat; + +// TODO Test errors +public abstract class AbstractZestMetricsTest extends AbstractZestBaseTest +{ + public interface Person + { + Property<String> name(); + } + + public interface PersonList + { + Identity LIST_ID = StringIdentity.fromString( "person-list" ); + + ManyAssociation<Person> all(); + } + + @Concerns( {TimingCaptureAllConcern.class, UnitOfWorkConcern.class} ) + @Mixins( CommandsMixin.class ) + public interface Commands extends ServiceActivation + { + @UnitOfWorkPropagation( MANDATORY ) + Person create( Identity id, String name ); + + @UnitOfWorkPropagation( MANDATORY ) + void rename( Identity id, String newName ); + + @UnitOfWorkPropagation( MANDATORY ) + void delete( Identity id ); + } + + public static class CommandsMixin implements Commands + { + @Structure + private Module module; + + @Override + public void activateService() throws Exception + { + try (UnitOfWork uow = module.unitOfWorkFactory().newUnitOfWork( newUsecase( "Init Person List" ) ) ) + { + try + { + uow.get( PersonList.class, PersonList.LIST_ID ); + } + catch( NoSuchEntityException ex ) + { + uow.newEntity( PersonList.class, PersonList.LIST_ID ); + uow.complete(); + } + } + } + + @Override + public void passivateService() + { + } + + @Override + public Person create( Identity id, String name ) + { + UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork(); + PersonList list = uow.get( PersonList.class, PersonList.LIST_ID ); + EntityBuilder<Person> builder = uow.newEntityBuilder( Person.class, id ); + builder.instance().name().set( name ); + Person person = builder.newInstance(); + list.all().add( person ); + return person; + } + + @Override + public void rename( Identity id, String newName ) + { + module.unitOfWorkFactory().currentUnitOfWork().get( Person.class, id ).name().set( newName ); + } + + @Override + public void delete( Identity id ) + { + UnitOfWork uow = module.unitOfWorkFactory().currentUnitOfWork(); + PersonList list = uow.get( PersonList.class, PersonList.LIST_ID ); + Person person = uow.get( Person.class, id ); + list.all().remove( person ); + uow.remove( person ); + } + } + + @Concerns( {TimingCaptureConcern.class, UnitOfWorkConcern.class} ) + @Mixins( QueriesMixin.class ) + public interface Queries + { + @UnitOfWorkPropagation( MANDATORY ) + Person byId( Identity id ); + + @TimingCapture + @UnitOfWorkPropagation( MANDATORY ) + Iterable<Person> all(); + } + + public static class QueriesMixin implements Queries + { + @Structure + private Module module; + + @Override + public Person byId( Identity id ) + { + return module.unitOfWorkFactory().currentUnitOfWork().get( Person.class, id ); + } + + @Override + public Iterable<Person> all() + { + return module.unitOfWorkFactory().currentUnitOfWork() + .get( PersonList.class, PersonList.LIST_ID ) + .all().toList(); + } + } + + @Override + protected final void defineApplication( ApplicationAssembly app ) throws AssemblyException + { + app.setName( "app" ); + + LayerAssembly domain = app.layer( "domain" ); + ModuleAssembly model = domain.module( "model" ); + model.entities( Person.class, PersonList.class ) + .visibleIn( Visibility.layer ); + ModuleAssembly services = domain.module( "services" ); + services.services( Commands.class, Queries.class ) + .instantiateOnStartup() + .visibleIn( Visibility.application ); + + LayerAssembly config = app.layer( "config" ); + ModuleAssembly configModule = config.module( "config" ); + new EntityTestAssembler() + .visibleIn( Visibility.module ) + .assemble( configModule ); + + LayerAssembly infra = app.layer( "infra" ); + ModuleAssembly storage = infra.module( "storage" ); + entityStoreAssembler( configModule, Visibility.application ) + .visibleIn( Visibility.application ) + .assemble( storage ); + metricsAssembler() + .visibleIn( Visibility.application ) + .assemble( infra.module( "metrics" ) ); + + domain.uses( infra ); + infra.uses( config ); + } + + protected Assemblers.Visible<? extends Assembler> entityStoreAssembler( ModuleAssembly configModule, Visibility configVisibility ) throws AssemblyException + { + return new EntityTestAssembler(); + } + + protected abstract Assemblers.Visible<? extends Assembler> metricsAssembler(); + + protected Module metricsModule() + { + return application.findModule( "infra", "metrics" ); + } + + protected static final String UOW_TIMER_NAME = "app.domain.services.UnitOfWork.timer"; + protected static final String ALL_NAME = "app.domain.services.AbstractZestMetricsTest.Queries.all"; + protected static final String CREATE_NAME = "app.domain.services.AbstractZestMetricsTest.Commands.create"; + protected static final String RENAME_NAME = "app.domain.services.AbstractZestMetricsTest.Commands.rename"; + protected static final String DELETE_NAME = "app.domain.services.AbstractZestMetricsTest.Commands.delete"; + + protected final void assertUowTimer( MetricValuesProvider metrics ) throws PassivationException, ActivationException + { + Long initialUowCount = metrics.timerCount( UOW_TIMER_NAME ); + runScenario1(); + assertThat( UOW_TIMER_NAME + " count incremented by 3", metrics.timerCount( UOW_TIMER_NAME ), is( initialUowCount + 3L ) ); + application.passivate(); + application.activate(); + assertThat( UOW_TIMER_NAME + " count reset on passivation", metrics.timerCount( UOW_TIMER_NAME ), equalTo( initialUowCount ) ); + } + + protected final void assertTimingCapture( MetricValuesProvider metrics ) throws PassivationException, ActivationException + { + // Initial state + assertThat( ALL_NAME + " count is 0 at start", metrics.timerCount( ALL_NAME ), is( 0L ) ); + assertThat( CREATE_NAME + " count is 0 at start", metrics.timerCount( CREATE_NAME ), is( 0L ) ); + assertThat( RENAME_NAME + " count is 0 at start", metrics.timerCount( RENAME_NAME ), is( 0L ) ); + assertThat( DELETE_NAME+ " count is 0 at start", metrics.timerCount( DELETE_NAME ), is( 0L ) ); + + // Run scenario + runScenario1(); + + // Queries.byId() timings are not captured + assertThat( "Queries.byId() has no timer", metrics.registeredMetricNames(), not( contains( containsString( "byId" ) ) ) ); + + // Captured timings + assertThat( ALL_NAME + " count is 4 after scenario", metrics.timerCount( ALL_NAME ), is( 4L ) ); + assertThat( CREATE_NAME + " count is 1 after scenario", metrics.timerCount( CREATE_NAME ), is( 1L ) ); + assertThat( RENAME_NAME + " count is 1 after scenario", metrics.timerCount( RENAME_NAME ), is( 1L ) ); + assertThat( DELETE_NAME + " count is 1 after scenario", metrics.timerCount( DELETE_NAME ), is( 1L ) ); + + // Reset on passivation + application.passivate(); + application.activate(); + assertThat( ALL_NAME + " count is 0 after restart", metrics.timerCount( ALL_NAME ), is( 0L ) ); + assertThat( CREATE_NAME + " count is 0 after restart", metrics.timerCount( CREATE_NAME ), is( 0L ) ); + assertThat( RENAME_NAME + " count is 0 after restart", metrics.timerCount( RENAME_NAME ), is( 0L ) ); + assertThat( DELETE_NAME + " count is 0 after restart", metrics.timerCount( DELETE_NAME ), is( 0L ) ); + } + + protected final void runScenario1() + { + Module services = application.findModule( "domain", "services" ); + Commands commands = services.findService( Commands.class ).get(); + Queries queries = services.findService( Queries.class ).get(); + + Identity identity = StringIdentity.fromString( "1" ); + + try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork( newUsecase( "Step 1" ) ) ) + { + assertThat( queries.all().iterator().hasNext(), is( false ) ); + assertThat( commands.create( identity, "Bob Geldof" ).name().get(), equalTo( "Bob Geldof" ) ); + assertThat( queries.byId( identity ).name().get(), equalTo( "Bob Geldof" ) ); + uow.complete(); + } + + try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork(newUsecase("Step 2"))) + { + assertThat( queries.all().iterator().next().name().get(), equalTo( "Bob Geldof" ) ); + assertThat( queries.byId( identity ).name().get(), equalTo( "Bob Geldof" ) ); + commands.rename( identity, "Nina Hagen" ); + assertThat( queries.all().iterator().next().name().get(), equalTo( "Nina Hagen" ) ); + uow.complete(); + } + + try (UnitOfWork uow = services.unitOfWorkFactory().newUnitOfWork(newUsecase("Step 3"))) + { + commands.delete( identity ); + assertThat( queries.all().iterator().hasNext(), is( false ) ); + uow.complete(); + } + } + + protected static class JmxMetricTestAdapter implements MetricValuesProvider + { + private final JmxFixture jmx = new JmxFixture( "metrics:name=" ); + + @Override + public long timerCount( String name ) + { + if( jmx.objectExists( name ) ) { + return jmx.attributeValue( name, "Count", Long.class ); + } + return 0L; + } + + @Override + public Collection<String> registeredMetricNames() + { + return jmx.allObjectNames().stream() + .filter( objName -> objName.startsWith( jmx.prefix() ) ) + .map( objName -> objName.substring( jmx.prefix().length() ) ) + .collect( toList() ); + } + } + + @Test + public void uowTimerJmx() throws PassivationException, ActivationException + { + assertUowTimer( new JmxMetricTestAdapter() ); + } + + @Test + public void timingCaptureJmx() throws PassivationException, ActivationException + { + assertTimingCapture( new JmxMetricTestAdapter() ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries.gradle ---------------------------------------------------------------------- diff --git a/libraries.gradle b/libraries.gradle index d99551c..59086b0 100644 --- a/libraries.gradle +++ b/libraries.gradle @@ -22,6 +22,7 @@ def asmVersion = '5.1' def bonecpVersion = '0.8.0.RELEASE' def bouncyVersion = '1.55' +def codahaleMetricsVersion = '3.1.2' def commonsDbcpVersion = '2.1.1' def commonsLangVersion = '3.5' def derbyVersion = '10.13.1.1' @@ -215,6 +216,10 @@ rootProject.ext { pdfbox: "org.apache.pdfbox:pdfbox:$pdfboxVersion", prefuse: "de.sciss:prefuse-core:$prefuseVersion", spymemcached: "net.spy:spymemcached:$spymemcachedVersion", + codahale_metrics: [ + "io.dropwizard.metrics:metrics-core:$codahaleMetricsVersion", + "io.dropwizard.metrics:metrics-healthchecks:$codahaleMetricsVersion" + ], // Testing junit: "junit:junit:$junitVersion", http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries/metrics/build.gradle ---------------------------------------------------------------------- diff --git a/libraries/metrics/build.gradle b/libraries/metrics/build.gradle index 0f27a3c..24823c3 100644 --- a/libraries/metrics/build.gradle +++ b/libraries/metrics/build.gradle @@ -27,6 +27,7 @@ dependencies { testCompile(project(":org.apache.zest.core:org.apache.zest.core.testsupport")) testCompile(project(":org.apache.zest.extensions:org.apache.zest.extension.metrics-yammer")) + testCompile(project(":org.apache.zest.extensions:org.apache.zest.extension.metrics-codahale")) testRuntime(project(":org.apache.zest.core:org.apache.zest.core.runtime")) testRuntime(libraries.logback) http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries/metrics/src/docs/metrics.txt ---------------------------------------------------------------------- diff --git a/libraries/metrics/src/docs/metrics.txt b/libraries/metrics/src/docs/metrics.txt index 179f3e0..991a3e3 100644 --- a/libraries/metrics/src/docs/metrics.txt +++ b/libraries/metrics/src/docs/metrics.txt @@ -33,7 +33,7 @@ There are currently the following possibilities available; Before looking at the details of these, we need to point out that there are some pre-conditions for Metrics to be working. First of all, you need to install a Metrics Extensions, most likely the -<<extension-metrics-yammer, Yammer Metrics Extension>>. See your chosen extension for details on how to do that. +<<extension-metrics-codahale, Codahale Metrics Extension>>. See your chosen extension for details on how to do that. Once the Metrics extension is installed, you will also need a suitable backend to gather all the data out of a production plant and likewise a good front-end to view this. See your chosen Metrics Extension for this as well. http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java ---------------------------------------------------------------------- diff --git a/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java b/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java new file mode 100644 index 0000000..30a2762 --- /dev/null +++ b/libraries/metrics/src/test/java/org/apache/zest/library/metrics/CodahaleTimingCaptureTest.java @@ -0,0 +1,59 @@ +/* + * 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 org.apache.zest.library.metrics; + +import com.codahale.metrics.MetricRegistry; +import org.apache.zest.bootstrap.Assembler; +import org.apache.zest.bootstrap.Assemblers; +import org.apache.zest.metrics.codahale.CodahaleMetricsAssembler; +import org.apache.zest.metrics.codahale.CodahaleMetricsProvider; +import org.apache.zest.test.metrics.MetricValuesProvider; + +import java.util.Collection; + +public class CodahaleTimingCaptureTest extends AbstractTimingCaptureTest +{ + @Override + protected Assemblers.Visible<? extends Assembler> metricsAssembler() + { + return new CodahaleMetricsAssembler(); + } + + @Override + protected MetricValuesProvider metricValuesProvider() + { + CodahaleMetricsProvider metricsProvider = serviceFinder.findService( CodahaleMetricsProvider.class ).get(); + MetricRegistry metricRegistry = metricsProvider.metricRegistry(); + return new MetricValuesProvider() + { + @Override + public Collection<String> registeredMetricNames() + { + return metricRegistry.getNames(); + } + + @Override + public long timerCount( String timerName ) + { + return metricRegistry.timer( application.name() + '.' + timerName ).getCount(); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/manual/src/docs/userguide/extensions.txt ---------------------------------------------------------------------- diff --git a/manual/src/docs/userguide/extensions.txt b/manual/src/docs/userguide/extensions.txt index 9d95997..ce7d495 100644 --- a/manual/src/docs/userguide/extensions.txt +++ b/manual/src/docs/userguide/extensions.txt @@ -129,6 +129,10 @@ include::../../../../extensions/indexing-sql/src/docs/index-sql.txt[] :leveloffset: 2 +include::../../../../extensions/metrics-codahale/src/docs/metrics-codahale.txt[] + +:leveloffset: 2 + include::../../../../extensions/metrics-yammer/src/docs/metrics-yammer.txt[] :leveloffset: 2 http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/manual/src/resources/js/progressive-enhancement.js ---------------------------------------------------------------------- diff --git a/manual/src/resources/js/progressive-enhancement.js b/manual/src/resources/js/progressive-enhancement.js index f496cdf..9af8dc9 100644 --- a/manual/src/resources/js/progressive-enhancement.js +++ b/manual/src/resources/js/progressive-enhancement.js @@ -161,7 +161,7 @@ $( document ).ready( function($){ case "Ehcache Cache": case "Memory EntityStore": case "ElasticSearch Index/Query": - case "Yammer Metrics": + case "Codahale Metrics": case "Migration": $dt.attr( "style", "margin-top: 24px" ); break; http://git-wip-us.apache.org/repos/asf/zest-java/blob/8453ce39/settings.gradle ---------------------------------------------------------------------- diff --git a/settings.gradle b/settings.gradle index 8d724c9..73b3a37 100644 --- a/settings.gradle +++ b/settings.gradle @@ -73,6 +73,7 @@ include 'core:functional', 'extensions:indexing-rdf', 'extensions:indexing-solr', 'extensions:indexing-sql', + 'extensions:metrics-codahale', 'extensions:metrics-yammer', 'extensions:migration', 'extensions:reindexer',
