Skip to content

Commit

Permalink
Prototypical functionality added for #22.
Browse files Browse the repository at this point in the history
  • Loading branch information
dekobon committed Oct 4, 2015
1 parent cbcb647 commit 47126ff
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 2 deletions.
111 changes: 111 additions & 0 deletions src/main/java/io/honeybadger/reporter/dto/Load.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package io.honeybadger.reporter.dto;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.util.Scanner;

/**
* Class containing statistics about the host system's load average.
*
* @author <a href="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/dekobon">Elijah Zupancic</a>
* @since 1.0.11
*/
public class Load implements Serializable {
private static final long serialVersionUID = 3398000045209329774L;

public final Number one;
public final Number five;
public final Number fifteen;

public Load() {
Number[] loadAverages = findLoadAverages();
this.one = loadAverages[0];
this.five = loadAverages[1];
this.fifteen = loadAverages[2];
}

public Load(Number one, Number five, Number fifteen) {
this.one = one;
this.five = five;
this.fifteen = fifteen;
}

/**
* Attempts to find all three load values in a way that is safe for an in-process
* operation. This leads to platform specific code. We attempt to avoid forking to
* call external processes because this would be a bad thing to do on every error
* that came into the system.
*
* @return an array containing all three load averages (1, 5, 15) in that order
*/
static Number[] findLoadAverages() {
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
String os = osBean.getName();

if (os.equals("Linux")) {
File loadavg = new File("/proc/loadavg");

if (loadavg.exists() && loadavg.isFile() && loadavg.canRead()) {
try (Scanner scanner = new Scanner(loadavg)) {
if (!scanner.hasNext()) {
return defaultLoadAverages(osBean);
}

String line = scanner.nextLine();
String[] values = line.split(" ", 3);

return new Number[]{
Double.parseDouble(values[0]),
Double.parseDouble(values[1]),
Double.parseDouble(values[2])
};

} catch (Exception e) {
return defaultLoadAverages(osBean);
}
} else {
return defaultLoadAverages(osBean);
}

} else {
return defaultLoadAverages(osBean);
}
}

static Number[] defaultLoadAverages(OperatingSystemMXBean osBean) {
return new Number[] { osBean.getSystemLoadAverage(), -1, -1 };
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Load load = (Load) o;

if (one != null ? !one.equals(load.one) : load.one != null) return false;
if (five != null ? !five.equals(load.five) : load.five != null) return false;
return !(fifteen != null ? !fifteen.equals(load.fifteen) : load.fifteen != null);

}

@Override
public int hashCode() {
int result = one != null ? one.hashCode() : 0;
result = 31 * result + (five != null ? five.hashCode() : 0);
result = 31 * result + (fifteen != null ? fifteen.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "Load{" +
"one=" + one +
", five=" + five +
", fifteen=" + fifteen +
'}';
}
}
72 changes: 72 additions & 0 deletions src/main/java/io/honeybadger/reporter/dto/Memory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package io.honeybadger.reporter.dto;

import java.io.Serializable;

/**
* Class containing the current state of memory on the running JVM.
*
* @author <a href="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/dekobon">Elijah Zupancic</a>
* @since 1.0.11
*/
public class Memory implements Serializable {
private static final long serialVersionUID = -8799953046383217102L;

public final Number total;
public final Number free;
public final Number buffers;
public final Number cached;
public final Number free_total;

public Memory() {
final Runtime r = Runtime.getRuntime();
this.total = r.totalMemory();
this.free = r.freeMemory();
this.buffers = -1;
this.cached = -1;
this.free_total = r.maxMemory() - (r.totalMemory() - r.freeMemory());
}

public Memory(Number total, Number free, Number buffers, Number cached, Number free_total) {
this.total = total;
this.free = free;
this.buffers = buffers;
this.cached = cached;
this.free_total = free_total;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Memory memory = (Memory) o;

if (total != null ? !total.equals(memory.total) : memory.total != null) return false;
if (free != null ? !free.equals(memory.free) : memory.free != null) return false;
if (buffers != null ? !buffers.equals(memory.buffers) : memory.buffers != null) return false;
if (cached != null ? !cached.equals(memory.cached) : memory.cached != null) return false;
return !(free_total != null ? !free_total.equals(memory.free_total) : memory.free_total != null);

}

@Override
public int hashCode() {
int result = total != null ? total.hashCode() : 0;
result = 31 * result + (free != null ? free.hashCode() : 0);
result = 31 * result + (buffers != null ? buffers.hashCode() : 0);
result = 31 * result + (cached != null ? cached.hashCode() : 0);
result = 31 * result + (free_total != null ? free_total.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "Memory{" +
"total=" + total +
", free=" + free +
", buffers=" + buffers +
", cached=" + cached +
", free_total=" + free_total +
'}';
}
}
65 changes: 63 additions & 2 deletions src/main/java/io/honeybadger/reporter/dto/ServerDetails.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
* Server details at the time an error occurred.
Expand All @@ -21,17 +26,27 @@ public class ServerDetails implements Serializable {
public final String environment_name;
public final String hostname;
public final String project_root;
public final Integer pid;
public final String time;
public final Stats stats;

public ServerDetails() {
this.environment_name = environment();
this.hostname = hostname();
this.project_root = projectRoot();
this.pid = pid();
this.time = time();
this.stats = new Stats();
}

public ServerDetails(String environment_name, String hostname, String project_root) {
public ServerDetails(String environment_name, String hostname, String project_root,
Integer pid, String time, Stats stats) {
this.environment_name = environment_name;
this.hostname = hostname;
this.project_root = project_root;
this.pid = pid;
this.time = time;
this.stats = stats;
}

/**
Expand Down Expand Up @@ -100,6 +115,39 @@ protected static String projectRoot() {
}
}

/**
* Finds the process id for the running JVM.
*
* @see <a href="https://stackoverflow.com/questions/35842/how-can-a-java-program-get-its-own-process-id/7690178#7690178>refrenced this implementation</a>
* @return process id or null if not found
*/
protected static Integer pid() {
// something like '<pid>@<hostname>', at least in SUN / Oracle JVMs
final String jvmName = ManagementFactory.getRuntimeMXBean().getName();
final int index = jvmName.indexOf('@');

if (index < 1) {
// part before '@' empty (index = 0) / '@' not found (index = -1)
return null;
}

try {
return Integer.parseInt(jvmName.substring(0, index));
} catch (NumberFormatException e) {
return null;
}
}

/**
* @return The current time in ISO-8601 format.
*/
public static String time() {
TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
formatter.setTimeZone(tz);
return formatter.format(new Date());
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -110,7 +158,8 @@ public boolean equals(Object o) {
if (environment_name != null ? !environment_name.equals(that.environment_name) : that.environment_name != null)
return false;
if (hostname != null ? !hostname.equals(that.hostname) : that.hostname != null) return false;
return !(project_root != null ? !project_root.equals(that.project_root) : that.project_root != null);
if (project_root != null ? !project_root.equals(that.project_root) : that.project_root != null) return false;
return !(pid != null ? !pid.equals(that.pid) : that.pid != null);

}

Expand All @@ -119,6 +168,18 @@ public int hashCode() {
int result = environment_name != null ? environment_name.hashCode() : 0;
result = 31 * result + (hostname != null ? hostname.hashCode() : 0);
result = 31 * result + (project_root != null ? project_root.hashCode() : 0);
result = 31 * result + (pid != null ? pid.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "ServerDetails{" +
"environment_name='" + environment_name + '\'' +
", hostname='" + hostname + '\'' +
", project_root='" + project_root + '\'' +
", pid=" + pid +
", stats=" + stats +
'}';
}
}
53 changes: 53 additions & 0 deletions src/main/java/io/honeybadger/reporter/dto/Stats.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.honeybadger.reporter.dto;

import java.io.Serializable;

/**
* Class containing the statistics about the running JVM.
*
* @author <a href="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/dekobon">Elijah Zupancic</a>
* @since 1.0.11
*/
public class Stats implements Serializable {
private static final long serialVersionUID = 4563609532018909058L;

public final Memory mem;
public final Load load;

public Stats() {
this.mem = new Memory();
this.load = new Load();
}

public Stats(Memory mem, Load load) {
this.mem = mem;
this.load = load;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Stats stats = (Stats) o;

if (mem != null ? !mem.equals(stats.mem) : stats.mem != null) return false;
return !(load != null ? !load.equals(stats.load) : stats.load != null);

}

@Override
public int hashCode() {
int result = mem != null ? mem.hashCode() : 0;
result = 31 * result + (load != null ? load.hashCode() : 0);
return result;
}

@Override
public String toString() {
return "Stats{" +
"mem=" + mem +
", load=" + load +
'}';
}
}

0 comments on commit 47126ff

Please sign in to comment.