Server Health Analysis #391

This commit is contained in:
Rsl1122 2017-11-25 13:25:08 +02:00
parent 3222465f13
commit d52de52cf0
5 changed files with 381 additions and 101 deletions

View File

@ -41,10 +41,13 @@ public class AnalysisData extends RawData {
private long refreshDate; private long refreshDate;
private String pluginsTabLayout; private String pluginsTabLayout;
private Map<String, Serializable> additionalDataReplaceMap; private Map<String, Serializable> additionalDataReplaceMap;
@Deprecated
private String playersTable; private Map<String, Long> analyzedValues;
private Set<StickyData> stickyMonthData;
public AnalysisData() { public AnalysisData() {
analyzedValues = new HashMap<>();
stickyMonthData = new HashSet<>();
} }
public void setPluginsTabLayout(String pluginsTabLayout) { public void setPluginsTabLayout(String pluginsTabLayout) {
@ -55,10 +58,6 @@ public class AnalysisData extends RawData {
this.additionalDataReplaceMap = additionalDataReplaceMap; this.additionalDataReplaceMap = additionalDataReplaceMap;
} }
public void setPlayersTable(String playersTable) {
this.playersTable = playersTable;
}
private void addConstants() { private void addConstants() {
addValue("version", MiscUtils.getIPlan().getVersion()); addValue("version", MiscUtils.getIPlan().getVersion());
addValue("worldPieColors", Settings.THEME_GRAPH_WORLD_PIE.toString()); addValue("worldPieColors", Settings.THEME_GRAPH_WORLD_PIE.toString());
@ -95,13 +94,18 @@ public class AnalysisData extends RawData {
long weekAgo = now - TimeAmount.WEEK.ms(); long weekAgo = now - TimeAmount.WEEK.ms();
long monthAgo = now - TimeAmount.MONTH.ms(); long monthAgo = now - TimeAmount.MONTH.ms();
got("now", now);
got("dayAgo", dayAgo);
got("weekAgo", weekAgo);
got("monthAgo", monthAgo);
Map<UUID, List<Session>> sessions = profile.getSessions(); Map<UUID, List<Session>> sessions = profile.getSessions();
List<Session> allSessions = profile.getAllSessions(); List<Session> allSessions = profile.getAllSessions();
allSessions.sort(new SessionStartComparator()); allSessions.sort(new SessionStartComparator());
List<PlayerProfile> players = profile.getPlayers(); List<PlayerProfile> players = profile.getPlayers();
List<PlayerProfile> ops = profile.getOps().collect(Collectors.toList()); List<PlayerProfile> ops = profile.getOps().collect(Collectors.toList());
int playersTotal = players.size(); long playersTotal = got("playersTotal", players.size());
List<TPS> tpsData = profile.getTPSData(0, now).collect(Collectors.toList()); List<TPS> tpsData = profile.getTPSData(0, now).collect(Collectors.toList());
List<TPS> tpsDataDay = profile.getTPSData(dayAgo, now).collect(Collectors.toList()); List<TPS> tpsDataDay = profile.getTPSData(dayAgo, now).collect(Collectors.toList());
@ -121,16 +125,224 @@ public class AnalysisData extends RawData {
addValue("ops", ops.size()); addValue("ops", ops.size());
addValue("playersTotal", playersTotal); addValue("playersTotal", playersTotal);
healthTab(now, monthAgo, players, tpsDataMonth);
long totalPlaytime = profile.getTotalPlaytime();
addValue("playtimeTotal", playersTotal != 0 ? FormatUtils.formatTimeAmount(totalPlaytime) : "No Players");
addValue("playtimeAverage", playersTotal != 0 ? FormatUtils.formatTimeAmount(MathUtils.averageLong(totalPlaytime, playersTotal)) : "-");
}
private void healthTab(long now, long monthAgo, List<PlayerProfile> players, List<TPS> tpsDataMonth) {
double serverHealth = 100.0;
List<String> healthNotes = new ArrayList<>();
TreeMap<Long, Map<String, Set<UUID>>> activityData = new TreeMap<>();
for (PlayerProfile player : players) {
for (long date = now; date >= now - TimeAmount.MONTH.ms() * 2L; date -= TimeAmount.WEEK.ms() * 2L) {
double activityIndex = player.getActivityIndex(date);
String index = FormatUtils.readableActivityIndex(activityIndex)[1];
Map<String, Set<UUID>> map = activityData.getOrDefault(date, new HashMap<>());
Set<UUID> uuids = map.getOrDefault(index, new HashSet<>());
uuids.add(player.getUuid());
map.put(index, uuids);
activityData.put(date, map);
}
}
long fourWeeksAgo = now - TimeAmount.WEEK.ms() * 4L;
Map<String, Set<UUID>> activityNow = activityData.get(now);
Map<String, Set<UUID>> activityFourWAgo = activityData.get(fourWeeksAgo);
Set<UUID> veryActiveNow = activityNow.getOrDefault("Very Active", new HashSet<>());
Set<UUID> activeNow = activityNow.getOrDefault("Active", new HashSet<>());
Set<UUID> regularNow = activityNow.getOrDefault("Regular", new HashSet<>());
Set<UUID> veryActiveFWAG = activityFourWAgo.getOrDefault("Very Active", new HashSet<>());
Set<UUID> activeFWAG = activityFourWAgo.getOrDefault("Active", new HashSet<>());
Set<UUID> regularFWAG = activityFourWAgo.getOrDefault("Regular", new HashSet<>());
Set<UUID> regularRemainCompareSet = new HashSet<>(regularFWAG);
regularRemainCompareSet.addAll(activeFWAG);
regularRemainCompareSet.addAll(veryActiveFWAG);
int activeFWAGNum = regularRemainCompareSet.size();
regularRemainCompareSet.removeAll(regularNow);
regularRemainCompareSet.removeAll(activeNow);
regularRemainCompareSet.removeAll(veryActiveNow);
int notRegularAnymore = regularRemainCompareSet.size();
int remain = activeFWAGNum - notRegularAnymore;
double percRemain = remain * 100.0 / activeFWAGNum;
Set<UUID> regularNewCompareSet = new HashSet<>(regularNow);
regularNewCompareSet.addAll(activeNow);
regularNewCompareSet.addAll(veryActiveNow);
regularNewCompareSet.removeAll(regularFWAG);
regularNewCompareSet.removeAll(activeFWAG);
regularNewCompareSet.removeAll(veryActiveFWAG);
int newActive = regularNewCompareSet.size();
int change = newActive - notRegularAnymore;
String remainNote = "";
if (activeFWAGNum != 0) {
remainNote = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
if (percRemain > 50) {
remainNote += Html.GREEN_THUMB.parse();
} else if (percRemain > 20) {
remainNote += Html.YELLOW_FLAG.parse();
} else {
remainNote += Html.RED_WARN.parse();
serverHealth -= 2.5;
}
remainNote += " " + FormatUtils.cutDecimals(percRemain) + "% of regular players have remained active (" + remain + "/" + activeFWAGNum + ")";
}
if (change > 0) {
healthNotes.add(
"<p>" + Html.GREEN_THUMB.parse() + " Number of regular players has increased (+" + change + ")<br>" +
remainNote + "</p>");
} else if (change == 0) {
healthNotes.add(
"<p>" + Html.GREEN_THUMB.parse() + " Number of regular players has stayed the same (+" + change + ")<br>" +
remainNote + "</p>");
} else if (change > -20) {
healthNotes.add(
"<p>" + Html.YELLOW_FLAG.parse() + " Number of regular players has decreased (" + change + ")<br>" +
remainNote + "</p>");
serverHealth -= 5;
} else {
healthNotes.add(
"<p>" + Html.RED_WARN.parse() + " Number of regular players has decreased (" + change + ")<br>" +
remainNote + "</p>");
serverHealth -= 10;
}
double avgOnlineOnRegister = MathUtils.averageInt(stickyMonthData.stream().map(StickyData::getOnlineOnJoin));
if (avgOnlineOnRegister >= 1) {
healthNotes.add("<p>" + Html.GREEN_THUMB.parse() + " New Players have players to play with when they join ("
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)</p>");
} else {
healthNotes.add("<p>" + Html.YELLOW_FLAG.parse() + " New Players may not have players to play with when they join ("
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)</p>");
serverHealth -= 5;
}
long newM = value("newM");
long stuckPerM = value("stuckPerM");
if (newM != 0) {
double stuckPerc = MathUtils.averageDouble(stuckPerM, newM) * 100;
if (stuckPerc >= 25) {
healthNotes.add("<p>" + Html.GREEN_THUMB.parse() + " " + FormatUtils.cutDecimals(stuckPerc)
+ "% of new players have stuck around (" + stuckPerM + "/" + newM + ")</p>");
} else {
healthNotes.add("<p>" + Html.YELLOW_FLAG.parse() + " " + FormatUtils.cutDecimals(stuckPerc)
+ "% of new players have stuck around (" + stuckPerM + "/" + newM + ")</p>");
}
}
List<PlayerProfile> currentActivePlayers = players.stream()
.filter(player -> player.getActivityIndex(now) >= 1.75)
.collect(Collectors.toList());
long twoWeeksAgo = now - TimeAmount.WEEK.ms() * 2L;
long totalFourToTwoWeeks = 0;
long totalLastTwoWeeks = 0;
for (PlayerProfile activePlayer : currentActivePlayers) {
totalFourToTwoWeeks += activePlayer.getPlaytime(monthAgo, twoWeeksAgo);
totalLastTwoWeeks += activePlayer.getPlaytime(twoWeeksAgo, now);
}
int currentlyActive = currentActivePlayers.size();
if (currentlyActive != 0) {
long avgFourToTwoWeeks = MathUtils.averageLong(totalFourToTwoWeeks, currentlyActive);
long avgLastTwoWeeks = MathUtils.averageLong(totalLastTwoWeeks, currentlyActive);
String avgLastTwoWeeksString = FormatUtils.formatTimeAmount(avgLastTwoWeeks);
String avgFourToTwoWeeksString = FormatUtils.formatTimeAmount(avgFourToTwoWeeks);
if (avgFourToTwoWeeks >= avgLastTwoWeeks) {
healthNotes.add("<p>" + Html.GREEN_THUMB.parse() + " Active players to have things to do ("
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
+ ")</p>");
} else if (avgFourToTwoWeeks - avgLastTwoWeeks > TimeAmount.HOUR.ms() * 2L) {
healthNotes.add("<p>" + Html.RED_WARN.parse() + " Active players might to be running out of things to do (Played "
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
+ ", last two weeks vs weeks 2-4)</p>");
serverHealth -= 5;
} else {
healthNotes.add("<p>" + Html.YELLOW_FLAG.parse() + " Active players might to be running out of things to do ("
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
+ ")</p>");
}
}
long serverDownTime = ServerProfile.serverDownTime(tpsDataMonth);
long serverIdleTime = ServerProfile.serverIdleTime(tpsDataMonth);
double aboveThreshold = ServerProfile.aboveLowThreshold(tpsDataMonth);
long tpsSpikeMonth = value("tpsSpikeMonth");
String avgLowThresholdString = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
if (aboveThreshold >= 0.96) {
avgLowThresholdString += Html.GREEN_THUMB.parse();
} else if (aboveThreshold >= 0.9) {
avgLowThresholdString += Html.YELLOW_FLAG.parse();
serverHealth *= 0.9;
} else {
avgLowThresholdString += Html.RED_WARN.parse();
serverHealth *= 0.6;
}
avgLowThresholdString += " Average TPS was above Low Threshold "
+ FormatUtils.cutDecimals(aboveThreshold * 100.0) + "% of the time";
if (tpsSpikeMonth <= 5) {
healthNotes.add("<p>" + Html.GREEN_THUMB.parse()
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
" " + tpsSpikeMonth + " times<br>" +
avgLowThresholdString + "</p>");
} else if (tpsSpikeMonth <= 25) {
healthNotes.add("<p>" + Html.YELLOW_FLAG.parse()
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
" " + tpsSpikeMonth + " times<br>" +
avgLowThresholdString + "</p>");
serverHealth *= 0.95;
} else {
healthNotes.add("<p>" + Html.RED_WARN.parse()
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
" " + tpsSpikeMonth + " times<br>" +
avgLowThresholdString + "</p>");
serverHealth *= 0.8;
}
if (serverDownTime <= TimeAmount.DAY.ms()) {
healthNotes.add("<p>" + Html.GREEN_THUMB.parse() + " Total Server downtime (No Data) was "
+ FormatUtils.formatTimeAmount(serverDownTime) + "</p>");
} else if (serverDownTime <= TimeAmount.WEEK.ms()) {
healthNotes.add("<p>" + Html.YELLOW_FLAG.parse() + " Total Server downtime (No Data) was "
+ FormatUtils.formatTimeAmount(serverDownTime) + "</p>");
serverHealth *= 0.6;
} else {
healthNotes.add("<p>" + Html.RED_WARN.parse() + " Total Server downtime (No Data) was "
+ FormatUtils.formatTimeAmount(serverDownTime) + "</p>");
serverHealth *= 0.3;
}
healthNotes.add("<p>" + Html.FA_COLORED_ICON.parse("red", "life-ring") + " Server was idle (No Players) "
+ FormatUtils.formatTimeAmount(serverIdleTime) + "</p>");
StringBuilder healthNoteBuilder = new StringBuilder();
for (String healthNote : healthNotes) {
healthNoteBuilder.append(healthNote);
}
addValue("healthNotes", healthNoteBuilder.toString());
addValue("healthIndex", serverHealth);
// TODO Rewrite Activity Pie // TODO Rewrite Activity Pie
addValue("playersActive", 0); addValue("playersActive", 0);
addValue("active", 0); addValue("active", 0);
addValue("inactive", 0); addValue("inactive", 0);
addValue("joinLeaver", 0); addValue("joinLeaver", 0);
addValue("banned", 0); addValue("banned", 0);
long totalPlaytime = profile.getTotalPlaytime();
addValue("playtimeTotal", playersTotal != 0 ? FormatUtils.formatTimeAmount(totalPlaytime) : "No Players");
addValue("playtimeAverage", playersTotal != 0 ? FormatUtils.formatTimeAmount(MathUtils.averageLong(totalPlaytime, playersTotal)) : "-");
} }
private void commandUsage(Map<String, Integer> commandUsage) { private void commandUsage(Map<String, Integer> commandUsage) {
@ -144,10 +356,10 @@ public class AnalysisData extends RawData {
} }
private void onlineActivityNumbers(ServerProfile profile, Map<UUID, List<Session>> sessions, List<PlayerProfile> players) { private void onlineActivityNumbers(ServerProfile profile, Map<UUID, List<Session>> sessions, List<PlayerProfile> players) {
long now = MiscUtils.getTime(); long now = value("now");
long dayAgo = now - TimeAmount.DAY.ms(); long dayAgo = value("dayAgo");
long weekAgo = now - TimeAmount.WEEK.ms(); long weekAgo = value("weekAgo");
long monthAgo = now - TimeAmount.MONTH.ms(); long monthAgo = value("monthAgo");
List<PlayerProfile> newDay = profile.getPlayersWhoRegistered(dayAgo, now).collect(Collectors.toList()); List<PlayerProfile> newDay = profile.getPlayersWhoRegistered(dayAgo, now).collect(Collectors.toList());
List<PlayerProfile> newWeek = profile.getPlayersWhoRegistered(weekAgo, now).collect(Collectors.toList()); List<PlayerProfile> newWeek = profile.getPlayersWhoRegistered(weekAgo, now).collect(Collectors.toList());
@ -159,10 +371,10 @@ public class AnalysisData extends RawData {
int uniqD = uniqueDay.size(); int uniqD = uniqueDay.size();
int uniqW = uniqueWeek.size(); int uniqW = uniqueWeek.size();
int uniqM = uniqueMonth.size(); int uniqM = uniqueMonth.size();
int newD = newDay.size(); long newD = got("newD", newDay.size());
int newW = newWeek.size(); long newW = got("newW", newWeek.size());
int newM = newMonth.size(); long newM = got("newM", newMonth.size());
int playersTotal = players.size(); long playersTotal = value("playersTotal");
addValue("playersDay", uniqD); addValue("playersDay", uniqD);
addValue("playersWeek", uniqW); addValue("playersWeek", uniqW);
@ -180,12 +392,15 @@ public class AnalysisData extends RawData {
addValue("playersNewAverageWeek", AnalysisUtils.getNewUsersPerDay(toRegistered(newWeek), -1, newW)); addValue("playersNewAverageWeek", AnalysisUtils.getNewUsersPerDay(toRegistered(newWeek), -1, newW));
addValue("playersNewAverageMonth", AnalysisUtils.getNewUsersPerDay(toRegistered(newMonth), -1, newM)); addValue("playersNewAverageMonth", AnalysisUtils.getNewUsersPerDay(toRegistered(newMonth), -1, newM));
stickiness(now, weekAgo, monthAgo, newDay, newWeek, newMonth, newD, newW, newM); stickiness(now, weekAgo, monthAgo, newDay, newWeek, newMonth);
} }
private void stickiness(long now, long weekAgo, long monthAgo, private void stickiness(long now, long weekAgo, long monthAgo,
List<PlayerProfile> newDay, List<PlayerProfile> newWeek, List<PlayerProfile> newMonth, List<PlayerProfile> newDay, List<PlayerProfile> newWeek, List<PlayerProfile> newMonth) {
int newD, int newW, int newM) { long newD = value("newD");
long newW = value("newW");
long newM = value("newM");
long fourDaysAgo = now - TimeAmount.DAY.ms() * 4L; long fourDaysAgo = now - TimeAmount.DAY.ms() * 4L;
long twoWeeksAgo = now - TimeAmount.WEEK.ms() * 2L; long twoWeeksAgo = now - TimeAmount.WEEK.ms() * 2L;
@ -198,6 +413,8 @@ public class AnalysisData extends RawData {
int stuckPerM = playersStuckPerMonth.size(); int stuckPerM = playersStuckPerMonth.size();
int stuckPerW = playersStuckPerWeek.size(); int stuckPerW = playersStuckPerWeek.size();
got("stuckPerM", stuckPerM);
got("stuckPerW", stuckPerW);
addValue("playersStuckMonth", stuckPerM); addValue("playersStuckMonth", stuckPerM);
addValue("playersStuckWeek", stuckPerW); addValue("playersStuckWeek", stuckPerW);
@ -206,7 +423,7 @@ public class AnalysisData extends RawData {
if (newD != 0) { if (newD != 0) {
// New Players // New Players
Set<StickyData> stickyM = newMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet()); stickyMonthData = newMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
Set<StickyData> stickyW = playersStuckPerMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet()); Set<StickyData> stickyW = playersStuckPerMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
// New Players who stayed // New Players who stayed
Set<StickyData> stickyStuckM = newMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet()); Set<StickyData> stickyStuckM = newMonth.stream().map(StickyData::new).distinct().collect(Collectors.toSet());
@ -218,7 +435,7 @@ public class AnalysisData extends RawData {
Set<StickyData> similarM = new HashSet<>(); Set<StickyData> similarM = new HashSet<>();
Set<StickyData> similarW = new HashSet<>(); Set<StickyData> similarW = new HashSet<>();
for (StickyData stickyData : stickyM) { for (StickyData stickyData : stickyMonthData) {
if (stickyData.distance(data) < 2.5) { if (stickyData.distance(data) < 2.5) {
similarM.add(stickyData); similarM.add(stickyData);
} }
@ -302,9 +519,12 @@ public class AnalysisData extends RawData {
} }
private void performanceTab(List<TPS> tpsData, List<TPS> tpsDataDay, List<TPS> tpsDataWeek, List<TPS> tpsDataMonth) { private void performanceTab(List<TPS> tpsData, List<TPS> tpsDataDay, List<TPS> tpsDataWeek, List<TPS> tpsDataMonth) {
addValue("tpsSpikeMonth", ServerProfile.getLowSpikeCount(tpsDataMonth)); got("tpsSpikeMonth", ServerProfile.getLowSpikeCount(tpsDataMonth));
addValue("tpsSpikeWeek", ServerProfile.getLowSpikeCount(tpsDataWeek)); got("tpsSpikeWeek", ServerProfile.getLowSpikeCount(tpsDataWeek));
addValue("tpsSpikeDay", ServerProfile.getLowSpikeCount(tpsDataDay)); got("tpsSpikeDay", ServerProfile.getLowSpikeCount(tpsDataDay));
addValue("tpsSpikeMonth", value("tpsSpikeMonth"));
addValue("tpsSpikeWeek", value("tpsSpikeWeek"));
addValue("tpsSpikeDay", value("tpsSpikeDay"));
addValue("playersOnlineSeries", PlayerActivityGraphCreator.buildSeriesDataString(tpsData)); addValue("playersOnlineSeries", PlayerActivityGraphCreator.buildSeriesDataString(tpsData));
addValue("tpsSeries", TPSGraphCreator.buildSeriesDataString(tpsData)); addValue("tpsSeries", TPSGraphCreator.buildSeriesDataString(tpsData));
@ -337,6 +557,15 @@ public class AnalysisData extends RawData {
addValue("chunkAverageWeek", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataWeek.stream().map(TPS::getChunksLoaded).filter(i -> i != 0)))); addValue("chunkAverageWeek", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataWeek.stream().map(TPS::getChunksLoaded).filter(i -> i != 0))));
addValue("chunkAverageDay", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataDay.stream().map(TPS::getChunksLoaded).filter(i -> i != 0)))); addValue("chunkAverageDay", FormatUtils.cutDecimals(MathUtils.averageInt(tpsDataDay.stream().map(TPS::getChunksLoaded).filter(i -> i != 0))));
} }
private long got(String key, long v) {
analyzedValues.put(key, v);
return v;
}
private long value(String key) {
return analyzedValues.getOrDefault(key, 0L);
}
} }
class StickyData { class StickyData {
@ -368,6 +597,12 @@ class StickyData {
} }
} }
} }
if (messagesSent == null) {
messagesSent = 0;
}
if (onlineOnJoin == null) {
onlineOnJoin = 0;
}
} }
public double distance(StickyData data) { public double distance(StickyData data) {
@ -393,4 +628,8 @@ class StickyData {
public int hashCode() { public int hashCode() {
return Objects.hashCode(activityIndex, messagesSent, onlineOnJoin); return Objects.hashCode(activityIndex, messagesSent, onlineOnJoin);
} }
public int getOnlineOnJoin() {
return onlineOnJoin;
}
} }

View File

@ -340,7 +340,7 @@ public class ServerProfile {
for (TPS tps : tpsData) { for (TPS tps : tpsData) {
long date = tps.getDate(); long date = tps.getDate();
int players = tps.getPlayers(); int players = tps.getPlayers();
if (lastDate != -1) { if (lastDate == -1) {
lastDate = date; lastDate = date;
lastPlayers = players; lastPlayers = players;
continue; continue;
@ -357,4 +357,21 @@ public class ServerProfile {
return idleTime; return idleTime;
} }
public static double aboveLowThreshold(List<TPS> tpsData) {
if (tpsData.isEmpty()) {
return 1;
}
int threshold = Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber();
long count = 0;
for (TPS tps : tpsData) {
if (tps.getTicksPerSecond() >= threshold) {
count++;
}
}
return count / tpsData.size();
}
} }

View File

@ -30,6 +30,9 @@ public enum Html {
// //
FONT_AWESOME_ICON("<i class=\"fa fa-${0}\"></i>"), FONT_AWESOME_ICON("<i class=\"fa fa-${0}\"></i>"),
FA_COLORED_ICON("<i class=\"col-${0} fa fa-${1}\"></i>"), FA_COLORED_ICON("<i class=\"col-${0} fa fa-${1}\"></i>"),
GREEN_THUMB("<i class=\"fa fa-thumbs-up g\"></i>"),
YELLOW_FLAG("<i class=\"fa fa-flag o\"></i>"),
RED_WARN("<i class=\"fa fa-exclamation-circle r\"></i>"),
SPAN("${0}</span>"), SPAN("${0}</span>"),
BUTTON("<a class=\"button\" href=\"${0}\">${1}</a>"), BUTTON("<a class=\"button\" href=\"${0}\">${1}</a>"),
BUTTON_CLASS("class=\"button\""), BUTTON_CLASS("class=\"button\""),

View File

@ -1,83 +1,101 @@
function healthGauge(id, healthData) { function healthGauge(id, healthData) {
var gaugeOptions = { var gaugeOptions = {
chart: { chart: {
type: 'solidgauge' type: 'solidgauge'
},
title: null,
pane: {
center: ['50%', '85%'],
size: '140%',
startAngle: -90,
endAngle: 90,
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
[0.1, '#DF5353'], // red
[0.5, '#DDDF0D'], // yellow
[0.9, '#55BF3B'] // green
],
lineWidth: 0,
minorTickInterval: null,
tickAmount: 2,
title: {
y: -70
}, },
labels: {
y: 16
}
},
plotOptions: { title: null,
solidgauge: {
dataLabels: { pane: {
y: 5, center: ['50%', '85%'],
borderWidth: 0, size: '140%',
useHTML: true startAngle: -90,
endAngle: 90,
background: {
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#EEE',
innerRadius: '60%',
outerRadius: '100%',
shape: 'arc'
}
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
stops: [
[0.1, '#DF5353'], // red
[0.5, '#DDDF0D'], // yellow
[0.9, '#55BF3B'] // green
],
lineWidth: 0,
minorTickInterval: null,
tickAmount: 2,
title: {
y: -70
},
labels: {
y: 16
}
},
plotOptions: {
solidgauge: {
dataLabels: {
y: 5,
borderWidth: 0,
useHTML: true
}
} }
} }
} };
};
var chartSpeed = Highcharts.chart(id, Highcharts.merge(gaugeOptions, { var chartSpeed = Highcharts.chart(id, Highcharts.merge(gaugeOptions, {
yAxis: { yAxis: {
min: 0, min: 0,
max: 100, max: 100,
title: { title: {
text: 'Server Health' text: 'Server Health'
},
visible: false
}, },
visible: false
},
credits: { credits: {
enabled: false enabled: false
}, },
series: [{ series: [{
name: 'health', name: 'health',
data: healthData, data: healthData,
dataLabels: { dataLabels: {
formatter: function() { formatter: function () {
return '<div style="text-align:center"><span style="font-size:25px;color:' + return '<div style="text-align:center"><span style="font-size:25px;color:' +
((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">'+(this.y).toFixed(2)+'</span><br/>' + ((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">' + (this.y).toFixed(2) + '</span><br/>' +
'<span style="font-size:12px;color:silver">Very Healthy</span></div>'; '<span style="font-size:12px;color:silver">' + getLabel(this.y) + '</span></div>';
} }
} }
}] }]
})); }));
}
function getLabel(index) {
if (index >= 80) {
return 'Very Healthy';
}
if (index >= 60) {
return 'Healthy';
}
if (index >= 50) {
return 'Good';
}
if (index >= 30) {
return 'OK';
}
if (index >= 0) {
return 'Poor';
}
} }

View File

@ -584,12 +584,12 @@
<div class="header"> <div class="header">
<div class="row clearfix"> <div class="row clearfix">
<div class="col-xs-12 col-sm-6"> <div class="col-xs-12 col-sm-6">
<h2><i class="col-red fa fa-life-ring"></i> Last 14 Days</h2> <h2><i class="col-red fa fa-life-ring"></i> Last 30 Days</h2>
</div> </div>
</div> </div>
</div> </div>
<div class="body bg-white"> <div class="body bg-white">
<p>${healthNotes} </p> ${healthNotes}
</div> </div>
</div> </div>
</div> </div>
@ -934,6 +934,8 @@
<script src="https://code.highcharts.com/maps/modules/map.js"></script> <script src="https://code.highcharts.com/maps/modules/map.js"></script>
<script src="https://code.highcharts.com/mapdata/custom/world.js"></script> <script src="https://code.highcharts.com/mapdata/custom/world.js"></script>
<script src="https://code.highcharts.com/modules/drilldown.js"></script> <script src="https://code.highcharts.com/modules/drilldown.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
<script src="https://code.highcharts.com/modules/no-data-to-display.js"></script> <script src="https://code.highcharts.com/modules/no-data-to-display.js"></script>
<!-- Font Awesome --> <!-- Font Awesome -->
@ -1103,6 +1105,7 @@
worldChart('worldGraph', entitySeries, chunkSeries, playersOnlineSeries); worldChart('worldGraph', entitySeries, chunkSeries, playersOnlineSeries);
worldMap('worldMap', '#EEFFEE', '#267f00', mapSeries); worldMap('worldMap', '#EEFFEE', '#267f00', mapSeries);
punchCard('punchCard', punchcardSeries); punchCard('punchCard', punchcardSeries);
healthGauge('healthGauge', [${healthIndex}]);
${sessionTabGraphViewFunctions} ${sessionTabGraphViewFunctions}
/**/ /**/