Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Orbit Metrics Round 2 #73

Merged
merged 46 commits into from
Jun 25, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b4b03a5
Orbit Metrics
FieldFlux Jun 3, 2015
f915165
Basic Metrics Configuration. Only Slf4j is supported.
FieldFlux Jun 4, 2015
a045663
Graphite and Ganglia Reporter configs
bwjefft Jun 4, 2015
9991b90
Graphite and Ganglia Reporter configs
FieldFlux Jun 4, 2015
421df72
Merge branch 'metricsredux' of https://github.com/fieldflux/orbit int…
bwjefft Jun 5, 2015
fa2beab
Have the stage pass in the runtime Id for unique prefixing
FieldFlux Jun 5, 2015
913d96d
Improved Graphite reporting
FieldFlux Jun 6, 2015
a1f5a4c
Moving Execution Metrics to getter methods due to limitation in
FieldFlux Jun 6, 2015
021d672
Fixing a bug in ReporterConfig that would cause period time units to be
FieldFlux Jun 6, 2015
8a2e52b
Cleaning up Metrics Manager and adding some warnings/exceptions
FieldFlux Jun 8, 2015
be6834b
Moving metrics out into its own module under util
FieldFlux Jun 12, 2015
c5f6bb8
Fixing POM to correctly reference orbit-parent
FieldFlux Jun 12, 2015
a8eb502
Added a Container Component so that metrics an be initialized if not …
FieldFlux Jun 13, 2015
f11b308
Added the ability to remove metrics from the registry.
FieldFlux Jun 13, 2015
db4c604
Orbit Metrics
FieldFlux Jun 3, 2015
cfa0ca0
Basic Metrics Configuration. Only Slf4j is supported.
FieldFlux Jun 4, 2015
b4804d1
Graphite and Ganglia Reporter configs
bwjefft Jun 4, 2015
7b3cb64
Have the stage pass in the runtime Id for unique prefixing
FieldFlux Jun 5, 2015
40a57e4
Improved Graphite reporting
FieldFlux Jun 6, 2015
b6580f1
Moving Execution Metrics to getter methods due to limitation in
FieldFlux Jun 6, 2015
764c26d
Fixing a bug in ReporterConfig that would cause period time units to be
FieldFlux Jun 6, 2015
2ab2664
Cleaning up Metrics Manager and adding some warnings/exceptions
FieldFlux Jun 8, 2015
b22a9a3
Moving metrics out into its own module under util
FieldFlux Jun 12, 2015
a7513cb
Fixing POM to correctly reference orbit-parent
FieldFlux Jun 12, 2015
8962f81
Added a Container Component so that metrics an be initialized if not …
FieldFlux Jun 13, 2015
58f00cc
Added the ability to remove metrics from the registry.
FieldFlux Jun 13, 2015
5251fe9
Fixing compile error after merging in latest from master
bwjefft Jun 18, 2015
c9f1186
Removing runtime prefix generation in favour of config-based setting
bwjefft Jun 18, 2015
c24d4d4
Handle duplicate metric exception better
bwjefft Jun 18, 2015
8c59f21
Fix metric name generation to use the correct class name
FieldFlux Jun 19, 2015
61511cc
Merge branch 'metricsredux' of https://github.com/FieldFlux/orbit int…
FieldFlux Jun 19, 2015
d12493c
Fixing missed merge conflict.
FieldFlux Jun 19, 2015
edd7197
Unregister Execution metrics on Stage Shutdown
FieldFlux Jun 19, 2015
a60bbb1
Jmx Reporter
FieldFlux Jun 19, 2015
5a5be5d
Delete .orig files introduced during branch merge
FieldFlux Jun 19, 2015
26711cf
Move Stage Metrics deregistration to be the last thing during Stage
FieldFlux Jun 19, 2015
ba2901a
Added a Stage Extension for runtime metric registration and deregistr…
FieldFlux Jun 20, 2015
ee12c52
Remove unneeded interface
FieldFlux Jun 20, 2015
e660b27
Move Metric Name Sanitization into Metrics Manager to reduce mistakes...
FieldFlux Jun 20, 2015
f0fa6e1
Remove unintentional changes.
FieldFlux Jun 20, 2015
3142bf4
Revert Commons POM
FieldFlux Jun 20, 2015
bfa3125
Sanitization Regex is now statically compiled and reused.
FieldFlux Jun 22, 2015
cf9956a
Fixing formatting
FieldFlux Jun 22, 2015
b48a9b9
Cleaning up some try catches
FieldFlux Jun 23, 2015
e9b8e61
Metric Scope is now controlled via an enum.
FieldFlux Jun 25, 2015
b6ef66f
adding missing copyright
FieldFlux Jun 25, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
56 changes: 56 additions & 0 deletions actors/extensions/metrics/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--~
Copyright (C) 2015 Electronic Arts Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-actors-parent</artifactId>
<version>0.3.2-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<name>Orbit Actors Extension: Metrics Support</name>
<artifactId>orbit-actors-metrics</artifactId>

<dependencies>
<dependency>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-actors-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-metrics</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright (C) 2015 Electronic Arts Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.ea.orbit.actors.extensions.metrics;

import com.ea.orbit.actors.extensions.LifetimeExtension;
import com.ea.orbit.actors.runtime.AbstractActor;
import com.ea.orbit.actors.runtime.ActorReference;
import com.ea.orbit.concurrent.Task;
import com.ea.orbit.metrics.MetricsManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* {@link MetricsLifetimeExtension} allows for automatic registration and deregistration of annotated Orbit Metrics
*
*/
public class MetricsLifetimeExtension implements LifetimeExtension
{
private static final Logger logger = LoggerFactory.getLogger(MetricsLifetimeExtension.class);
@Override
public Task preActivation(AbstractActor actor)
{
try
{
String actorId = ActorReference.getId(ActorReference.from(actor)).toString();
MetricsManager.getInstance().registerExportedMetrics(actor, actorId);
}
catch(Exception ex)
{
logger.error("Unexpected error while registering Actor Metrics for " + actor.getClass().getName() + ": " + ex.getMessage());
}
finally
{
return Task.done();
}
}

@Override
public Task postDeactivation(final AbstractActor<?> actor)
{
try
{
String actorId = ActorReference.getId(ActorReference.from(actor)).toString();
MetricsManager.getInstance().unregisterExportedMetrics(actor, actorId);
}
catch(Exception ex)
{
logger.error("Unexpected error while unregistering Actor Metrics for " + actor.getClass().getName() + ": " + ex.getMessage());
}
finally
{
return Task.done();
}
}
}
1 change: 1 addition & 0 deletions actors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<module>extensions/postgresql</module>
<module>extensions/spring</module>
<module>extensions/memcached</module>
<module>extensions/metrics</module>
<module>test/actor-tests</module>
<module>actors-all</module>
</modules>
Expand Down
7 changes: 7 additions & 0 deletions actors/stage/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>

<dependency>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-metrics</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
66 changes: 60 additions & 6 deletions actors/stage/src/main/java/com/ea/orbit/actors/Stage.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.ea.orbit.actors.cluster.NodeAddress;
import com.ea.orbit.actors.extensions.LifetimeExtension;
import com.ea.orbit.actors.extensions.ActorExtension;
import com.ea.orbit.metrics.config.ReporterConfig;
import com.ea.orbit.actors.runtime.Execution;
import com.ea.orbit.actors.runtime.Hosting;
import com.ea.orbit.actors.runtime.NodeCapabilities;
Expand All @@ -51,10 +52,12 @@

import javax.inject.Singleton;

import java.lang.reflect.Method;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutorService;

@Singleton
Expand All @@ -74,6 +77,9 @@ public class Stage implements Startable
@Config("orbit.actors.extensions")
private List<ActorExtension> extensions = new ArrayList<>();

@Config("orbit.metrics.reporters")
private List<ReporterConfig> metricsConfig = new ArrayList<>();

@Wired
Container container;

Expand Down Expand Up @@ -241,6 +247,8 @@ public Task<?> start()
hosting.start();
execution.start();

startMetrics();

Task<?> future = clusterPeer.join(clusterName, nodeName);
if (mode == StageMode.HOST)
{
Expand Down Expand Up @@ -281,7 +289,7 @@ public void setClusterPeer(final ClusterPeer clusterPeer)

/**
* Installs extensions to the stage.
* <p/>
* <p>
* Example:
* <pre>
* stage.addExtension(new MongoDbProvider(...));
Expand All @@ -306,7 +314,9 @@ public Task<?> stop()
// * wait pending tasks execution
// * stop the network
return execution.stop()
.thenRun(clusterPeer::leave);
.thenRun(clusterPeer::leave).thenRun(() -> {
unregisterMetrics();
});
}

/**
Expand Down Expand Up @@ -365,15 +375,15 @@ public void cleanup(boolean block)
/**
* Binds this stage to the current thread.
* This tells ungrounded references to use this stage to call remote methods.
* <p/>
* <p>
* An ungrounded reference is a reference created with {@code Actor.getReference} and used outside of an actor method.
* <p/>
* <p>
* This is only necessary when there are <i>two or more</i> OrbitStages active in the same virtual machine and
* remote calls need to be issued from outside an actor.
* This method was created to help with test cases.
* <p/>
* <p>
* A normal application will have a single stage and should have no reason to call this method.
* <p/>
* <p>
* This method writes a weak reference to the runtime in a thread local.
* No cleanup is necessary, so none is available.
*/
Expand Down Expand Up @@ -404,4 +414,48 @@ public NodeCapabilities.NodeState getState()
{
return execution.getState();
}

private void startMetrics()
{
try
{
Class mmClazz = Class.forName("com.ea.orbit.metrics.MetricsManager"); //make sure the metrics manager is on the classpath.
Method getInstanceMethod = mmClazz.getDeclaredMethod("getInstance");
Method initializeMetricsMethod = mmClazz.getDeclaredMethod("initializeMetrics", List.class);
Method registerExportedMetricsMethod = mmClazz.getDeclaredMethod("registerExportedMetrics", Object.class, String.class);

Object managerObject = getInstanceMethod.invoke(null, null);
initializeMetricsMethod.invoke(managerObject, metricsConfig);
registerExportedMetricsMethod.invoke(managerObject, execution, execution.runtimeIdentity());
}
catch (ClassNotFoundException ex)
{
//OK. Just means that metrics isn't being used.
}
catch (Exception ex)
{
logger.error("Unexpected error while initializing Orbit Metrics: " + ex.getMessage());
}
}

private void unregisterMetrics()
{
try
{
Class mmClazz = Class.forName("com.ea.orbit.metrics.MetricsManager"); //make sure the metrics manager is on the classpath.
Method getInstanceMethod = mmClazz.getDeclaredMethod("getInstance");
Method unregisterExportedMetricsMethod = mmClazz.getDeclaredMethod("unregisterExportedMetrics", Object.class, String.class);

Object managerObject = getInstanceMethod.invoke(null, null);
unregisterExportedMetricsMethod.invoke(managerObject, execution, execution.runtimeIdentity());
}
catch (ClassNotFoundException ex)
{
//OK. Just means that metrics isn't being used.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see above.

}
catch (Exception ex)
{
logger.error("Unexpected error while unregistering execution metrics: " + ex.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import com.ea.orbit.actors.extensions.LifetimeExtension;
import com.ea.orbit.actors.extensions.ActorExtension;
import com.ea.orbit.actors.extensions.InvocationContext;
import com.ea.orbit.metrics.annotations.ExportMetric;
import com.ea.orbit.metrics.annotations.MetricScope;
import com.ea.orbit.concurrent.ExecutorUtils;
import com.ea.orbit.concurrent.Task;
import com.ea.orbit.container.Startable;
Expand Down Expand Up @@ -1199,4 +1201,28 @@ public NodeCapabilities.NodeState getState()
{
return state;
}

@ExportMetric(name="localActorCount", scope=MetricScope.PROTOTYPE)
public long getLocalActorCount()
{
return localActors.size();
}

@ExportMetric(name="messagesReceived", scope=MetricScope.PROTOTYPE)
public long getMessagesReceived()
{
return messagesReceived.longValue();
}

@ExportMetric(name="messagesHandled", scope=MetricScope.PROTOTYPE)
public long getMessagesHandled()
{
return messagesHandled.longValue();
}

@ExportMetric(name="refusedExecutions",scope=MetricScope.PROTOTYPE)
public long getRefusedExecutions()
{
return refusedExecutions.longValue();
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<module>samples</module>
<module>packaging/all-docs</module>
<module>utils/agent-loader</module>
<module>utils/metrics</module>
<module>utils/rest-client</module>
</modules>

Expand Down
11 changes: 11 additions & 0 deletions samples/chat/chat-actors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<version>0.3.2-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-metrics</artifactId>
<version>${orbit.version}</version>
</dependency>
<dependency>
<groupId>com.ea.orbit</groupId>
<artifactId>orbit-actors-metrics</artifactId>
<version>${orbit.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import com.ea.orbit.actors.runtime.AbstractActor;
import com.ea.orbit.annotation.Config;
import com.ea.orbit.concurrent.Task;
import com.ea.orbit.metrics.annotations.ExportMetric;
import com.ea.orbit.metrics.annotations.MetricScope;

import java.util.ArrayList;
import java.util.Date;
Expand Down Expand Up @@ -122,4 +124,10 @@ public Task<?> deactivateAsync()
{
return writeState().thenCompose(() -> super.deactivateAsync());
}

@ExportMetric(name="historySize", scope= MetricScope.PROTOTYPE)
public long historySize()
{
return state().history.size();
}
}
8 changes: 8 additions & 0 deletions samples/chat/chat-actors/src/main/resources/conf/orbit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,16 @@ orbit.actors.extensions:
host: localhost
port: 27017
database: chat
- !!com.ea.orbit.actors.extensions.metrics.MetricsLifetimeExtension {}

orbit.chat.maxMessages: 500

orbit.components:
- com.ea.orbit.actors.server.ServerModule

orbit.metrics.reporters:
- !!com.ea.orbit.metrics.config.Slf4jReporterConfig
period: 1
periodUnit: 'MINUTES'
prefix: 'chat.chat-backend'
- !!com.ea.orbit.metrics.config.JmxReporterConfig {}