Skip to content

Commit f61cf9d

Browse files
author
Ruslan Gainutdinov
committed
Initial release
0 parents  commit f61cf9d

17 files changed

+2366
-0
lines changed

.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/.vagrant
2+
/deb
3+
/docker-compose
4+
mystem
5+
bashttpd
6+
/test/PrettyOutput.html
7+
/test/*.bin
8+
/tomita-linux64
9+
/*.log
10+
/target/
11+
/.settings
12+
/.classpath
13+
/.project
14+
.built
15+
.idea
16+
*.iml
17+
/jdk-8u111-linux-x64.tar.gz
18+
/logs/metabase.log
19+
/metabase.jar
20+
/main.html
21+
/main.md
22+
/main2.md
23+
node_modules
24+

README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Persistent metrics
2+
3+
Drop-in enhancement for [Dropwizard Metrics](http://metrics.dropwizard.io/) which provide metric persistence using Redis DB via [Redisson](https://github.com/redisson/redisson) library.
4+
5+
## Limitations
6+
7+
1. Gauge is not supported as it implemented as instant Java method call measurement.
8+
2. Obvious latency issues. Use only for important selected metrics.
9+
10+
## Usage
11+
12+
Replace your usual
13+
```java
14+
new MetricRegistry();
15+
```
16+
17+
with improved
18+
19+
```java
20+
new PersistentMetricRegistry();
21+
```
22+
23+
## Configuring Redis
24+
25+
By default it uses locally installed Redis (default port, i.e. 6379)
26+
To configure redis use following environment variables:
27+
28+
* REDIS_CONF - Redisson JSON [config](https://github.com/redisson/redisson/wiki/2.-Configuration#221-jsonyaml-file-based-configuration) file. Takes precedence.
29+
* REDIS_ADDR - host:port for single server.
30+
31+
## Configuring prefix
32+
33+
By default all metrics is put in redis using prefix "metrics.".
34+
To configure different prefix use METRIC_PREFIX environment variable (dot at the end is added automatically).
35+
36+

pom.xml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.wizecore</groupId>
5+
<artifactId>persistent-metrics</artifactId>
6+
<packaging>jar</packaging>
7+
<version>1.0-SNAPSHOT</version>
8+
<name>persistent-metrics</name>
9+
<url>http://github.com/wizecore/persistent-metrics</url>
10+
11+
<properties>
12+
<maven.compiler.source>1.8</maven.compiler.source>
13+
<maven.compiler.target>1.8</maven.compiler.target>
14+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15+
<spring.version>4.3.8.RELEASE</spring.version>
16+
<metrics.version>3.2.1</metrics.version>
17+
</properties>
18+
19+
<dependencies>
20+
<dependency>
21+
<groupId>org.slf4j</groupId>
22+
<artifactId>slf4j-jdk14</artifactId>
23+
<version>1.7.24</version>
24+
</dependency>
25+
<dependency>
26+
<groupId>org.slf4j</groupId>
27+
<artifactId>slf4j-api</artifactId>
28+
<version>1.7.24</version>
29+
</dependency>
30+
<dependency>
31+
<groupId>io.dropwizard.metrics</groupId>
32+
<artifactId>metrics-core</artifactId>
33+
<version>3.2.1</version>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.redisson</groupId>
37+
<artifactId>redisson</artifactId>
38+
<version>3.3.1</version>
39+
</dependency>
40+
<dependency>
41+
<groupId>junit</groupId>
42+
<artifactId>junit</artifactId>
43+
<version>4.11</version>
44+
<scope>test</scope>
45+
</dependency>
46+
</dependencies>
47+
</project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.wizecore.metrics;
2+
3+
/**
4+
* Interface which exposes the LongAdder functionality. Allows different
5+
* LongAdder implementations to coexist together.
6+
*/
7+
interface LongAdderAdapter {
8+
9+
void add(long x);
10+
11+
long sum();
12+
13+
void increment();
14+
15+
void decrement();
16+
17+
long sumThenReset();
18+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.wizecore.metrics;
2+
3+
import java.io.File;
4+
import java.io.IOException;
5+
import java.util.SortedSet;
6+
7+
import org.redisson.Redisson;
8+
import org.redisson.api.RAtomicDouble;
9+
import org.redisson.api.RAtomicLong;
10+
import org.redisson.api.RedissonClient;
11+
import org.redisson.config.Config;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
15+
/**
16+
* Provides persistance by using Redis instance.
17+
* If no REDIS_ADDR or REDIS_CONF enviroment variables specifed, uses local default instance.
18+
*
19+
* @see #redisAddr
20+
* @
21+
* @author Ruslan
22+
*/
23+
public class PersistenceUtil {
24+
private static Logger log = LoggerFactory.getLogger(PersistenceUtil.class);
25+
26+
/**
27+
* Single instance of Redis client
28+
*/
29+
private static RedissonClient redis;
30+
31+
/**
32+
* Optional config file name. Use REDIS_CONF environment variable to set.
33+
* Takes precedence over REDIS_ADDR (@see {@link PersistenceUtil#redisAddr})
34+
*/
35+
private static String redisConfig = null;
36+
37+
/**
38+
* Optional redis address. Use REDIS_ADDR environment variable to set.
39+
*/
40+
private static String redisAddr = null;
41+
42+
/**
43+
* Common prefix for all values stored. By default <code>metrics.</code>
44+
* Can be specified in environment variable METRICS_PREFIX.
45+
* If not ends with ".", dot will be appended to end of it.
46+
*/
47+
private static String metricPrefix = null;
48+
49+
/**
50+
* Makes lazy initialization of redis client.
51+
*/
52+
protected static void init() {
53+
if (redis == null) {
54+
if (redisConfig == null) {
55+
redisConfig = System.getenv("REDIS_CONF");
56+
}
57+
58+
if (redisAddr == null) {
59+
redisAddr = System.getenv("REDIS_ADDR");
60+
}
61+
62+
if (metricPrefix == null) {
63+
metricPrefix = System.getenv("METRIC_PREFIX");
64+
}
65+
66+
if (metricPrefix == null) {
67+
metricPrefix = "metrics";
68+
}
69+
70+
if (!metricPrefix.endsWith(".")) {
71+
metricPrefix = metricPrefix + ".";
72+
}
73+
74+
Config redisConf = null;
75+
try {
76+
redisConf = redisConfig != null ? Config.fromJSON(new File(redisConfig)) : null;
77+
78+
if (redisConf == null && redisAddr != null && !redisAddr.equals("")) {
79+
redisConf = new Config();
80+
redisConf.useSingleServer().setAddress(redisAddr);
81+
}
82+
83+
log.info("Initializing persistent metrics via Redis with " + (redisConf != null ? redisConf.toJSON() : "defaults"));
84+
redis = redisConf != null ? Redisson.create(redisConf) : Redisson.create();
85+
} catch (IOException e) {
86+
e.printStackTrace();
87+
throw new IllegalStateException("Redis connection failed with " + redisConf);
88+
}
89+
}
90+
}
91+
92+
public static <T> SortedSet<T> createSortedSet(String name, Class<T> elements) {
93+
return redis.getSortedSet(name);
94+
}
95+
96+
public static RAtomicLong createAtomicLong(String name, long defaultValue) {
97+
init();
98+
RAtomicLong v = redis.getAtomicLong(metricPrefix + name);
99+
if (!v.isExists()) {
100+
v.set(defaultValue);
101+
}
102+
return v;
103+
}
104+
105+
public static RAtomicLong createAtomicLong(String name) {
106+
init();
107+
RAtomicLong v = redis.getAtomicLong(metricPrefix + name);
108+
if (!v.isExists()) {
109+
v.set(0);
110+
}
111+
return v;
112+
}
113+
114+
public static LongAdderAdapter createLongAdderAdapter(String name) {
115+
final RAtomicLong v = createAtomicLong(name);
116+
return new LongAdderAdapter() {
117+
@Override
118+
public long sumThenReset() {
119+
long l = v.get();
120+
v.set(0);
121+
return l;
122+
}
123+
124+
@Override
125+
public long sum() {
126+
return v.get();
127+
}
128+
129+
@Override
130+
public void increment() {
131+
v.incrementAndGet();
132+
}
133+
134+
@Override
135+
public void decrement() {
136+
v.decrementAndGet();
137+
}
138+
139+
@Override
140+
public void add(long x) {
141+
v.addAndGet(x);
142+
}
143+
};
144+
}
145+
146+
public static RAtomicDouble createAtomicDouble(String name) {
147+
init();
148+
RAtomicDouble v = redis.getAtomicDouble(metricPrefix + name);
149+
if (!v.isExists()) {
150+
v.set(0);
151+
}
152+
return v;
153+
}
154+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.wizecore.metrics;
2+
3+
import com.codahale.metrics.Counter;
4+
5+
/**
6+
* An incrementing and decrementing counter metric.
7+
*/
8+
public class PersistentCounter extends Counter {
9+
private final LongAdderAdapter count;
10+
11+
public PersistentCounter(String name) {
12+
this.count = PersistenceUtil.createLongAdderAdapter(name);
13+
}
14+
15+
/**
16+
* Increment the counter by one.
17+
*/
18+
public void inc() {
19+
inc(1);
20+
}
21+
22+
/**
23+
* Increment the counter by {@code n}.
24+
*
25+
* @param n the amount by which the counter will be increased
26+
*/
27+
public void inc(long n) {
28+
count.add(n);
29+
}
30+
31+
/**
32+
* Decrement the counter by one.
33+
*/
34+
public void dec() {
35+
dec(1);
36+
}
37+
38+
/**
39+
* Decrement the counter by {@code n}.
40+
*
41+
* @param n the amount by which the counter will be decreased
42+
*/
43+
public void dec(long n) {
44+
count.add(-n);
45+
}
46+
47+
/**
48+
* Returns the counter's current value.
49+
*
50+
* @return the counter's current value
51+
*/
52+
@Override
53+
public long getCount() {
54+
return count.sum();
55+
}
56+
}

0 commit comments

Comments
 (0)