| /* |
| * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved. |
| * |
| * Licensed 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.yammer.metrics.Metrics; |
| import com.yammer.metrics.core.MetricsRegistry; |
| import java.io.ByteArrayOutputStream; |
| import java.io.PrintStream; |
| import java.lang.reflect.Field; |
| import java.util.Map; |
| import java.util.concurrent.TimeUnit; |
| import org.junit.Test; |
| import org.apache.zest.api.common.Optional; |
| import org.apache.zest.api.composite.TransientComposite; |
| import org.apache.zest.api.concern.Concerns; |
| import org.apache.zest.api.mixin.Mixins; |
| import org.apache.zest.api.property.Property; |
| import org.apache.zest.bootstrap.AssemblyException; |
| import org.apache.zest.bootstrap.ModuleAssembly; |
| import org.apache.zest.metrics.yammer.YammerMetricsAssembler; |
| import org.apache.zest.test.AbstractQi4jTest; |
| |
| import static org.hamcrest.CoreMatchers.equalTo; |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.assertTrue; |
| |
| public class MetricsTest extends AbstractQi4jTest |
| { |
| private PrintStream reportOut; |
| private ByteArrayOutputStream result; |
| private YammerMetricsAssembler assembler; |
| |
| @Override |
| public void assemble( ModuleAssembly module ) |
| throws AssemblyException |
| { |
| module.layer().application().setName( "SomeApplication" ); |
| module.transients( Country1.class ); |
| module.transients( Country2.class ).withConcerns( TimingCaptureAllConcern.class ); |
| module.transients( Country3.class ).withConcerns( TimingCaptureConcern.class ); |
| result = new ByteArrayOutputStream(); |
| reportOut = new PrintStream( result ); |
| assembler = new YammerMetricsAssembler( reportOut, 100, TimeUnit.MILLISECONDS ); |
| assembler.assemble( module ); |
| } |
| |
| @Override |
| public void tearDown() |
| throws Exception |
| { |
| if( assembler != null ) // Is null if assemble fails... |
| { |
| assembler.shutdown(); |
| } |
| Field metrics = MetricsRegistry.class.getDeclaredField( "metrics" ); |
| metrics.setAccessible( true ); |
| Map m = (Map) metrics.get( Metrics.defaultRegistry() ); |
| m.clear(); |
| super.tearDown(); |
| } |
| |
| @Test |
| public void givenNonInstrumentedCompositeWhenCallingUpdateNameExpectNoReport() |
| { |
| Country underTest = module.newTransient( Country1.class ); |
| String result = runTest( underTest ); |
| result = result.replace( "\r", "" ); |
| assertTrue( lastLine( result, 1 ).contains( "=====================" ) ); |
| System.out.println( "---END TEST---" ); |
| } |
| |
| @Test |
| public void givenInstrumentedWithAllCompositeWhenCallingUpdateNameExpectReport() |
| { |
| Country underTest = module.newTransient( Country2.class ); |
| String result = runTest( underTest ); |
| result = result.replace( "\r", "" ); |
| assertThat( lastLine( result, 34 ), equalTo( "org.qi4j.library.metrics.Country.SomeApplication:" ) ); |
| assertThat( lastLine( result, 33 ).trim(), equalTo( "name() [TimingCapture]:" ) ); |
| assertThat( lastLine( result, 16 ).trim(), equalTo( "updateName() [TimingCapture]:" ) ); |
| assertTrue( lastLine( result, 5 ).contains( "75% <=" ) ); |
| assertTrue( lastLine( result, 4 ).contains( "95% <=" ) ); |
| assertTrue( lastLine( result, 3 ).contains( "98% <=" ) ); |
| assertTrue( lastLine( result, 2 ).contains( "99% <=" ) ); |
| assertTrue( lastLine( result, 1 ).contains( "99.9% <=" ) ); |
| System.out.println( "---END TEST---" ); |
| } |
| |
| @Test |
| public void givenOneMethodAnnotatedWhenCallingUpdateNameExpectReportForThatMethodOnly() |
| { |
| Country underTest = module.newTransient( Country3.class ); |
| String result = runTest( underTest ); |
| result = result.replace( "\r", "" ); |
| assertThat( lastLine( result, 17 ), equalTo( "org.qi4j.library.metrics.Country.SomeApplication:" ) ); |
| assertThat( lastLine( result, 16 ).trim(), equalTo( "updateName() [TimingCapture]:" ) ); |
| assertTrue( lastLine( result, 5 ).contains( "75% <=" ) ); |
| assertTrue( lastLine( result, 4 ).contains( "95% <=" ) ); |
| assertTrue( lastLine( result, 3 ).contains( "98% <=" ) ); |
| assertTrue( lastLine( result, 2 ).contains( "99% <=" ) ); |
| assertTrue( lastLine( result, 1 ).contains( "99.9% <=" ) ); |
| System.out.println( "---END TEST---" ); |
| } |
| |
| private String lastLine( String text, int index ) |
| { |
| String[] lines = text.split( "\n" ); |
| return lines[ lines.length - index ]; |
| } |
| |
| private String runTest( Country underTest ) |
| { |
| |
| for( int i = 0; i < 1000000; i++ ) |
| { |
| underTest.updateName( "Name" + i ); |
| } |
| reportOut.close(); |
| return result.toString(); |
| } |
| |
| // START SNIPPET: complex-capture |
| public interface Country extends TransientComposite |
| { |
| @Optional |
| Property<String> name(); |
| |
| void updateName( String newName ); |
| } |
| |
| @Mixins( Country1Mixin.class ) |
| public interface Country1 extends Country |
| { |
| |
| } |
| |
| public static abstract class Country1Mixin |
| implements Country1 |
| { |
| |
| @Override |
| public void updateName( String newName ) |
| { |
| name().set( newName ); |
| } |
| } |
| |
| @Mixins( Country2Mixin.class ) |
| public interface Country2 extends Country |
| { |
| } |
| |
| public static abstract class Country2Mixin |
| implements Country2 |
| { |
| |
| @Override |
| public void updateName( String newName ) |
| { |
| name().set( newName ); |
| } |
| } |
| |
| @Mixins( Country3Mixin.class ) |
| @Concerns( TimingCaptureConcern.class ) |
| public interface Country3 extends Country |
| { |
| } |
| |
| public static abstract class Country3Mixin |
| implements Country3 |
| { |
| @Override |
| @TimingCapture |
| public void updateName( String newName ) |
| { |
| name().set( newName ); |
| } |
| } |
| // END SNIPPET: complex-capture |
| } |