diff --git a/.gitignore b/.gitignore
index 1940f2a..9006e87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
.classpath
.project
.settings
+.idea
target
-coverage.ec
\ No newline at end of file
+coverage.ec
+*.iml
diff --git a/README.md b/README.md
index 87ecd37..9427e53 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# stackify-metrics
+[](http://mvnrepository.com/artifact/com.stackify/stackify-metrics)
[](https://travis-ci.org/stackify/stackify-metrics)
[](https://coveralls.io/r/stackify/stackify-metrics?branch=master)
@@ -7,12 +8,23 @@ API for sending custom metrics to Stackify.
Custom Metrics Overview:
-http://docs.stackify.com/m/7787/l/232533
+http://support.stackify.com/custom-metrics-overview/
Sign Up for a Trial:
http://www.stackify.com/sign-up/
+## Installation
+
+Add it as a maven dependency:
+```xml
+
+ com.stackify
+ stackify-metrics
+ 2.1.1
+
+```
+
## Usage
There are four different types of metrics:
@@ -44,6 +56,23 @@ stackify.environment=YOUR_ENVIRONMENT
Note: *If you are logging from a device that has the stackify-agent installed, the environment setting is optional. We will use the environment associated to your device in Stackify.*
+#### Programmatic Configuration (Optional)
+
+Instead of providing a properties file in your classpath, you can configure the Metrics API programmatically:
+```
+ApiConfiguration.Builder builder = ApiConfiguration.newBuilder();
+builder.apiKey("YOUR_API_KEY");
+builder.application("YOUR_APPLICATION_NAME");
+builder.environment("YOUR_ENVIRONMENT");
+ApiConfiguration config = builder.build();
+
+MetricManager.configure(config);
+```
+
+This needs to be done at application startup before any other interactions with the Metrics API.
+
+Note: *If you are logging from a device that has the stackify-agent installed, the environment setting is optional. We will use the environment associated to your device in Stackify.*
+
#### Gauge Metric
```java
@@ -179,22 +208,9 @@ counterAndTimer.autoReportZeroValue();
...
```
-## Installation
-
-Add it as a maven dependency:
-```xml
-
- com.stackify
- stackify-metrics
- 1.0.4
-
-```
-
-Note: *We are dependent on the Guava project from Google. We require version 14.0.1 (or beyond) for the background thread that sends data back to Stackify.*
-
## License
-Copyright 2014 Stackify, LLC.
+Copyright 2020 Stackify, LLC.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/pom.xml b/pom.xml
index bcb3c69..c754e9a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,17 +3,17 @@
com.stackify
stackify-metrics
- 1.0.4-SNAPSHOT
-
+ 2.1.2-SNAPSHOT
+
Stackify Metrics
Stackify Metrics
https://github.com/stackify/stackify-metrics
org.sonatype.oss
oss-parent
- 7
+ 9
-
+
The Apache Software License, Version 2.0
@@ -31,62 +31,60 @@
Stackify, LLC
http://www.stackify.com
-
+
eric-martin
Eric Martin
+
+ darinhoward
+ Darin Howard
+
-
+
1.6
-
+
-
+
- com.google.guava
- guava
- 14.0.1
+ com.stackify
+ stackify-api-java
+ 3.1.0
-
+
org.slf4j
slf4j-api
1.7.5
-
+
com.fasterxml.jackson.core
jackson-core
- 2.1.3
-
-
-
- com.fasterxml.jackson.core
- jackson-annotations
- 2.1.2
+ 2.9.10
-
+
- com.fasterxml.jackson.core
- jackson-databind
- 2.1.3
+ com.fasterxml.jackson.core
+ jackson-annotations
+ 2.9.10
-
+
- com.stackify
- stackify-api-java
- 2.0.2-SNAPSHOT
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.9.10.5
-
+
-
+
org.slf4j
slf4j-log4j12
@@ -100,53 +98,53 @@
4.11
test
-
+
org.mockito
mockito-core
1.9.5
test
-
+
org.powermock
powermock-core
1.5.6
test
-
+
org.powermock
powermock-module-junit4
1.5.6
test
-
+
org.powermock
powermock-api-mockito
1.5.6
test
-
+
nl.jqno.equalsverifier
equalsverifier
1.4.1
test
-
+
-
+
-
+
src/main/resources
true
-
+
org.apache.maven.wagon
@@ -154,9 +152,9 @@
2.2
-
+
-
+
org.apache.maven.plugins
maven-compiler-plugin
@@ -166,7 +164,7 @@
${java.version}
-
+
org.apache.maven.plugins
maven-jar-plugin
@@ -177,20 +175,25 @@
-
+
org.apache.maven.plugins
maven-javadoc-plugin
+ 2.9.1
attach-javadocs
jar
+
+ false
+ -Xdoclint:none
+
-
+
org.apache.maven.plugins
maven-source-plugin
@@ -203,7 +206,7 @@
-
+
org.apache.felix
maven-bundle-plugin
@@ -218,7 +221,7 @@
-
+
org.codehaus.mojo
cobertura-maven-plugin
@@ -229,31 +232,31 @@
-
+
org.eluder.coveralls
coveralls-maven-plugin
2.2.0
-
+
-
+
-
+
-
+
org.apache.maven.plugins
maven-javadoc-plugin
2.9.1
-
+
-
+
-
+
release-sign-artifacts
@@ -283,5 +286,5 @@
-
-
\ No newline at end of file
+
+
diff --git a/src/main/java/com/stackify/metric/MetricManager.java b/src/main/java/com/stackify/metric/MetricManager.java
index 31e3d4f..0b0c36d 100644
--- a/src/main/java/com/stackify/metric/MetricManager.java
+++ b/src/main/java/com/stackify/metric/MetricManager.java
@@ -15,17 +15,16 @@
*/
package com.stackify.metric;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Throwables;
import com.stackify.api.common.ApiConfiguration;
import com.stackify.api.common.ApiConfigurations;
import com.stackify.api.common.AppIdentityService;
+import com.stackify.api.common.EnvironmentDetails;
import com.stackify.metric.impl.MetricBackgroundService;
import com.stackify.metric.impl.MetricCollector;
import com.stackify.metric.impl.MetricMonitorService;
@@ -72,25 +71,52 @@ public static MetricCollector getCollector() {
return COLLECTOR;
}
+
+ /**
+ * Manually configure the metrics api
+ * @param config API configuration
+ */
+ public static synchronized void configure(final ApiConfiguration config) {
+
+ ApiConfiguration.Builder builder = ApiConfiguration.newBuilder();
+ builder.apiUrl(config.getApiUrl());
+ builder.apiKey(config.getApiKey());
+ builder.application(config.getApplication());
+ builder.environment(config.getEnvironment());
+
+ if (config.getEnvDetail() == null)
+ {
+ builder.envDetail(EnvironmentDetails.getEnvironmentDetail(config.getApplication(), config.getEnvironment()));
+ }
+ else
+ {
+ builder.envDetail(config.getEnvDetail());
+ }
+
+ CONFIG = builder.build();
+ }
+
/**
* Start up the background thread that is processing metrics
*/
private static synchronized void startup() {
try {
- CONFIG = ApiConfigurations.fromProperties();
-
+ if (CONFIG == null) {
+ CONFIG = ApiConfigurations.fromProperties();
+ }
+
ObjectMapper objectMapper = new ObjectMapper();
- AppIdentityService appIdentityService = new AppIdentityService(CONFIG, objectMapper);
+ AppIdentityService appIdentityService = new AppIdentityService(CONFIG, objectMapper, true);
MetricMonitorService monitorService = new MetricMonitorService(CONFIG, objectMapper, appIdentityService);
MetricSender sender = new MetricSender(CONFIG, objectMapper, monitorService);
BACKGROUND_SERVICE = new MetricBackgroundService(COLLECTOR, sender);
- BACKGROUND_SERVICE.start().get(5, TimeUnit.SECONDS);
+ BACKGROUND_SERVICE.start();
} catch (Throwable t) {
LOGGER.error("Exception starting Stackify Metrics API service", t);
@@ -103,10 +129,12 @@ private static synchronized void startup() {
public static synchronized void shutdown() {
if (BACKGROUND_SERVICE != null) {
try {
- BACKGROUND_SERVICE.stop().get(5, TimeUnit.SECONDS);
- } catch (Exception e) {
- Throwables.propagate(e);
+ BACKGROUND_SERVICE.stop();
+ } catch (Throwable t) {
+ LOGGER.error("Exception stopping Stackify Metrics API service", t);
}
+
+ INITIALIZED.compareAndSet(true, false);
}
}
diff --git a/src/main/java/com/stackify/metric/impl/JsonMetric.java b/src/main/java/com/stackify/metric/impl/JsonMetric.java
index 96d4f3f..7b93083 100644
--- a/src/main/java/com/stackify/metric/impl/JsonMetric.java
+++ b/src/main/java/com/stackify/metric/impl/JsonMetric.java
@@ -62,6 +62,12 @@ public class JsonMetric {
@JsonProperty("MonitorTypeID")
private final Integer monitorTypeId;
+ /**
+ * Client device id
+ */
+ @JsonProperty("ClientDeviceID")
+ private final Integer clientDeviceId;
+
/**
* @return the monitorId
*/
@@ -97,6 +103,13 @@ public Integer getMonitorTypeId() {
return monitorTypeId;
}
+ /**
+ * @return the clientDeviceId
+ */
+ public Integer getClientDeviceId() {
+ return clientDeviceId;
+ }
+
/**
* @param builder The Builder object that contains all of the values for initialization
*/
@@ -106,6 +119,7 @@ private JsonMetric(final Builder builder) {
this.count = builder.count;
this.occurredUtc = builder.occurredUtc;
this.monitorTypeId = builder.monitorTypeId;
+ this.clientDeviceId = builder.clientDeviceId;
}
/**
@@ -152,6 +166,12 @@ public static class Builder {
@JsonProperty("MonitorTypeID")
private Integer monitorTypeId;
+ /**
+ * The builder's clientDeviceId
+ */
+ @JsonProperty("ClientDeviceID")
+ private Integer clientDeviceId;
+
/**
* Sets the builder's monitorId
* @param monitorId The monitorId to be set
@@ -202,6 +222,16 @@ public Builder monitorTypeId(final Integer monitorTypeId) {
return this;
}
+ /**
+ * Sets the builder's clientDeviceId
+ * @param clientDeviceId The clientDeviceId to be set
+ * @return Reference to the current object
+ */
+ public Builder clientDeviceId(final Integer clientDeviceId) {
+ this.clientDeviceId = clientDeviceId;
+ return this;
+ }
+
/**
* @return A new object constructed from this builder
*/
diff --git a/src/main/java/com/stackify/metric/impl/Metric.java b/src/main/java/com/stackify/metric/impl/Metric.java
index eb065db..1a92d0c 100644
--- a/src/main/java/com/stackify/metric/impl/Metric.java
+++ b/src/main/java/com/stackify/metric/impl/Metric.java
@@ -15,7 +15,6 @@
*/
package com.stackify.metric.impl;
-import com.google.common.base.Objects;
/**
* Metric
@@ -147,16 +146,11 @@ public Metric build() {
/**
* @see java.lang.Object#toString()
- * @return A string representation of the object
*/
@Override
public String toString() {
- return Objects.toStringHelper(this)
- .omitNullValues()
- .add("identity", identity)
- .add("occurredMillis", occurredMillis)
- .add("value", value)
- .add("isIncrement", isIncrement)
- .toString();
+ return "Metric [identity=" + identity + ", occurredMillis="
+ + occurredMillis + ", value=" + value + ", isIncrement="
+ + isIncrement + "]";
}
}
diff --git a/src/main/java/com/stackify/metric/impl/MetricAggregate.java b/src/main/java/com/stackify/metric/impl/MetricAggregate.java
index 92cdfea..dd25641 100644
--- a/src/main/java/com/stackify/metric/impl/MetricAggregate.java
+++ b/src/main/java/com/stackify/metric/impl/MetricAggregate.java
@@ -15,8 +15,7 @@
*/
package com.stackify.metric.impl;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricAggregate
@@ -111,16 +110,11 @@ public long getOccurredMillis() {
/**
* @see java.lang.Object#toString()
- * @return A string representation of the object
*/
@Override
public String toString() {
- return Objects.toStringHelper(this)
- .omitNullValues()
- .add("identity", identity)
- .add("occurredMillis", occurredMillis)
- .add("value", value)
- .add("count", count)
- .toString();
+ return "MetricAggregate [identity=" + identity + ", occurredMillis="
+ + occurredMillis + ", value=" + value + ", count=" + count
+ + "]";
}
}
diff --git a/src/main/java/com/stackify/metric/impl/MetricAggregator.java b/src/main/java/com/stackify/metric/impl/MetricAggregator.java
index c916005..fa72b66 100644
--- a/src/main/java/com/stackify/metric/impl/MetricAggregator.java
+++ b/src/main/java/com/stackify/metric/impl/MetricAggregator.java
@@ -15,6 +15,8 @@
*/
package com.stackify.metric.impl;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -22,9 +24,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricAggregator
@@ -40,7 +40,7 @@ public class MetricAggregator {
/**
* Map from metric key to utc minute to metric aggregate)
*/
- private final Map> aggregates = Maps.newHashMap();
+ private final Map> aggregates = new HashMap>();
/**
* Current minute
@@ -69,7 +69,7 @@ public MetricAggregator(final long currentMinute, final Map getAggregates() {
- List flatAggregates = Lists.newArrayList();
+ List flatAggregates = new ArrayList();
for (Map metricAggregates : aggregates.values()) {
for (MetricAggregate aggregate : metricAggregates.values()) {
@@ -180,7 +180,7 @@ private MetricAggregate getAggregate(final MetricIdentity identity) {
// get the map from utc minute to aggregate for this metric
if (!aggregates.containsKey(identity)) {
- aggregates.put(identity, Maps.newHashMap());
+ aggregates.put(identity, new HashMap());
}
Map metricAggregates = aggregates.get(identity);
diff --git a/src/main/java/com/stackify/metric/impl/MetricBackgroundService.java b/src/main/java/com/stackify/metric/impl/MetricBackgroundService.java
index a893f3a..333dedf 100644
--- a/src/main/java/com/stackify/metric/impl/MetricBackgroundService.java
+++ b/src/main/java/com/stackify/metric/impl/MetricBackgroundService.java
@@ -18,14 +18,14 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.util.concurrent.AbstractScheduledService;
+import com.stackify.api.common.concurrent.BackgroundService;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricBackgroundService
* @author Eric Martin
*/
-public class MetricBackgroundService extends AbstractScheduledService {
+public class MetricBackgroundService extends BackgroundService {
/**
* Logger
@@ -60,19 +60,10 @@ public MetricBackgroundService(final MetricCollector collector, final MetricSend
}
/**
- * @see com.google.common.util.concurrent.AbstractScheduledService#serviceName()
+ * @see com.stackify.api.common.concurrent.BackgroundService#startUp()
*/
@Override
- protected String serviceName() {
- return "Stackify_MetricBackgroundService";
- }
-
- /**
- * @see com.google.common.util.concurrent.AbstractScheduledService#scheduler()
- */
- @Override
- protected Scheduler scheduler() {
- return scheduler;
+ protected void startUp() {
}
/**
@@ -89,6 +80,14 @@ protected void runOneIteration() {
}
}
+ /**
+ * @see com.stackify.api.common.concurrent.BackgroundService#getNextScheduleDelayMilliseconds()
+ */
+ @Override
+ protected long getNextScheduleDelayMilliseconds() {
+ return scheduler.getScheduleDelay();
+ }
+
/**
* @see com.google.common.util.concurrent.AbstractScheduledService#shutDown()
*/
@@ -99,7 +98,5 @@ protected void shutDown() throws Exception {
} catch (Throwable t) {
LOGGER.info("Exception flushing metrics collector during shut down", t);
}
-
- super.shutDown();
}
}
diff --git a/src/main/java/com/stackify/metric/impl/MetricBackgroundServiceScheduler.java b/src/main/java/com/stackify/metric/impl/MetricBackgroundServiceScheduler.java
index 10c6787..356d87e 100644
--- a/src/main/java/com/stackify/metric/impl/MetricBackgroundServiceScheduler.java
+++ b/src/main/java/com/stackify/metric/impl/MetricBackgroundServiceScheduler.java
@@ -16,9 +16,7 @@
package com.stackify.metric.impl;
import java.net.HttpURLConnection;
-import java.util.concurrent.TimeUnit;
-import com.google.common.util.concurrent.AbstractScheduledService.CustomScheduler;
import com.stackify.api.common.http.HttpException;
/**
@@ -26,7 +24,7 @@
*
* @author Eric Martin
*/
-public class MetricBackgroundServiceScheduler extends CustomScheduler {
+public class MetricBackgroundServiceScheduler {
/**
* Five seconds (milliseconds)
@@ -99,12 +97,4 @@ public void update(final Throwable t) {
public long getScheduleDelay() {
return scheduleDelay;
}
-
- /**
- * @see com.google.common.util.concurrent.AbstractScheduledService.CustomScheduler#getNextSchedule()
- */
- @Override
- protected Schedule getNextSchedule() {
- return new Schedule(scheduleDelay, TimeUnit.MILLISECONDS);
- }
}
diff --git a/src/main/java/com/stackify/metric/impl/MetricCollector.java b/src/main/java/com/stackify/metric/impl/MetricCollector.java
index 79a31af..eaf5fa3 100644
--- a/src/main/java/com/stackify/metric/impl/MetricCollector.java
+++ b/src/main/java/com/stackify/metric/impl/MetricCollector.java
@@ -16,6 +16,8 @@
package com.stackify.metric.impl;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
@@ -24,12 +26,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Queues;
-import com.google.common.collect.Sets;
+import com.stackify.api.common.collect.SynchronizedEvictingQueue;
import com.stackify.api.common.http.HttpException;
-import com.stackify.api.common.lang.EvictingQueue;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricCollector
@@ -50,22 +49,22 @@ public class MetricCollector {
/**
* The queue of objects to be transmitted
*/
- private final Queue queue = Queues.synchronizedQueue(new EvictingQueue(1000));
+ private final Queue queue = new SynchronizedEvictingQueue(100000);
/**
* Initial values for the next iteration
*/
- private final Map lastValues = Maps.newHashMap();
+ private final Map lastValues = new HashMap();
/**
* Metrics that should auto report zero if there isn't a current value
*/
- private final Set autoReportZeroMetrics = Sets.newHashSet();
+ private final Set autoReportZeroMetrics = new HashSet();
/**
* Metrics that should auto report the last value if there isn't a current value
*/
- private final Set autoReportLastMetrics = Sets.newHashSet();
+ private final Set autoReportLastMetrics = new HashSet();
/**
* The last time the collector was flushed
@@ -116,6 +115,7 @@ public int flush(final MetricSender sender) throws IOException, HttpException {
long currentMinute = (System.currentTimeMillis() / MS_IN_MIN) * MS_IN_MIN;
LOGGER.debug("Flushing metrics < {}", currentMinute);
+ LOGGER.debug("Metrics queue size {}", queue.size());
MetricAggregator aggregator = new MetricAggregator(currentMinute, lastValues);
diff --git a/src/main/java/com/stackify/metric/impl/MetricIdentity.java b/src/main/java/com/stackify/metric/impl/MetricIdentity.java
index 08576e9..c29611c 100644
--- a/src/main/java/com/stackify/metric/impl/MetricIdentity.java
+++ b/src/main/java/com/stackify/metric/impl/MetricIdentity.java
@@ -15,8 +15,7 @@
*/
package com.stackify.metric.impl;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricIdentity
@@ -80,46 +79,51 @@ public MetricMonitorType getType() {
/**
* @see java.lang.Object#hashCode()
- * @return A hash code of this object
*/
@Override
public int hashCode() {
- return Objects.hashCode(category, name, type);
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((category == null) ? 0 : category.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
- * @param other The reference object with which to compare
- * @return True if this object is the same as the other object, false otherwise
*/
@Override
- public boolean equals(final Object other) {
- if (other == this) {
- return true;
- }
-
- if (!(other instanceof MetricIdentity)) {
- return false;
- }
-
- final MetricIdentity otherMetricIdentity = (MetricIdentity) other;
-
- return Objects.equal(category, otherMetricIdentity.category)
- && Objects.equal(name, otherMetricIdentity.name)
- && Objects.equal(type, otherMetricIdentity.type);
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (!(obj instanceof MetricIdentity))
+ return false;
+ MetricIdentity other = (MetricIdentity) obj;
+ if (category == null) {
+ if (other.category != null)
+ return false;
+ } else if (!category.equals(other.category))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (type != other.type)
+ return false;
+ return true;
}
/**
* @see java.lang.Object#toString()
- * @return A string representation of the object
*/
@Override
public String toString() {
- return Objects.toStringHelper(this)
- .omitNullValues()
- .add("category", category)
- .add("name", name)
- .add("type", type)
- .toString();
+ return "MetricIdentity [category=" + category + ", name=" + name
+ + ", type=" + type + "]";
}
}
diff --git a/src/main/java/com/stackify/metric/impl/MetricMonitorService.java b/src/main/java/com/stackify/metric/impl/MetricMonitorService.java
index bf44490..d863172 100644
--- a/src/main/java/com/stackify/metric/impl/MetricMonitorService.java
+++ b/src/main/java/com/stackify/metric/impl/MetricMonitorService.java
@@ -16,6 +16,7 @@
package com.stackify.metric.impl;
import java.io.IOException;
+import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
@@ -24,14 +25,12 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
import com.stackify.api.AppIdentity;
import com.stackify.api.common.ApiConfiguration;
import com.stackify.api.common.AppIdentityService;
import com.stackify.api.common.http.HttpClient;
import com.stackify.api.common.http.HttpException;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricMonitorService
@@ -52,12 +51,12 @@ public class MetricMonitorService {
/**
* Timestamp of the last queries
*/
- private final Map lastQueries = Maps.newHashMap();
+ private final Map lastQueries = new HashMap();
/**
* The cached monitor ids
*/
- private Map monitorIds = Maps.newHashMap();
+ private Map monitorIds = new HashMap();
/**
* API configuration
@@ -89,6 +88,19 @@ public MetricMonitorService(final ApiConfiguration apiConfig, final ObjectMapper
this.appIdentityService = appIdentityService;
}
+ /**
+ * @return Client device id
+ */
+ public Integer getDeviceId() {
+ AppIdentity appIdentity = appIdentityService.getAppIdentity();
+
+ if (appIdentity != null) {
+ return appIdentity.getDeviceId();
+ }
+
+ return null;
+ }
+
/**
* Gets the monitor id for this metric
* @param identity The metric identity
@@ -96,11 +108,11 @@ public MetricMonitorService(final ApiConfiguration apiConfig, final ObjectMapper
* @throws IOException
* @throws HttpException
*/
- public Optional getMonitorId(final MetricIdentity identity) throws IOException, HttpException {
+ public Integer getMonitorId(final MetricIdentity identity) throws IOException, HttpException {
Preconditions.checkNotNull(identity);
if (monitorIds.containsKey(identity)) {
- return Optional.of(monitorIds.get(identity));
+ return monitorIds.get(identity);
}
long lastQuery = 0;
@@ -115,11 +127,11 @@ public Optional getMonitorId(final MetricIdentity identity) throws IOEx
try {
lastQueries.put(identity, lastQuery);
- Optional appIdentity = appIdentityService.getAppIdentity();
+ AppIdentity appIdentity = appIdentityService.getAppIdentity();
- if (appIdentity.isPresent()) {
+ if (appIdentity != null) {
- int monitorId = getMetricInfo(identity, appIdentity.get());
+ int monitorId = getMetricInfo(identity, appIdentity);
LOGGER.debug("Metric {} monitor id: {}", identity, monitorId);
@@ -133,10 +145,10 @@ public Optional getMonitorId(final MetricIdentity identity) throws IOEx
}
if (monitorIds.containsKey(identity)) {
- return Optional.of(monitorIds.get(identity));
+ return monitorIds.get(identity);
}
- return Optional.absent();
+ return null;
}
/**
@@ -166,11 +178,18 @@ private int getMetricInfo(final MetricIdentity identity, final AppIdentity appId
byte[] jsonBytes = objectMapper.writer().writeValueAsBytes(request);
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("GetMetricInfo Request: {}", new String(jsonBytes, "UTF-8"));
+ }
+
// post to stackify
HttpClient httpClient = new HttpClient(apiConfig);
String responseString = httpClient.post("/Metrics/GetMetricInfo", jsonBytes);
+ LOGGER.debug("GetMetricInfo Response: {}", responseString);
+
// deserialize the response and return the monitor id
ObjectReader jsonReader = objectMapper.reader(new TypeReference(){});
diff --git a/src/main/java/com/stackify/metric/impl/MetricSender.java b/src/main/java/com/stackify/metric/impl/MetricSender.java
index d94b275..2f92500 100644
--- a/src/main/java/com/stackify/metric/impl/MetricSender.java
+++ b/src/main/java/com/stackify/metric/impl/MetricSender.java
@@ -16,6 +16,7 @@
package com.stackify.metric.impl;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -23,12 +24,11 @@
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
import com.stackify.api.common.ApiConfiguration;
import com.stackify.api.common.http.HttpClient;
import com.stackify.api.common.http.HttpException;
+import com.stackify.api.common.http.HttpResendQueue;
+import com.stackify.api.common.util.Preconditions;
/**
* MetricSender
@@ -56,6 +56,11 @@ public class MetricSender {
*/
private final MetricMonitorService monitorService;
+ /**
+ * The queue of requests to be retransmitted (60 minutes of metric aggregates)
+ */
+ private final HttpResendQueue resendQueue = new HttpResendQueue(60);
+
/**
* Constructor
* @param apiConfig API configuration
@@ -79,21 +84,28 @@ public MetricSender(final ApiConfiguration apiConfig, final ObjectMapper objectM
*/
public void send(final List aggregates) throws IOException, HttpException {
+ HttpClient httpClient = new HttpClient(apiConfig);
+
+ // retransmit any metrics on the resend queue
+
+ resendQueue.drain(httpClient, "/Metrics/SubmitMetricsByID");
+
// build the json objects
- List metrics = Lists.newArrayListWithCapacity(aggregates.size());
+ List metrics = new ArrayList(aggregates.size());
for (MetricAggregate aggregate : aggregates) {
- Optional monitorId = monitorService.getMonitorId(aggregate.getIdentity());
+ Integer monitorId = monitorService.getMonitorId(aggregate.getIdentity());
- if (monitorId.isPresent()) {
+ if (monitorId != null) {
JsonMetric.Builder builder = JsonMetric.newBuilder();
- builder.monitorId(monitorId.get());
+ builder.monitorId(monitorId);
builder.value(Double.valueOf(aggregate.getValue()));
builder.count(Integer.valueOf(aggregate.getCount()));
builder.occurredUtc(new Date(aggregate.getOccurredMillis()));
builder.monitorTypeId(Integer.valueOf(aggregate.getIdentity().getType().getId()));
+ builder.clientDeviceId(monitorService.getDeviceId());
metrics.add(builder.build());
} else {
@@ -105,13 +117,20 @@ public void send(final List aggregates) throws IOException, Htt
return;
}
- // convert to json bytes
-
- byte[] jsonBytes = objectMapper.writer().writeValueAsBytes(metrics);
+ // post metrics to stackify
- // post to stackify
+ byte[] jsonBytes = objectMapper.writer().writeValueAsBytes(metrics);
- HttpClient httpClient = new HttpClient(apiConfig);
- httpClient.post("/Metrics/SubmitMetricsByID", jsonBytes);
+ try {
+ httpClient.post("/Metrics/SubmitMetricsByID", jsonBytes);
+ } catch (IOException t) {
+ LOGGER.info("Queueing metrics for retransmission due to IOException");
+ resendQueue.offer(jsonBytes, t);
+ throw t;
+ } catch (HttpException t) {
+ LOGGER.info("Queueing metrics for retransmission due to HttpException");
+ resendQueue.offer(jsonBytes, t);
+ throw t;
+ }
}
}
diff --git a/src/test/java/com/stackify/metric/MetricManagerTest.java b/src/test/java/com/stackify/metric/MetricManagerTest.java
index 7cbd74c..7c1cfed 100644
--- a/src/test/java/com/stackify/metric/MetricManagerTest.java
+++ b/src/test/java/com/stackify/metric/MetricManagerTest.java
@@ -15,6 +15,7 @@
*/
package com.stackify.metric;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -23,7 +24,8 @@
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.stackify.api.common.ApiConfiguration;
+import com.stackify.api.common.ApiConfigurations;
import com.stackify.api.common.AppIdentityService;
import com.stackify.metric.impl.MetricBackgroundService;
import com.stackify.metric.impl.MetricCollector;
@@ -35,9 +37,17 @@
* @author Eric Martin
*/
@RunWith(PowerMockRunner.class)
-@PrepareForTest({MetricManager.class, AppIdentityService.class, MetricMonitorService.class, MetricSender.class, MetricBackgroundService.class})
+@PrepareForTest({MetricManager.class, AppIdentityService.class, MetricMonitorService.class, MetricSender.class, MetricBackgroundService.class, ApiConfigurations.class})
public class MetricManagerTest {
+ /**
+ * tearDown
+ */
+ @After
+ public void tearDown() {
+ MetricManager.shutdown();
+ }
+
/**
* testGetCollectorAndShutdown
* @throws Exception
@@ -54,8 +64,6 @@ public void testGetCollectorAndShutdown() throws Exception {
PowerMockito.whenNew(MetricSender.class).withAnyArguments().thenReturn(sender);
MetricBackgroundService background = PowerMockito.mock(MetricBackgroundService.class);
- Mockito.when(background.start()).thenReturn(Mockito.mock(ListenableFuture.class));
- Mockito.when(background.stop()).thenReturn(Mockito.mock(ListenableFuture.class));
PowerMockito.whenNew(MetricBackgroundService.class).withAnyArguments().thenReturn(background);
MetricManager.shutdown();
@@ -76,4 +84,40 @@ public void testGetCollectorAndShutdown() throws Exception {
Mockito.verify(background).stop();
}
+
+ /**
+ * testManualConfig
+ * @throws Exception
+ */
+ @Test
+ public void testManualConfig() throws Exception {
+
+ PowerMockito.mockStatic(ApiConfigurations.class);
+ PowerMockito.when(ApiConfigurations.fromProperties()).thenThrow(new RuntimeException());
+
+ ApiConfiguration config = Mockito.mock(ApiConfiguration.class);
+
+ MetricManager.configure(config);
+
+ AppIdentityService ais = Mockito.mock(AppIdentityService.class);
+ PowerMockito.whenNew(AppIdentityService.class).withAnyArguments().thenReturn(ais);
+
+ MetricMonitorService mms = Mockito.mock(MetricMonitorService.class);
+ PowerMockito.whenNew(MetricMonitorService.class).withAnyArguments().thenReturn(mms);
+
+ MetricSender sender = Mockito.mock(MetricSender.class);
+ PowerMockito.whenNew(MetricSender.class).withAnyArguments().thenReturn(sender);
+
+ MetricBackgroundService background = PowerMockito.mock(MetricBackgroundService.class);
+ PowerMockito.whenNew(MetricBackgroundService.class).withAnyArguments().thenReturn(background);
+
+ MetricCollector collector = MetricManager.getCollector();
+ Assert.assertNotNull(collector);
+
+ Mockito.verify(background).start();
+
+ MetricManager.shutdown();
+
+ Mockito.verify(background).stop();
+ }
}
diff --git a/src/test/java/com/stackify/metric/impl/MetricAggregatorTest.java b/src/test/java/com/stackify/metric/impl/MetricAggregatorTest.java
index 79151c9..10c1089 100644
--- a/src/test/java/com/stackify/metric/impl/MetricAggregatorTest.java
+++ b/src/test/java/com/stackify/metric/impl/MetricAggregatorTest.java
@@ -16,15 +16,14 @@
package com.stackify.metric.impl;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-
/**
* MetricAggregatorTest
* @author Eric Martin
@@ -105,12 +104,14 @@ public void testAddGauge() {
public void testAutoReportZero() {
MetricIdentity identity = new MetricIdentity("category", "name", MetricMonitorType.COUNTER);
- Map lastValues = Maps.newHashMap();
+ Map lastValues = new HashMap();
lastValues.put(identity, Double.valueOf(14.0));
MetricAggregator aggregator = new MetricAggregator(System.currentTimeMillis(), lastValues);
- aggregator.autoReportZero(Sets.newHashSet(identity));
+ Set arz = new HashSet();
+ arz.add(identity);
+ aggregator.autoReportZero(arz);
List aggregates = aggregator.getAggregates();
@@ -129,12 +130,14 @@ public void testAutoReportZero() {
public void testAutoReportLast() {
MetricIdentity identity = new MetricIdentity("category", "name", MetricMonitorType.COUNTER);
- Map lastValues = Maps.newHashMap();
+ Map lastValues = new HashMap();
lastValues.put(identity, Double.valueOf(14.0));
MetricAggregator aggregator = new MetricAggregator(System.currentTimeMillis(), lastValues);
- aggregator.autoReportLast(Sets.newHashSet(identity));
+ Set arl = new HashSet();
+ arl.add(identity);
+ aggregator.autoReportLast(arl);
List aggregates = aggregator.getAggregates();
@@ -153,11 +156,13 @@ public void testAutoReportLast() {
public void testAutoReportLastWithoutLast() {
MetricIdentity identity = new MetricIdentity("category", "name", MetricMonitorType.COUNTER);
- Map lastValues = Maps.newHashMap();
+ Map lastValues = new HashMap();
MetricAggregator aggregator = new MetricAggregator(System.currentTimeMillis(), lastValues);
- aggregator.autoReportLast(Sets.newHashSet(identity));
+ Set arl = new HashSet();
+ arl.add(identity);
+ aggregator.autoReportLast(arl);
List aggregates = aggregator.getAggregates();
diff --git a/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceSchedulerTest.java b/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceSchedulerTest.java
index c7d6df8..3cbfc9f 100644
--- a/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceSchedulerTest.java
+++ b/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceSchedulerTest.java
@@ -27,8 +27,6 @@
*
* @author Eric Martin
*/
-//@RunWith(PowerMockRunner.class)
-//@PrepareForTest({MetricBackgroundServiceScheduler.class, System.class})
public class MetricBackgroundServiceSchedulerTest {
/**
@@ -39,7 +37,6 @@ public void testNoUpdate() {
MetricBackgroundServiceScheduler scheduler = new MetricBackgroundServiceScheduler();
Assert.assertEquals(5000, scheduler.getScheduleDelay());
- Assert.assertNotNull(scheduler.getNextSchedule());
}
/**
@@ -52,7 +49,6 @@ public void testUpdateOk() {
scheduler.update(50);
Assert.assertEquals(5000, scheduler.getScheduleDelay());
- Assert.assertNotNull(scheduler.getNextSchedule());
}
/**
@@ -65,7 +61,6 @@ public void testUpdateUnauthorized() {
scheduler.update(new HttpException(HttpURLConnection.HTTP_UNAUTHORIZED));
Assert.assertEquals(300000, scheduler.getScheduleDelay());
- Assert.assertNotNull(scheduler.getNextSchedule());
}
/**
@@ -78,7 +73,6 @@ public void testUpdateError() {
scheduler.update(new HttpException(HttpURLConnection.HTTP_INTERNAL_ERROR));
Assert.assertEquals(15000, scheduler.getScheduleDelay());
- Assert.assertNotNull(scheduler.getNextSchedule());
}
/**
@@ -91,11 +85,9 @@ public void testUpdateErrorAndClear() {
scheduler.update(new HttpException(HttpURLConnection.HTTP_INTERNAL_ERROR));
Assert.assertEquals(15000, scheduler.getScheduleDelay());
- Assert.assertNotNull(scheduler.getNextSchedule());
scheduler.update(50);
Assert.assertEquals(5000, scheduler.getScheduleDelay());
- Assert.assertNotNull(scheduler.getNextSchedule());
}
}
diff --git a/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceTest.java b/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceTest.java
index 081960e..cc841ce 100644
--- a/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceTest.java
+++ b/src/test/java/com/stackify/metric/impl/MetricBackgroundServiceTest.java
@@ -38,8 +38,7 @@ public void testConstructor() {
MetricSender sender = Mockito.mock(MetricSender.class);
MetricBackgroundService service = new MetricBackgroundService(collector, sender);
- Assert.assertEquals("Stackify_MetricBackgroundService", service.serviceName());
- Assert.assertNotNull(service.scheduler());
+ Assert.assertFalse(service.isRunning());
}
/**
diff --git a/src/test/java/com/stackify/metric/impl/MetricMonitorServiceTest.java b/src/test/java/com/stackify/metric/impl/MetricMonitorServiceTest.java
index 2c86f75..d1cfcc6 100644
--- a/src/test/java/com/stackify/metric/impl/MetricMonitorServiceTest.java
+++ b/src/test/java/com/stackify/metric/impl/MetricMonitorServiceTest.java
@@ -24,7 +24,6 @@
import org.powermock.modules.junit4.PowerMockRunner;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Optional;
import com.stackify.api.AppIdentity;
import com.stackify.api.common.ApiConfiguration;
import com.stackify.api.common.AppIdentityService;
@@ -47,7 +46,7 @@ public void testNoAppIdentity() throws Exception {
ApiConfiguration apiConfig = Mockito.mock(ApiConfiguration.class);
ObjectMapper objectMapper = new ObjectMapper();
AppIdentityService appIdentityService = Mockito.mock(AppIdentityService.class);
- Mockito.when(appIdentityService.getAppIdentity()).thenReturn(Optional.absent());
+ Mockito.when(appIdentityService.getAppIdentity()).thenReturn(null);
HttpClient httpClient = PowerMockito.mock(HttpClient.class);
PowerMockito.whenNew(HttpClient.class).withAnyArguments().thenReturn(httpClient);
@@ -57,10 +56,9 @@ public void testNoAppIdentity() throws Exception {
MetricIdentity identity = new MetricIdentity("category", "name", MetricMonitorType.COUNTER);
- Optional id = service.getMonitorId(identity);
+ Integer id = service.getMonitorId(identity);
- Assert.assertNotNull(id);
- Assert.assertFalse(id.isPresent());
+ Assert.assertNull(id);
Mockito.verifyZeroInteractions(httpClient);
}
@@ -74,7 +72,7 @@ public void testGetMonitorId() throws Exception {
ApiConfiguration apiConfig = Mockito.mock(ApiConfiguration.class);
ObjectMapper objectMapper = new ObjectMapper();
AppIdentityService appIdentityService = Mockito.mock(AppIdentityService.class);
- Mockito.when(appIdentityService.getAppIdentity()).thenReturn(Optional.of(Mockito.mock(AppIdentity.class)));
+ Mockito.when(appIdentityService.getAppIdentity()).thenReturn(Mockito.mock(AppIdentity.class));
HttpClient httpClient = PowerMockito.mock(HttpClient.class);
PowerMockito.whenNew(HttpClient.class).withAnyArguments().thenReturn(httpClient);
@@ -84,21 +82,18 @@ public void testGetMonitorId() throws Exception {
MetricIdentity identity = new MetricIdentity("category", "name", MetricMonitorType.COUNTER);
- Optional id = service.getMonitorId(identity);
+ Integer id = service.getMonitorId(identity);
Assert.assertNotNull(id);
- Assert.assertTrue(id.isPresent());
- Assert.assertEquals(14, id.get().intValue());
+ Assert.assertEquals(14, id.intValue());
- Optional cachedId = service.getMonitorId(identity);
+ Integer cachedId = service.getMonitorId(identity);
Assert.assertNotNull(cachedId);
- Assert.assertTrue(cachedId.isPresent());
- Assert.assertEquals(14, cachedId.get().intValue());
+ Assert.assertEquals(14, cachedId.intValue());
- Optional absentId = service.getMonitorId(new MetricIdentity("does-not", "exist", MetricMonitorType.COUNTER));
+ Integer absentId = service.getMonitorId(new MetricIdentity("does-not", "exist", MetricMonitorType.COUNTER));
- Assert.assertNotNull(absentId);
- Assert.assertFalse(absentId.isPresent());
+ Assert.assertNull(absentId);
}
}
diff --git a/src/test/java/com/stackify/metric/impl/MetricSenderTest.java b/src/test/java/com/stackify/metric/impl/MetricSenderTest.java
index cffbdad..faa6fad 100644
--- a/src/test/java/com/stackify/metric/impl/MetricSenderTest.java
+++ b/src/test/java/com/stackify/metric/impl/MetricSenderTest.java
@@ -25,7 +25,6 @@
import org.powermock.modules.junit4.PowerMockRunner;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.Optional;
import com.stackify.api.common.ApiConfiguration;
import com.stackify.api.common.http.HttpClient;
@@ -48,7 +47,7 @@ public void testSend() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
MetricMonitorService monitorService = Mockito.mock(MetricMonitorService.class);
- Mockito.when(monitorService.getMonitorId(Mockito.any(MetricIdentity.class))).thenReturn(Optional.of(14));
+ Mockito.when(monitorService.getMonitorId(Mockito.any(MetricIdentity.class))).thenReturn(14);
HttpClient httpClient = PowerMockito.mock(HttpClient.class);
PowerMockito.whenNew(HttpClient.class).withAnyArguments().thenReturn(httpClient);
@@ -75,7 +74,7 @@ public void testSendWithoutMonitorId() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
MetricMonitorService monitorService = Mockito.mock(MetricMonitorService.class);
- Mockito.when(monitorService.getMonitorId(Mockito.any(MetricIdentity.class))).thenReturn(Optional.absent());
+ Mockito.when(monitorService.getMonitorId(Mockito.any(MetricIdentity.class))).thenReturn(null);
HttpClient httpClient = PowerMockito.mock(HttpClient.class);
PowerMockito.whenNew(HttpClient.class).withAnyArguments().thenReturn(httpClient);