JsonObject export() { return JSONUtil.objectBuilder() .add("s", this.startTime) .add("e", this.endTime) .add("tk", this.totalTicks) .add("tm", this.totalTime) .add("w", this.worlds) .add( "h", JSONUtil.mapArray( this.entries, (entry) -> entry.data.count == 0 ? null : entry.export())) .add("mp", JSONUtil.mapArray(this.minuteReports, MinuteReport::export)) .build(); }
public JsonArray export() { return JSONUtil.arrayOf( this.time, Math.round(this.tps * 100D) / 100D, Math.round(this.pingRecord.avg * 100D) / 100D, this.fst.export(), JSONUtil.arrayOf( this.ticksRecord.timed, this.ticksRecord.player, this.ticksRecord.entity, this.ticksRecord.activatedEntity, this.ticksRecord.tileEntity), this.usedMemory, this.freeMemory, this.loadAvg); }
private static JsonElement serializeConfigNode(ConfigurationNode node) { if (node.hasMapChildren()) { JsonObject object = new JsonObject(); for (Entry<Object, ? extends ConfigurationNode> entry : node.getChildrenMap().entrySet()) { String fullPath = CONFIG_PATH_JOINER.join(entry.getValue().getPath()); if (fullPath.equals("sponge.sql") || TimingsManager.hiddenConfigs.contains(fullPath)) { continue; } object.add(entry.getKey().toString(), serializeConfigNode(entry.getValue())); } return object; } if (node.hasListChildren()) { JsonArray array = new JsonArray(); for (ConfigurationNode child : node.getChildrenList()) { array.add(serializeConfigNode(child)); } return array; } return JSONUtil.toJsonElement(node.getValue()); }
/** * Builds an XML report of the timings to be uploaded for parsing. * * @param sender Who to report to */ static void reportTimings(CommandSource sender) { Platform platform = SpongeImpl.getGame().getPlatform(); JsonObjectBuilder builder = JSONUtil.objectBuilder() // Get some basic system details about the server .add( "version", platform .getImplementation() .getVersion() .orElse(platform.getMinecraftVersion().getName() + "-DEV")) .add("maxplayers", SpongeImpl.getGame().getServer().getMaxPlayers()) .add("start", TimingsManager.timingStart / 1000) .add("end", System.currentTimeMillis() / 1000) .add("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000); if (!TimingsManager.privacy) { builder .add("server", getServerName()) .add("motd", SpongeImpl.getGame().getServer().getMotd().toPlain()) .add("online-mode", SpongeImpl.getGame().getServer().getOnlineMode()) .add("icon", MinecraftServer.getServer().getServerStatusResponse().getFavicon()); } final Runtime runtime = Runtime.getRuntime(); RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); builder.add( "system", JSONUtil.objectBuilder() .add("timingcost", getCost()) .add("name", System.getProperty("os.name")) .add("version", System.getProperty("os.version")) .add("jvmversion", System.getProperty("java.version")) .add("arch", System.getProperty("os.arch")) .add("maxmem", runtime.maxMemory()) .add("cpu", runtime.availableProcessors()) .add("runtime", ManagementFactory.getRuntimeMXBean().getUptime()) .add("flags", RUNTIME_FLAG_JOINER.join(runtimeBean.getInputArguments())) .add( "gc", JSONUtil.mapArrayToObject( ManagementFactory.getGarbageCollectorMXBeans(), (input) -> { return JSONUtil.singleObjectPair( input.getName(), JSONUtil.arrayOf(input.getCollectionCount(), input.getCollectionTime())); }))); Set<BlockType> blockTypeSet = Sets.newHashSet(); Set<EntityType> entityTypeSet = Sets.newHashSet(); int size = HISTORY.size(); TimingHistory[] history = new TimingHistory[size + 1]; int i = 0; for (TimingHistory timingHistory : HISTORY) { blockTypeSet.addAll(timingHistory.blockTypeSet); entityTypeSet.addAll(timingHistory.entityTypeSet); history[i++] = timingHistory; } history[i] = new TimingHistory(); // Current snapshot blockTypeSet.addAll(history[i].blockTypeSet); entityTypeSet.addAll(history[i].entityTypeSet); JsonObjectBuilder handlersBuilder = JSONUtil.objectBuilder(); for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { for (TimingHandler id : group.handlers) { if (!id.timed && !id.isSpecial()) { continue; } handlersBuilder.add(id.id, JSONUtil.arrayOf(group.id, id.name)); } } builder.add( "idmap", JSONUtil.objectBuilder() .add( "groups", JSONUtil.mapArrayToObject( TimingIdentifier.GROUP_MAP.values(), (group) -> { return JSONUtil.singleObjectPair(group.id, group.name); })) .add("handlers", handlersBuilder) .add( "worlds", JSONUtil.mapArrayToObject( TimingHistory.worldMap.entrySet(), (entry) -> { return JSONUtil.singleObjectPair(entry.getValue(), entry.getKey()); })) .add( "tileentity", JSONUtil.mapArrayToObject( blockTypeSet, (blockType) -> { return JSONUtil.singleObjectPair( Block.getIdFromBlock((Block) blockType), blockType.getId()); })) .add( "entity", JSONUtil.mapArrayToObject( entityTypeSet, (entityType) -> { return JSONUtil.singleObjectPair( ((SpongeEntityType) entityType).entityTypeId, entityType.getId()); }))); // Information about loaded plugins builder.add( "plugins", JSONUtil.mapArrayToObject( SpongeImpl.getGame().getPluginManager().getPlugins(), (plugin) -> { return JSONUtil.objectBuilder() .add( plugin.getId(), JSONUtil.objectBuilder() .add("version", plugin.getVersion().orElse("")) .add("description", plugin.getDescription().orElse("")) .add("website", plugin.getUrl().orElse("")) .add("authors", AUTHOR_LIST_JOINER.join(plugin.getAuthors()))) .build(); })); // Information on the users Config builder.add( "config", JSONUtil.objectBuilder() .add("sponge", serializeConfigNode(SpongeImpl.getGlobalConfig().getRootNode()))); new TimingsExport(sender, builder.build(), history).start(); }
@Override public void run() { this.sender.sendMessage(Text.of(TextColors.GREEN, "Preparing Timings Report...")); this.out.add("data", JSONUtil.mapArray(this.history, TimingHistory::export)); String response = null; try { HttpURLConnection con = (HttpURLConnection) new URL("http://timings.aikar.co/post").openConnection(); con.setDoOutput(true); con.setRequestProperty( "User-Agent", "Sponge/" + getServerName() + "/" + InetAddress.getLocalHost().getHostName()); con.setRequestMethod("POST"); con.setInstanceFollowRedirects(false); OutputStream request = new GZIPOutputStream(con.getOutputStream()) { { this.def.setLevel(7); } }; request.write(JSONUtil.toString(this.out).getBytes("UTF-8")); request.close(); response = getResponse(con); if (con.getResponseCode() != 302) { this.sender.sendMessage( Text.of( TextColors.RED, "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage())); this.sender.sendMessage(Text.of(TextColors.RED, "Check your logs for more information")); if (response != null) { SpongeImpl.getLogger().fatal(response); } return; } String location = con.getHeaderField("Location"); this.sender.sendMessage( Text.of( TextColors.GREEN, "View Timings Report: ", TextActions.openUrl(new URL(location)), location)); if (!(this.sender instanceof ConsoleSource)) { SpongeImpl.getLogger().info("View Timings Report: " + location); } if (response != null && !response.isEmpty()) { SpongeImpl.getLogger().info("Timing Response: " + response); } } catch (IOException ex) { this.sender.sendMessage( Text.of(TextColors.RED, "Error uploading timings, check your logs for more information")); if (response != null) { SpongeImpl.getLogger().fatal(response); } SpongeImpl.getLogger().fatal("Could not paste timings", ex); } }
TimingHistory() { this.endTime = System.currentTimeMillis() / 1000; this.startTime = TimingsManager.historyStart / 1000; if (timedTicks % 1200 != 0 || MINUTE_REPORTS.isEmpty()) { this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size() + 1]); this.minuteReports[this.minuteReports.length - 1] = new MinuteReport(); } else { this.minuteReports = MINUTE_REPORTS.toArray(new MinuteReport[MINUTE_REPORTS.size()]); } long ticks = 0; for (MinuteReport mp : this.minuteReports) { ticks += mp.ticksRecord.timed; } this.totalTicks = ticks; this.totalTime = FULL_SERVER_TICK.record.totalTime; this.entries = new TimingHistoryEntry[TimingsManager.HANDLERS.size()]; int i = 0; for (TimingHandler handler : TimingsManager.HANDLERS) { this.entries[i++] = new TimingHistoryEntry(handler); } final Map<EntityType, Counter> entityCounts = MRUMapCache.of(LoadingMap.of(Maps.newHashMap(), Counter.loader())); final Map<BlockType, Counter> tileEntityCounts = MRUMapCache.of(LoadingMap.of(Maps.newHashMap(), Counter.loader())); // Information about all loaded chunks/entities this.worlds = JSONUtil.mapArrayToObject( SpongeImpl.getGame().getServer().getWorlds(), (world) -> { return JSONUtil.singleObjectPair( String.valueOf(worldMap.get(world.getName())), JSONUtil.mapArray( world.getLoadedChunks(), (chunk) -> { entityCounts.clear(); tileEntityCounts.clear(); for (Entity entity : chunk.getEntities()) { if (entity.getType() == null) { SpongeImpl.getLogger().error("Entity is not registered {}", entity); continue; } entityCounts.get(entity.getType()).increment(); } for (TileEntity tileEntity : chunk.getTileEntities()) { tileEntityCounts.get(tileEntity.getBlock().getType()).increment(); } if (tileEntityCounts.isEmpty() && entityCounts.isEmpty()) { return null; } return JSONUtil.arrayOf( chunk.getPosition().getX(), chunk.getPosition().getZ(), JSONUtil.mapArrayToObject( entityCounts.entrySet(), (entry) -> { if (entry.getKey() == EntityTypes.UNKNOWN) { return null; } this.entityTypeSet.add(entry.getKey()); return JSONUtil.singleObjectPair( ((SpongeEntityType) entry.getKey()).entityTypeId, entry.getValue().count()); }), JSONUtil.mapArrayToObject( tileEntityCounts.entrySet(), (entry) -> { this.blockTypeSet.add(entry.getKey()); return JSONUtil.singleObjectPair( Block.getIdFromBlock((Block) entry.getKey()), entry.getValue().count()); })); })); }); }