2015-02-13 31 views
31

Próbuję dodać metryki do zwykłej aplikacji Java za pomocą danych Codahale. Chciałbym użyć adnotacji @Timed, ale nie jest dla mnie jasne, której MetricRegistry używa lub jak określić, której MetricRegistry użyć. Aplikacja jest zwykłą aplikacją Java 8, zbudowaną przy użyciu Maven 3, bez Spring, bez Hibernate.Codahale Metrics: użycie adnotacji metryk @Timed w zwykłej Javie

nie mogę znaleźć żadnej dokumentacji na temat sposobu realizacji @Timed w dokumentacji dropwizard: https://dropwizard.github.io/metrics/3.1.0/manual/

dodałem te zależności:

<dependency> 
    <groupId>io.dropwizard.metrics</groupId> 
    <artifactId>metrics-core</artifactId> 
    <version>3.1.0</version> 
</dependency> 
<dependency> 
    <groupId>com.codahale.metrics</groupId> 
    <artifactId>metrics-annotation</artifactId> 
    <version>3.0.2</version> 
</dependency> 

Kiedy używam Zautomatyzowane wywołanie czasowy, ja można uzyskać raporty, bo wiem, który jest stosowany MetricsRegistry:

static final MetricRegistry metrics = new MetricRegistry(); 
private void update() throws SQLException { 
    Timer.Context time = metrics.timer("domainobject.update").time(); 
    try { 
    [...] 
    } finally { 
    time.stop(); 
    } 
} 

Ale kiedy używam dużo bardziej elegancki @Timed adnotacji, nie mam pojęcia whic h rejestr jest używany, a więc nie mogę utworzyć reporter, co oznacza, że ​​nie mogę dostać metryki zgłoszone (nie jestem nawet pewien, czy to faktycznie nic nie robi):

@Timed(name = "domainobject.update") 
private void update() throws SQLException { 
    [...] 
} 

Proszę doradzić jak zrobić Atrybuty @Timed i inne metryki działają w zwykłej aplikacji Java.

Dodatkowe informacje: Powodem, dla którego znajduję to dziwne jest to, że dodałem framework Lombok i adnotacje @ Slf4j działają. Dodałem Lombok jako zależność w pom.xml maven:

<dependency> 
    <groupId>org.projectlombok</groupId> 
    <artifactId>lombok</artifactId> 
    <version>1.14.8</version> 
</dependency> 

I mogę użyć adnotacji @ klasy Sl4fj dodać rejestrator do klasy bez zaśmiecania zmienne członków:

@Slf4j 
public class App { 
    public void logsome(){ 
    log.info("Hello there"); 
    } 
} 

Więc jeśli jest to możliwe, po prostu dodając zależność, myślę, że po prostu brakuje mi zależności lub konfiguracji, aby uzyskać pracę z adnotacją codahale @ Timed, jak opisano powyżej.

(przy okazji, sprawdź Lombok, będzie to ułatwić Ci życie: http://projectlombok.org/)

+0

myślę będziesz out-of-szczęścia bez wiosennym AOP lub ręcznego konfigurowania AspectJ tkać swoje klasy. Tego typu rzeczy działają tylko z AOP, więc potrzebujesz czegoś, aby to zapewnić w swoich klasach. Na przykład, Spring AOP używa proxy JDK, CGLIB lub AspectJ do osiągnięcia tego – Alex

+0

. Więc AspectJ byłby do zrobienia? Jak mam to zrobić? – Rolf

+0

Jeszcze bardziej interesujące: Dlaczego na przykład @ Slf4j działa, a @ Timed nie? Nie używam jawnie AspectJ do działania Slf4j. – Rolf

Odpowiedz

12

Krótko mówiąc, nie można używać @Timed bez jakiejś AOP (czy to wiosna AOP lub AspectJ).

Tydzień lub dwa temu, zdecydowałem się dodać dane do naszego projektu i wybrałem AspectJ do tego zadania (głównie dlatego, że używałem go w przeszłości do podobnych celów i ponieważ pozwala na kompilowanie czasu, podczas gdy Spring pozwala tylko środowisko wykonawcze za pośrednictwem serwerów proxy).

Powinieneś być w stanie znaleźć wszystkie niezbędne informacje i instrukcje tutaj: https://github.com/astefanutti/metrics-aspectj.

Jak na Lombok, myślę, że oni korzystać z wbudowanych w procesor javac adnotacji:

Kolejnym punktem spornym jest realizacja zarówno kod wspierającej integrację IDE jak również procesor javac adnotacji. Oba te elementy Projektu Lombok wykorzystują niepubliczne interfejsy API do realizacji swoich czarów. Oznacza to, że istnieje ryzyko, że projekt Lombok zostanie zerwany wraz z kolejnymi wydaniami IDE lub JDK.

+0

To wydaje się być sposób, aby uzyskać @ Timed działa rzeczywiście, dzięki, ale teraz Lombok i AspectJ dostać się do argumentu w moim cyklu budowy. AspectJ skarży się na adnotację @ Slf4j. Muszę wymyślić, jak sprawić, by były przyjemne. – Rolf

+0

Wygląda na to, że Lombok i AspectJ nie zawsze dobrze grają: https://stackoverflow.com/questions/25903686/lombok-does-not-work-with-aspectj – Rolf

+0

Czas na trudne decyzje. Próbowałem usunąć Lombok na rzecz adnotacji @Timed, ale rzeczy z AspectJ dają mi tak ciężki czas i jest tak trudny i niezrozumiały do ​​debugowania, że ​​zrezygnowałem. Dzięki temu projekt staje się bardziej złożony i stwarza większy problem niż ten, który rozwiązuje. Oceniłem twoją odpowiedź jako "odpowiedział", ponieważ to * jest * odpowiedź, to po prostu zbyt duży problem z moim małym projektem (i moim małym mózgiem). Ręczne kodowanie połączeń z zegarami Codahale. Dzięki! – Rolf

5

pomocą wbudowanego MetricRegistry dostępny z parametrem bootstrap w metodzie initialize swojej klasie aplikacji.

@Override 
public void initialize(final Bootstrap<Configuration> bootstrap) { 
    final JmxReporter reporter = JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build(); 
    reporter.start(); 
} 
3

AOP jest przesadą i nie jest odpowiedni do stosowania @timed, ogólnie mówienia.

Domyślny rejestr metryk zapisuje @metody metryczne w ConcurrentHashMap i nie dołącza żadnych sensownych detektorów.

DropWizard Bootstrap konstruktor:

/** 
* Creates a new {@link Bootstrap} for the given application. 
* @param application a Dropwizard {@link Application} 
*/ 
public Bootstrap(Application<T> application) { 
    this.application = application; 
    this.objectMapper = Jackson.newObjectMapper(); 
    this.bundles = Lists.newArrayList(); 
    this.configuredBundles = Lists.newArrayList(); 
    this.commands = Lists.newArrayList(); 
    this.validatorFactory = Validators.newValidatorFactory(); 


    // returns new ConcurrentHashMap<String, Metric>(); 
    this.metricRegistry = new MetricRegistry(); 


    this.configurationSourceProvider = new FileConfigurationSourceProvider(); 
    this.classLoader = Thread.currentThread().getContextClassLoader(); 
    this.configurationFactoryFactory = new DefaultConfigurationFactoryFactory<T>(); 
} 

Więc trzeba budować/start/zarejestrować odpowiedni rejestr metryczną w aby zobaczyć wyniki.

Tutaj Używam JMX:

@Override 
public void initialize(Bootstrap<PayloadStorageConfiguration> bootstrap) { 
    JmxReporter.forRegistry(bootstrap.getMetricRegistry()).build().start(); 
} 

To wszystko, co trzeba zrobić.

Oto przykład wyjścia (run JConsole przeciwko swojej aplikacji Java/serwera, aby zobaczyć wyniki JMX):

enter image description here

0

Można również użyć stagemonitor-core za to. Zobacz dokumentację here i here. Zaletą tego jest to, że stagemonitor (który jest darmowy z wolnym dostępem open source &) nie zależy od żadnego AOP opartego na pojemnikach, takiego jak atrybuty Spring AOP lub EJB. Używa on kodowania kodu bajtowego za pośrednictwem załącznika środowiska wykonawczego, co oznacza, że ​​nie trzeba nawet dodawać flagi do uruchamiania aplikacji - wystarczy zwykła zależność.

Jeśli chcesz zmierzyć czas wykonywania w aplikacji internetowej lub zdalnej aplikacji EJB, nie musisz nawet ręcznie opisywać swojego kodu. Stagemonitor oferuje również wstępnie skonfigurowane kokpity graficzne i Kibana.

Zastrzeżenie: Jestem jednym z twórców stagemonitor

8

Korzystanie @Timed faktycznie nie wymagają użycia AOP, jak wcześniej zastrzeżono w najwyższej klasy odpowiedź, jeśli jesteś wewnątrz pojemnika i przy użyciu jednej z bibliotek oprzyrządowania Dropwizarda. Zobacz na przykład moduł Jersey 2.x, który można zobaczyć za pomocą refleksji (podobnie jak inne, na które patrzyłem), jeśli czytasz source.

można przeczytać na wszystkich tych modułów w the Dropwizard docs pod odpowiednim „instrumentacji ____” kul.

Rozumiem, że OP nie działa jawnie w takim kontenerze, ale chciałem zaoferować te informacje, ponieważ wielu z nas szukających tej odpowiedzi może pracować nad nowoczesną usługą sieciową, która może zarejestrować takie zasoby w swoim środowisku wykonawczym .

0

W nowszych wersjach Dropwizarda (używam wersji 0.9.2), można uzyskać dostęp do domyślnego MetricRegistry za pośrednictwem środowiska konfiguracyjnego io.dropwizard.setup.Environment. Ten domyślny numer MetricRegistry ma już powiązany z nim kod InstrumentedResourceMethodApplicationListener, który nasłuchuje wszystkich metryk zasobów.

Jeżeli zarejestrowałeś zasób z JerseyEnvironment jak w,

environment.jersey().register(resource); 

trzeba tylko opisywanie metodę zasobów (lub klasa) z @Timed, @Metered lub @ExceptionMetered zarejestrować odpowiednie dane.

@POST 
@Timed 
public String show() { 
    return "yay"; 
} 

można przypisać Reporter (jak u Slf4jReporter lub JmxReporter) do domyślnego MetricRegistry jak pod

Slf4jReporter.forRegistry(environment.metrics()).build(); 

jako szybki test, aby sprawdzić, czy dane zostały faktycznie zarejestrowana, można zrobić GET Zadzwoń pod URL http://localhost:8081/metrics lub odpowiadający mu URL Admin Metrics w twoim środowisku testowym.

Niektóre inne wersje wymagają wyraźnie zarejestrować InstrumentedResourceMethodApplicationListener jak pokazano in this Doc