mirror of
https://github.com/octoleo/plantuml-server.git
synced 2024-12-22 08:48:54 +00:00
[FEATURE] Add stat packages
This commit is contained in:
parent
8799670f1d
commit
0cfaaf9bbc
@ -0,0 +1,39 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public interface LogCallback {
|
||||
|
||||
public void logHtmlCreate(String token, long date0, long date1, String encoded, HttpServletRequest request);
|
||||
|
||||
public void logHtmlLoadPage(HttpServletRequest request, long date0, String start, String end, String token,
|
||||
String width, String height);
|
||||
|
||||
public void logHtmlLoadImage(HttpServletRequest request, long date0, String start, String end, String token,
|
||||
String width, String height);
|
||||
|
||||
public void logImageGeneration(HttpServletRequest request, long date0, long date1, String type);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class StatSxServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
String token = request.getParameter("t");
|
||||
String start = request.getParameter("s");
|
||||
String page = request.getParameter("p");
|
||||
String image = request.getParameter("i");
|
||||
String width = request.getParameter("w");
|
||||
String height = request.getParameter("h");
|
||||
|
||||
if (page != null) {
|
||||
Stats.getInstance().logHtmlLoadPage(request, System.currentTimeMillis(), start, page, token, width, height);
|
||||
}
|
||||
if (image != null) {
|
||||
Stats.getInstance().logHtmlLoadImage(request, System.currentTimeMillis(), start, image, token, width,
|
||||
height);
|
||||
}
|
||||
|
||||
// System.err.println("get sx1 " + token + " start=" + start + " page=" + page + " image=" + image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
super.destroy();
|
||||
Stats.getInstance().destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
|
||||
IOException {
|
||||
}
|
||||
}
|
312
src/main/java/net/sourceforge/plantuml/pstat/Stats.java
Normal file
312
src/main/java/net/sourceforge/plantuml/pstat/Stats.java
Normal file
@ -0,0 +1,312 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.event.StatEvent;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventAdminStart;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventAdminStop;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventFileIterator;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlCreate;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadImage;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadPage;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
|
||||
import net.sourceforge.plantuml.pstat.graph.Curve;
|
||||
import net.sourceforge.plantuml.pstat.tick.GraphData;
|
||||
import net.sourceforge.plantuml.pstat.tick.GraphDataLongTerm;
|
||||
import net.sourceforge.plantuml.pstat.tick.TickDatabase;
|
||||
|
||||
public class Stats implements LogCallback {
|
||||
|
||||
public static final boolean USE_STATS = true;
|
||||
|
||||
static class Mem {
|
||||
public Mem(StatEvent ev) {
|
||||
totalMemory = (int) (ev.getTotalMemory() / 1024L / 1024L);
|
||||
freeMemory = (int) (ev.getFreeMemory() / 1024L / 1024L);
|
||||
activeCount = ev.getActiveCount();
|
||||
time = ev.getStartServerTime();
|
||||
|
||||
}
|
||||
|
||||
final private long time;
|
||||
final private int freeMemory;
|
||||
final private int totalMemory;
|
||||
final private int activeCount;
|
||||
}
|
||||
|
||||
private final static Stats singleton = new Stats();
|
||||
|
||||
private final LinkedBlockingDeque<StatEvent> events = new LinkedBlockingDeque<StatEvent>();
|
||||
private final LinkedBlockingDeque<Mem> memories = new LinkedBlockingDeque<Mem>();
|
||||
private final TickDatabase tickDatabase = USE_STATS ? new TickDatabase() : null;
|
||||
|
||||
public GraphData getGraphData() {
|
||||
return tickDatabase == null ? new GraphData() : tickDatabase.getGraphData();
|
||||
}
|
||||
|
||||
public GraphDataLongTerm getGraphDataLongTerm() {
|
||||
return tickDatabase == null ? new GraphDataLongTerm() : tickDatabase.getGraphDataLongTerm();
|
||||
}
|
||||
|
||||
private static final Random rnd = new Random();
|
||||
|
||||
public String getNewToken(long now) {
|
||||
final String t = Integer.toString((int) (now / 1000L), 36)
|
||||
+ Long.toString(Math.abs(rnd.nextLong()), 36).substring(1);
|
||||
return t;
|
||||
}
|
||||
|
||||
public static File getSavedFile() {
|
||||
return new File(getSavedFileName() + ".pat");
|
||||
}
|
||||
|
||||
public static String getSavedFileName() {
|
||||
final DateFormat df = new SimpleDateFormat("yyyy_MM", Locale.US);
|
||||
return "pdata" + df.format(new Date());
|
||||
}
|
||||
|
||||
public static String getPreviousFileName() {
|
||||
final DateFormat df = new SimpleDateFormat("yyyy_MM", Locale.US);
|
||||
final String cname = df.format(new Date());
|
||||
int y = Integer.parseInt(cname.substring(0, 4));
|
||||
int m = Integer.parseInt(cname.substring(5, 7));
|
||||
m--;
|
||||
if (m == 0) {
|
||||
y--;
|
||||
m = 12;
|
||||
}
|
||||
return "pdata" + String.format("%04d", y) + "_" + String.format("%02d", m);
|
||||
}
|
||||
|
||||
private Stats() {
|
||||
final Thread th = new Thread() {
|
||||
public void run() {
|
||||
fileAccess.lock();
|
||||
try {
|
||||
reload();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
fileAccess.unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
addEvent(new StatEventAdminStart());
|
||||
th.start();
|
||||
}
|
||||
|
||||
private final Lock fileAccess = new ReentrantLock();
|
||||
|
||||
private void reload() throws IOException {
|
||||
reload(getSavedFile());
|
||||
final String cur = getSavedFileName();
|
||||
for (char c = 'a'; c < 'z'; c++) {
|
||||
reload(cur + c);
|
||||
}
|
||||
final String prev = getPreviousFileName();
|
||||
reload(prev);
|
||||
for (char c = 'a'; c < 'z'; c++) {
|
||||
reload(prev + c);
|
||||
}
|
||||
reload("legacy2000");
|
||||
}
|
||||
|
||||
private void reload(final String name) throws IOException {
|
||||
File file = new File(name + ".pat");
|
||||
if (file.exists() == false) {
|
||||
file = new File(name + ".pat.gz");
|
||||
}
|
||||
if (file.exists() == false) {
|
||||
file = new File(name + ".zip");
|
||||
}
|
||||
reload(file);
|
||||
}
|
||||
|
||||
private void reload(final File file) throws IOException {
|
||||
if (file.exists() == false) {
|
||||
return;
|
||||
}
|
||||
StatEventFileIterator it = null;
|
||||
try {
|
||||
it = StatEventFileIterator.fromFile(file);
|
||||
reload(it);
|
||||
} finally {
|
||||
if (it != null) {
|
||||
it.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reload(StatEventFileIterator it) {
|
||||
while (it.hasNext()) {
|
||||
final StatEvent ev = it.next();
|
||||
updateStats(ev);
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
||||
public static Stats getInstance() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
private void addEvent(final StatEvent ev) {
|
||||
updateStats(ev);
|
||||
events.add(ev);
|
||||
memories.add(new Mem(ev));
|
||||
while (memories.size() > 100) {
|
||||
final Iterator<Mem> it = memories.iterator();
|
||||
it.next();
|
||||
it.remove();
|
||||
}
|
||||
|
||||
if (fileAccess.tryLock()) {
|
||||
try {
|
||||
saveEvents();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
fileAccess.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
System.err.println("CALLING DESTROY");
|
||||
addEvent(new StatEventAdminStop());
|
||||
if (fileAccess.tryLock()) {
|
||||
try {
|
||||
saveEvents();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
fileAccess.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveEvents() throws IOException {
|
||||
final File saveFile = getSavedFile();
|
||||
// final long startSave = System.currentTimeMillis();
|
||||
DataOutputStream oos = null;
|
||||
try {
|
||||
oos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(saveFile, true), 1024 * 50));
|
||||
for (Iterator<StatEvent> it = events.iterator(); it.hasNext();) {
|
||||
final StatEvent event = it.next();
|
||||
event.save(oos);
|
||||
it.remove();
|
||||
// nbSave++;
|
||||
}
|
||||
} finally {
|
||||
if (oos != null) {
|
||||
oos.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void logHtmlCreate(String token, long date0, long date1, String encoded, HttpServletRequest request) {
|
||||
final StatEvent event = new StatEventHtmlCreate(request, date0, date1, token, encoded);
|
||||
addEvent(event);
|
||||
}
|
||||
|
||||
public void logHtmlLoadPage(HttpServletRequest request, long date0, String start, String end, String token,
|
||||
String width, String height) {
|
||||
final long start_ = parseSecureLong(start);
|
||||
final long end_ = parseSecureLong(end);
|
||||
final int width_ = parseSecureInt(width);
|
||||
final int height_ = parseSecureInt(height);
|
||||
final StatEventHtmlLoadPage event = new StatEventHtmlLoadPage(request, date0, start_, end_, token, width_,
|
||||
height_);
|
||||
addEvent(event);
|
||||
|
||||
}
|
||||
|
||||
public void logHtmlLoadImage(HttpServletRequest request, long date0, String start, String end, String token,
|
||||
String width, String height) {
|
||||
final long start_ = parseSecureLong(start);
|
||||
final long end_ = parseSecureLong(end);
|
||||
final int width_ = parseSecureInt(width);
|
||||
final int height_ = parseSecureInt(height);
|
||||
final StatEventHtmlLoadImage event = new StatEventHtmlLoadImage(request, date0, start_, end_, token, width_,
|
||||
height_);
|
||||
addEvent(event);
|
||||
}
|
||||
|
||||
public void logImageGeneration(HttpServletRequest request, long date0, long date1, String type) {
|
||||
final StatEventImageGeneration event = new StatEventImageGeneration(request, date0, date1, type);
|
||||
addEvent(event);
|
||||
}
|
||||
|
||||
private int parseSecureInt(String s) {
|
||||
if (s != null && s.matches("\\d+")) {
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private long parseSecureLong(String s) {
|
||||
if (s != null && s.matches("\\d+")) {
|
||||
return Long.parseLong(s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void updateStats(final StatEvent ev) {
|
||||
if (USE_STATS) {
|
||||
tickDatabase.updateStats(ev);
|
||||
}
|
||||
}
|
||||
|
||||
public Curve memories(double height, double singleBarWidth, int fontSize) {
|
||||
final Curve result = new Curve(height, singleBarWidth, fontSize);
|
||||
for (Mem mem : memories) {
|
||||
result.addData(new Date(mem.time).toString(), mem.totalMemory, mem.freeMemory);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Curve threads(double height, double singleBarWidth, int fontSize) {
|
||||
final Curve result = new Curve(height, singleBarWidth, fontSize);
|
||||
for (Mem mem : memories) {
|
||||
result.addData(new Date(mem.time).toString(), mem.activeCount);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
public class WriterOutputStream extends OutputStream {
|
||||
|
||||
final Writer pw;
|
||||
|
||||
public WriterOutputStream(Writer pw) {
|
||||
this.pw = pw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int data) throws IOException {
|
||||
pw.write(data);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
final String s = new String(b, off, len);
|
||||
pw.write(s);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,318 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.maxmind.geoip.LookupService;
|
||||
|
||||
public abstract class StatEvent {
|
||||
|
||||
private final int byteHeader;
|
||||
private final long serverTime;
|
||||
private final Map<String, String> header = new HashMap<String, String>();
|
||||
private final String ipClient;
|
||||
|
||||
private final int activeCount;
|
||||
private final long freeMemory;
|
||||
private final long totalMemory;
|
||||
|
||||
private static final UAParser uaParser = new UAParser();
|
||||
private static final LookupService countryService = initCountryService();
|
||||
|
||||
private static LookupService initCountryService() {
|
||||
try {
|
||||
return new LookupService("GeoIP.dat", LookupService.GEOIP_MEMORY_CACHE);
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("path=" + new File("GeoIP.dat").getAbsolutePath() + " not found");
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("path=" + new File("GeoIP.dat").getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public void save(DataOutputStream os) throws IOException {
|
||||
os.write(0x43);
|
||||
os.writeInt(activeCount);
|
||||
os.writeLong(freeMemory);
|
||||
os.writeLong(totalMemory);
|
||||
os.write(byteHeader);
|
||||
os.writeLong(serverTime);
|
||||
writeStringSecure(os, ipClient);
|
||||
for (Map.Entry<String, String> ent : header.entrySet()) {
|
||||
writeStringSecure(os, ent.getKey());
|
||||
writeStringSecure(os, ent.getValue());
|
||||
}
|
||||
writeStringSecure(os, "");
|
||||
saveSuppData(os);
|
||||
}
|
||||
|
||||
public static StatEvent read(DataInputStream is) throws IOException {
|
||||
final int sign = is.read();
|
||||
if (sign == -1) {
|
||||
return null;
|
||||
}
|
||||
final int activeCount;
|
||||
final long freeMemory;
|
||||
final long totalMemory;
|
||||
if (sign == 0x42) {
|
||||
activeCount = 0;
|
||||
freeMemory = 0;
|
||||
totalMemory = 0;
|
||||
} else if (sign == 0x43) {
|
||||
activeCount = is.readInt();
|
||||
freeMemory = is.readLong();
|
||||
totalMemory = is.readLong();
|
||||
} else {
|
||||
throw new IOException("No 0x42 header found");
|
||||
}
|
||||
final int byteHeader = is.read();
|
||||
final long serverTime = is.readLong();
|
||||
final String ipClient = is.readUTF();
|
||||
final Map<String, String> header = new HashMap<String, String>();
|
||||
while (true) {
|
||||
final String key = is.readUTF();
|
||||
if (key.length() == 0) {
|
||||
break;
|
||||
}
|
||||
final String value = is.readUTF();
|
||||
header.put(key.toLowerCase(), value);
|
||||
}
|
||||
switch (byteHeader) {
|
||||
case 0x51:
|
||||
return new StatEventAdminStart(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
case 0x52:
|
||||
return new StatEventAdminStop(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
case 0x53:
|
||||
return new StatEventAdminSaveLog(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
case 0x43:
|
||||
return new StatEventHtmlCreate(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
case 0x44:
|
||||
return new StatEventHtmlLoadPage(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
case 0x45:
|
||||
return new StatEventHtmlLoadImage(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
case 0x46:
|
||||
case 0x47:
|
||||
return new StatEventImageGeneration(byteHeader, is, serverTime, ipClient, header, activeCount, freeMemory,
|
||||
totalMemory);
|
||||
}
|
||||
throw new IOException("Unknown header " + byteHeader);
|
||||
}
|
||||
|
||||
protected abstract void saveSuppData(DataOutputStream os) throws IOException;
|
||||
|
||||
public StatEvent(int byteHeader, long serverTime, HttpServletRequest request) {
|
||||
this.byteHeader = byteHeader;
|
||||
this.serverTime = serverTime;
|
||||
this.activeCount = Thread.activeCount();
|
||||
this.freeMemory = Runtime.getRuntime().freeMemory();
|
||||
this.totalMemory = Runtime.getRuntime().totalMemory();
|
||||
|
||||
if (request != null) {
|
||||
for (Enumeration foo = request.getHeaderNames(); foo.hasMoreElements();) {
|
||||
String h = foo.nextElement().toString().toLowerCase();
|
||||
String v = request.getHeader(h);
|
||||
header.put(h, v);
|
||||
}
|
||||
this.ipClient = request.getRemoteAddr();
|
||||
} else {
|
||||
this.ipClient = "";
|
||||
}
|
||||
}
|
||||
|
||||
public StatEvent(int byteHeader, long serverTime, String ipClient, Map<String, String> header, int activeCount,
|
||||
long freeMemory, long totalMemory) {
|
||||
this.byteHeader = byteHeader;
|
||||
this.serverTime = serverTime;
|
||||
this.ipClient = ipClient;
|
||||
this.header.putAll(header);
|
||||
this.activeCount = activeCount;
|
||||
this.freeMemory = freeMemory;
|
||||
this.totalMemory = totalMemory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// System.err.println(header.keySet());
|
||||
// System.err.println(header);
|
||||
final long f = freeMemory / 1024 / 1024;
|
||||
final long t = totalMemory / 1024 / 1024;
|
||||
return "{" + Integer.toHexString(byteHeader) + "} " + new Date(serverTime).toGMTString() + " " + f + "/" + t
|
||||
+ " " + activeCount + " " + ipClient + " {" + getAcceptLanguage() + "} {" + getCountry() + "} ["
|
||||
+ getRefererDetailed() + "] ";
|
||||
}
|
||||
|
||||
public String getAcceptLanguage() {
|
||||
final String lang = header.get("accept-language");
|
||||
if (lang == null) {
|
||||
return "??";
|
||||
}
|
||||
if (lang.length() < 2) {
|
||||
return "??";
|
||||
}
|
||||
return lang.substring(0, 2);
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
final String host = header.get("host");
|
||||
if (host == null) {
|
||||
return "??";
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
final String agent = header.get("user-agent");
|
||||
if (agent == null) {
|
||||
return "??";
|
||||
}
|
||||
return agent;
|
||||
}
|
||||
|
||||
public String getReferer() {
|
||||
String agent = header.get("referer");
|
||||
if (agent == null) {
|
||||
return "??";
|
||||
}
|
||||
final int x = agent.indexOf('/', 9);
|
||||
if (x == -1) {
|
||||
return "??";
|
||||
}
|
||||
agent = agent.substring(0, x);
|
||||
if (agent.matches(".*\\.[a-z]{2,3}$")) {
|
||||
return agent;
|
||||
}
|
||||
return "Other";
|
||||
}
|
||||
|
||||
private String getRefererDetailed() {
|
||||
String agent = header.get("referer");
|
||||
if (agent == null) {
|
||||
return "None";
|
||||
}
|
||||
final int x = agent.indexOf('/', 9);
|
||||
if (x == -1) {
|
||||
return "??";
|
||||
}
|
||||
agent = agent.substring(0, x);
|
||||
if (agent.matches(".*\\.[a-z]{2,3}$")) {
|
||||
return agent;
|
||||
}
|
||||
// return "Other";
|
||||
return agent;
|
||||
}
|
||||
|
||||
public String getOperatingSystem() {
|
||||
final String user = getUserAgent();
|
||||
if ("??".equals(user)) {
|
||||
return "??";
|
||||
}
|
||||
final String result = uaParser.getOperatingSystem(user);
|
||||
if (result.startsWith("OS X")) {
|
||||
return "OS X";
|
||||
}
|
||||
if (result.startsWith("Android")) {
|
||||
return "Android";
|
||||
}
|
||||
if (result.startsWith("iOS")) {
|
||||
return "iOS";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getBrowser() {
|
||||
final String user = getUserAgent();
|
||||
if ("??".equals(user)) {
|
||||
return "??";
|
||||
}
|
||||
final String result = uaParser.getBrowser(user);
|
||||
return result;
|
||||
}
|
||||
|
||||
public long getStartServerTime() {
|
||||
return serverTime;
|
||||
}
|
||||
|
||||
protected Map<String, String> getHeader() {
|
||||
return Collections.unmodifiableMap(header);
|
||||
}
|
||||
|
||||
public String getIpClient() {
|
||||
return ipClient;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
if (countryService == null) {
|
||||
return "Not loaded";
|
||||
}
|
||||
if (ipClient == null) {
|
||||
return "??";
|
||||
}
|
||||
final String country = countryService.getCountry(ipClient).getName();
|
||||
if ("N/A".equals(country)) {
|
||||
return "??";
|
||||
}
|
||||
return country;
|
||||
}
|
||||
|
||||
final protected void writeStringSecure(DataOutputStream oos, String s) throws IOException {
|
||||
if (s == null) {
|
||||
s = "";
|
||||
}
|
||||
oos.writeUTF(s);
|
||||
}
|
||||
|
||||
final protected String shorten(String s) {
|
||||
if (s.length() > 20) {
|
||||
return s.substring(0, 20) + "...";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public final int getActiveCount() {
|
||||
return activeCount;
|
||||
}
|
||||
|
||||
public final long getFreeMemory() {
|
||||
return freeMemory;
|
||||
}
|
||||
|
||||
public final long getTotalMemory() {
|
||||
return totalMemory;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class StatEventAdminSaveLog extends StatEvent {
|
||||
|
||||
private final int saveDuration;
|
||||
private final int nbSaved;
|
||||
private final int nbRemainingAfterSave;
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
os.writeInt(saveDuration);
|
||||
os.writeInt(nbSaved);
|
||||
os.writeInt(nbRemainingAfterSave);
|
||||
}
|
||||
|
||||
public StatEventAdminSaveLog(int saveDuration, int nbSaved, int nbRemainingAfterSave) {
|
||||
super(0x53, System.currentTimeMillis(), null);
|
||||
this.saveDuration = saveDuration;
|
||||
this.nbSaved = nbSaved;
|
||||
this.nbRemainingAfterSave = nbRemainingAfterSave;
|
||||
}
|
||||
|
||||
public StatEventAdminSaveLog(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
|
||||
int activeCount, long freeMemory, long totalMemory) throws IOException {
|
||||
super(0x53, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
this.saveDuration = is.readInt();
|
||||
this.nbSaved = is.readInt();
|
||||
this.nbRemainingAfterSave = is.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " SAVELOG " + saveDuration + " ms, nb=" + nbSaved + " remain=" + nbRemainingAfterSave;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class StatEventAdminStart extends StatEvent {
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
}
|
||||
|
||||
public StatEventAdminStart() {
|
||||
super(0x51, System.currentTimeMillis(), null);
|
||||
}
|
||||
|
||||
public StatEventAdminStart(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
|
||||
int activeCount, long freeMemory, long totalMemory) {
|
||||
super(0x51, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " START";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class StatEventAdminStop extends StatEvent {
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
}
|
||||
|
||||
public StatEventAdminStop() {
|
||||
super(0x52, System.currentTimeMillis(), null);
|
||||
}
|
||||
|
||||
public StatEventAdminStop(DataInputStream is, long serverTime, String ipClient, Map<String, String> header, int activeCount,
|
||||
long freeMemory, long totalMemory) {
|
||||
super(0x52, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " STOP";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
public abstract class StatEventFileIterator implements Closeable, Iterator<StatEvent> {
|
||||
|
||||
final public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static StatEventFileIterator fromFile(File f) throws IOException {
|
||||
if (f.getName().endsWith(".zip")) {
|
||||
return new StatEventFileIteratorZip(f);
|
||||
}
|
||||
return new StatEventFileIteratorSimple(f);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
class StatEventFileIteratorSimple extends StatEventFileIterator {
|
||||
|
||||
private DataInputStream is;
|
||||
private StatEvent potentialNext;
|
||||
|
||||
public StatEventFileIteratorSimple(File f) throws IOException {
|
||||
if (f.getName().endsWith(".gz")) {
|
||||
this.is = new DataInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(f))));
|
||||
} else {
|
||||
this.is = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
|
||||
}
|
||||
this.potentialNext = StatEvent.read(is);
|
||||
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
is.close();
|
||||
is = null;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return potentialNext != null;
|
||||
}
|
||||
|
||||
public StatEvent next() {
|
||||
final StatEvent result = potentialNext;
|
||||
try {
|
||||
potentialNext = StatEvent.read(is);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
final File f = new File("C:/eclipse/eclipse/pdata2013_11.pat");
|
||||
final StatEventFileIteratorSimple it = new StatEventFileIteratorSimple(f);
|
||||
while (it.hasNext()) {
|
||||
final StatEvent ev = it.next();
|
||||
System.out.println(ev);
|
||||
}
|
||||
it.close();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
class StatEventFileIteratorZip extends StatEventFileIterator {
|
||||
|
||||
private StatEvent potentialNext;
|
||||
private ZipInputStream zip;
|
||||
private ZipEntry current;
|
||||
private DataInputStream is;
|
||||
|
||||
public StatEventFileIteratorZip(File f) throws IOException {
|
||||
this.zip = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)));
|
||||
current = zip.getNextEntry();
|
||||
is = new DataInputStream(zip);
|
||||
this.potentialNext = StatEvent.read(is);
|
||||
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
is.close();
|
||||
is = null;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return potentialNext != null;
|
||||
}
|
||||
|
||||
public StatEvent next() {
|
||||
final StatEvent result = potentialNext;
|
||||
try {
|
||||
potentialNext = StatEvent.read(is);
|
||||
if (potentialNext == null) {
|
||||
current = zip.getNextEntry();
|
||||
if (current != null) {
|
||||
// is = new DataInputStream(zip);
|
||||
this.potentialNext = StatEvent.read(is);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
final File f = new File("G:/log2/pdata2013_11.zip");
|
||||
final StatEventFileIteratorZip it = new StatEventFileIteratorZip(f);
|
||||
int nb = 0;
|
||||
while (it.hasNext()) {
|
||||
final StatEvent ev = it.next();
|
||||
nb++;
|
||||
// System.out.println(ev);
|
||||
}
|
||||
System.err.println("nb=" + nb);
|
||||
it.close();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class StatEventHtmlCreate extends StatEvent {
|
||||
|
||||
private final long date1;
|
||||
private final String token;
|
||||
private final String encoded;
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
os.writeLong(date1);
|
||||
writeStringSecure(os, token);
|
||||
writeStringSecure(os, encoded);
|
||||
}
|
||||
|
||||
public StatEventHtmlCreate(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
|
||||
int activeCount, long freeMemory, long totalMemory) throws IOException {
|
||||
super(0x43, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
this.date1 = is.readLong();
|
||||
this.token = is.readUTF();
|
||||
this.encoded = is.readUTF();
|
||||
}
|
||||
|
||||
public StatEventHtmlCreate(HttpServletRequest request, long date0, long date1, String token, String encoded) {
|
||||
super(0x43, date0, request);
|
||||
this.date1 = date1;
|
||||
this.token = token;
|
||||
this.encoded = encoded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final long duration = date1 - getStartServerTime();
|
||||
return super.toString() + " " + token + " (ht=" + duration + "ms) " + shorten(encoded);
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class StatEventHtmlLoadImage extends StatEvent {
|
||||
|
||||
private final long start;
|
||||
private final long end;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final String token;
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
os.writeLong(start);
|
||||
os.writeLong(end);
|
||||
os.writeInt(width);
|
||||
os.writeInt(height);
|
||||
writeStringSecure(os, token);
|
||||
}
|
||||
|
||||
public StatEventHtmlLoadImage(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
|
||||
int activeCount, long freeMemory, long totalMemory) throws IOException {
|
||||
super(0x45, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
this.start = is.readLong();
|
||||
this.end = is.readLong();
|
||||
this.width = is.readInt();
|
||||
this.height = is.readInt();
|
||||
this.token = is.readUTF();
|
||||
}
|
||||
|
||||
public StatEventHtmlLoadImage(HttpServletRequest request, long date0, long start, long end, String token,
|
||||
int width, int height) {
|
||||
super(0x45, date0, request);
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final long duration = end - start;
|
||||
return super.toString() + " " + token + " (im=" + duration + "ms) " + width + "x" + height;
|
||||
}
|
||||
|
||||
public int getImageLoad() {
|
||||
final long duration = end - start;
|
||||
return (int) duration;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class StatEventHtmlLoadPage extends StatEvent {
|
||||
|
||||
private final long start;
|
||||
private final long end;
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final String token;
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
os.writeLong(start);
|
||||
os.writeLong(end);
|
||||
os.writeInt(width);
|
||||
os.writeInt(height);
|
||||
writeStringSecure(os, token);
|
||||
}
|
||||
|
||||
public StatEventHtmlLoadPage(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
|
||||
int activeCount, long freeMemory, long totalMemory) throws IOException {
|
||||
super(0x44, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
this.start = is.readLong();
|
||||
this.end = is.readLong();
|
||||
this.width = is.readInt();
|
||||
this.height = is.readInt();
|
||||
this.token = is.readUTF();
|
||||
}
|
||||
|
||||
public StatEventHtmlLoadPage(HttpServletRequest request, long date0, long start, long end, String token, int width,
|
||||
int height) {
|
||||
super(0x44, date0, request);
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.token = token;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final long duration = end - start;
|
||||
return super.toString() + " " + token + " (pa=" + duration + "ms) " + width + "x" + height;
|
||||
}
|
||||
|
||||
public int getPageLoad() {
|
||||
final long duration = end - start;
|
||||
return (int) duration;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public class StatEventImageGeneration extends StatEvent {
|
||||
|
||||
private final long date1;
|
||||
private final String uri;
|
||||
private String type = "??";
|
||||
|
||||
@Override
|
||||
protected void saveSuppData(DataOutputStream os) throws IOException {
|
||||
os.writeLong(date1);
|
||||
writeStringSecure(os, uri);
|
||||
writeStringSecure(os, type);
|
||||
}
|
||||
|
||||
public StatEventImageGeneration(int byteHeader, DataInputStream is, long serverTime, String ipClient,
|
||||
Map<String, String> header, int activeCount, long freeMemory, long totalMemory) throws IOException {
|
||||
super(byteHeader, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
|
||||
this.date1 = is.readLong();
|
||||
this.uri = is.readUTF();
|
||||
if (byteHeader == 0x47) {
|
||||
this.type = is.readUTF();
|
||||
}
|
||||
}
|
||||
|
||||
public StatEventImageGeneration(HttpServletRequest request, long date0, long date1, String type) {
|
||||
super(0x47, date0, request);
|
||||
this.date1 = date1;
|
||||
this.uri = request.getRequestURI();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public StatEventImageGeneration(long date0, String uri, String type) {
|
||||
super(0x47, date0, null);
|
||||
this.date1 = 0;
|
||||
this.uri = uri;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// final long duration = date1 == 0 ? -1 : date1 - getStartServerTime();
|
||||
return super.toString() + "(" + type + ") [" + getDuration() + "ms] " + shorten(uri);
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
final long duration = date1 == 0 ? -1 : date1 - getStartServerTime();
|
||||
return (int) duration;
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getIncomming() {
|
||||
final String refererer = getReferer();
|
||||
if (refererer.startsWith("http://www.plantuml.com")) {
|
||||
return "www.plantuml.com";
|
||||
}
|
||||
if (refererer.startsWith("http://plantuml.com")) {
|
||||
return "plantuml.com";
|
||||
}
|
||||
return "Other website";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.event;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.sf.uadetector.OperatingSystem;
|
||||
import net.sf.uadetector.ReadableUserAgent;
|
||||
import net.sf.uadetector.UserAgentFamily;
|
||||
import net.sf.uadetector.UserAgentStringParser;
|
||||
import net.sf.uadetector.service.UADetectorServiceFactory;
|
||||
|
||||
public class UAParser {
|
||||
|
||||
private static final UserAgentStringParser parser = UADetectorServiceFactory.getResourceModuleParser();
|
||||
|
||||
private static final Map<String, String> osMap = new ConcurrentHashMap<String, String>();
|
||||
private static final Map<String, String> browserMap = new ConcurrentHashMap<String, String>();
|
||||
|
||||
public String getOperatingSystem(String userAgent) {
|
||||
String result = osMap.get(userAgent);
|
||||
if (result == null) {
|
||||
final ReadableUserAgent agent = parser.parse(userAgent);
|
||||
final OperatingSystem os = agent.getOperatingSystem();
|
||||
result = os.getName();
|
||||
osMap.put(userAgent, result);
|
||||
// System.err.println("os=" + osMap.size());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getBrowser(String userAgent) {
|
||||
String result = browserMap.get(userAgent);
|
||||
if (result == null) {
|
||||
final ReadableUserAgent agent = parser.parse(userAgent);
|
||||
final UserAgentFamily family = agent.getFamily();
|
||||
result = family.getName();
|
||||
browserMap.put(userAgent, result);
|
||||
// System.err.println("browser=" + browserMap.size());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
285
src/main/java/net/sourceforge/plantuml/pstat/graph/Chart.java
Normal file
285
src/main/java/net/sourceforge/plantuml/pstat/graph/Chart.java
Normal file
@ -0,0 +1,285 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||
import net.sourceforge.plantuml.graphic.StringBounder;
|
||||
import net.sourceforge.plantuml.pstat.WriterOutputStream;
|
||||
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||
import net.sourceforge.plantuml.ugraphic.UPolygon;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UText;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
|
||||
|
||||
public class Chart {
|
||||
|
||||
class Data {
|
||||
final private String label;
|
||||
final private int value;
|
||||
|
||||
Data(String label, int value) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private double getAngle() {
|
||||
return 360.0 * value / sum;
|
||||
}
|
||||
|
||||
private String getFullLabel() {
|
||||
final long pour = 100L * value / sum;
|
||||
return label + " [" + pour + "%] [" + value + "/" + sum + "]";
|
||||
}
|
||||
|
||||
public String getLabelShort() {
|
||||
if (label.length() > 40) {
|
||||
return "...";
|
||||
}
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<Data> datas = new ArrayList<Data>();
|
||||
private long sum;
|
||||
private final UFont fontComment = new UFont("", Font.BOLD, 12);
|
||||
|
||||
public void compact() {
|
||||
final List<Data> newList = new ArrayList<Data>();
|
||||
final StringBuilder relicat = new StringBuilder();
|
||||
int relicatValue = 0;
|
||||
final int limit = (int) (sum / 100);
|
||||
for (Data d : datas) {
|
||||
if (d.value > limit) {
|
||||
newList.add(d);
|
||||
} else {
|
||||
if (relicat.length() > 0) {
|
||||
relicat.append(" - ");
|
||||
}
|
||||
relicat.append(d.label);
|
||||
relicatValue += d.value;
|
||||
}
|
||||
}
|
||||
if (relicatValue > 0) {
|
||||
newList.add(new Data(relicat.toString(), relicatValue));
|
||||
}
|
||||
datas.clear();
|
||||
datas.addAll(newList);
|
||||
}
|
||||
|
||||
public void removeBig(double pour) {
|
||||
final List<Data> newList = new ArrayList<Data>();
|
||||
final int limit = (int) (sum * pour);
|
||||
for (Data d : datas) {
|
||||
if (d.value <= limit) {
|
||||
newList.add(d);
|
||||
} else {
|
||||
sum -= d.value;
|
||||
}
|
||||
}
|
||||
datas.clear();
|
||||
datas.addAll(newList);
|
||||
}
|
||||
|
||||
private final double heightGraph;
|
||||
private final List<HtmlColor> colors = Arrays.asList(HtmlColorUtils.getColorIfValid("CadetBlue"),
|
||||
HtmlColorUtils.getColorIfValid("Sienna"), HtmlColorUtils.getColorIfValid("Khaki"),
|
||||
HtmlColorUtils.getColorIfValid("GreenYellow"), HtmlColorUtils.getColorIfValid("Olive"),
|
||||
HtmlColorUtils.GRAY, HtmlColorUtils.getColorIfValid("HotPink"),
|
||||
HtmlColorUtils.getColorIfValid("LightBlue"), HtmlColorUtils.getColorIfValid("Orange"),
|
||||
HtmlColorUtils.getColorIfValid("OrangeRed"), HtmlColorUtils.getColorIfValid("Chocolate"),
|
||||
HtmlColorUtils.getColorIfValid("Coral"));
|
||||
|
||||
public Chart(double height) {
|
||||
this.heightGraph = height;
|
||||
}
|
||||
|
||||
public void addData(String label, int value) {
|
||||
datas.add(new Data(label, value));
|
||||
this.sum += value;
|
||||
}
|
||||
|
||||
private void drawPart(UGraphic ug, double v1, double v2, HtmlColor color, String title) {
|
||||
if (v2 < 180) {
|
||||
drawPartInternal(ug, v1, v2, color, title);
|
||||
} else {
|
||||
drawPartInternal(ug, v1, v2 / 2, color, title);
|
||||
drawPartInternal(ug, v1 + v2 / 2, v2 / 2, color, title);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawPartInternal(UGraphic ug, double v1, double v2, HtmlColor color, String title) {
|
||||
// System.err.println("v1=" + v1 + " v2=" + v2 + " v1+v2=" + (v1 + v2));
|
||||
ug = ug.apply(new UStroke(0));
|
||||
ug = ug.apply(new UChangeBackColor(color)).apply(new UChangeColor(color));
|
||||
ug.startUrl(new Url("", title));
|
||||
ug.apply(new UStroke(2)).draw(new UEllipse(heightGraph, heightGraph, v1, v2));
|
||||
|
||||
final double cx = heightGraph / 2;
|
||||
final double cy = heightGraph / 2;
|
||||
|
||||
final double start = v1 + 90;
|
||||
final double extend = v2;
|
||||
|
||||
final double x1 = cx + Math.sin(start * Math.PI / 180.) * heightGraph / 2;
|
||||
final double y1 = cy + Math.cos(start * Math.PI / 180.) * heightGraph / 2;
|
||||
final double x2 = cx + Math.sin((start + extend) * Math.PI / 180.) * heightGraph / 2;
|
||||
final double y2 = cy + Math.cos((start + extend) * Math.PI / 180.) * heightGraph / 2;
|
||||
|
||||
final UPolygon poly = new UPolygon();
|
||||
poly.addPoint(heightGraph / 2, heightGraph / 2);
|
||||
poly.addPoint(x1, y1);
|
||||
poly.addPoint(x2, y2);
|
||||
ug.apply(new UStroke(1.5)).draw(poly);
|
||||
ug.closeAction();
|
||||
|
||||
}
|
||||
|
||||
private void drawPartComment(UGraphic ug, double v1, double v2, String title) {
|
||||
final double cx = heightGraph / 2;
|
||||
final double cy = heightGraph / 2;
|
||||
|
||||
final double start = v1 + 90;
|
||||
final double extend = v2;
|
||||
|
||||
final double middle = (start + extend / 2) * Math.PI / 180.;
|
||||
final double x3 = cx + Math.sin(middle) * (heightGraph / 2 * 4 / 5);
|
||||
final double y3 = cy + Math.cos(middle) * (heightGraph / 2 * 4 / 5);
|
||||
final double x4 = cx + Math.sin(middle) * (heightGraph / 2 + 20);
|
||||
final double y4 = cy + Math.cos(middle) * (heightGraph / 2 + 20);
|
||||
|
||||
ug = ug.apply(new UStroke(2));
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
|
||||
|
||||
drawLine(ug, x3, y3, x4, y4);
|
||||
|
||||
final UText text = new UText(title, new FontConfiguration(fontComment, HtmlColorUtils.BLACK));
|
||||
final double textWidth = ug.getStringBounder().calculateDimension(fontComment, title).getWidth();
|
||||
final double xText;
|
||||
if (x4 < cx) {
|
||||
xText = x4 - textWidth - 3;
|
||||
} else {
|
||||
xText = x4 + 3;
|
||||
}
|
||||
ug.apply(new UTranslate(xText, y4)).draw(text);
|
||||
|
||||
}
|
||||
|
||||
private void drawPartLimit(UGraphic ug, double v1, double v2) {
|
||||
ug = ug.apply(new UStroke(1.5));
|
||||
|
||||
final double cx = heightGraph / 2;
|
||||
final double cy = heightGraph / 2;
|
||||
|
||||
final double start = v1 + 90;
|
||||
final double extend = v2;
|
||||
|
||||
final double x1 = cx + Math.sin(start * Math.PI / 180.) * heightGraph / 2;
|
||||
final double y1 = cy + Math.cos(start * Math.PI / 180.) * heightGraph / 2;
|
||||
|
||||
drawLine(ug, cx, cy, x1, y1);
|
||||
|
||||
}
|
||||
|
||||
private void drawLine(UGraphic ug, double x1, double y1, double x2, double y2) {
|
||||
ug = ug.apply(new UTranslate(x1, y1));
|
||||
ug.draw(new ULine(x2 - x1, y2 - y1));
|
||||
}
|
||||
|
||||
private double getMaxTitleWidth(StringBounder stringBounder) {
|
||||
double result = 0;
|
||||
for (Data data : datas) {
|
||||
if (data.value == 0) {
|
||||
continue;
|
||||
}
|
||||
final double textWidth = stringBounder.calculateDimension(fontComment, data.getLabelShort()).getWidth();
|
||||
result = Math.max(result, textWidth);
|
||||
}
|
||||
return result * 1.1 + 20;
|
||||
}
|
||||
|
||||
public void printSvg(Writer writer) throws IOException {
|
||||
|
||||
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
|
||||
double wmargin = getMaxTitleWidth(ug.getStringBounder());
|
||||
ug = ug.apply(new UTranslate(wmargin, 40));
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.WHITE));
|
||||
ug = ug.apply(new UChangeBackColor(HtmlColorUtils.WHITE));
|
||||
ug.apply(new UTranslate(heightGraph + wmargin, 0)).draw(new URectangle(1, 1));
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
|
||||
ug = ug.apply(new UChangeBackColor(HtmlColorUtils.BLUE));
|
||||
|
||||
double s = 0;
|
||||
ug = ug.apply(new UChangeBackColor(HtmlColorUtils.GREEN));
|
||||
Iterator<HtmlColor> cols = colors.iterator();
|
||||
for (Data data : datas) {
|
||||
if (data.value == 0) {
|
||||
continue;
|
||||
}
|
||||
if (cols.hasNext() == false) {
|
||||
cols = colors.iterator();
|
||||
}
|
||||
drawPart(ug, s, data.getAngle(), cols.next(), data.getFullLabel());
|
||||
s += data.getAngle();
|
||||
}
|
||||
s = 0;
|
||||
for (Data data : datas) {
|
||||
if (data.value == 0) {
|
||||
continue;
|
||||
}
|
||||
drawPartLimit(ug, s, data.getAngle());
|
||||
drawPartComment(ug, s, data.getAngle(), data.getLabelShort());
|
||||
s += data.getAngle();
|
||||
}
|
||||
ug = ug.apply(new UStroke(2));
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
|
||||
ug = ug.apply(new UChangeBackColor(null));
|
||||
ug.draw(new UEllipse(heightGraph, heightGraph));
|
||||
|
||||
OutputStream os = new WriterOutputStream(writer);
|
||||
ug.writeImage(os, null, 96);
|
||||
os.flush();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ChartProducer {
|
||||
|
||||
private final Collection<Integer> datas;
|
||||
|
||||
public ChartProducer(Collection<Integer> all) {
|
||||
datas = all;
|
||||
}
|
||||
|
||||
public Chart getChart(double height) {
|
||||
final Chart chart = new Chart(height);
|
||||
final int nb = datas.size();
|
||||
if (nb == 0) {
|
||||
return chart;
|
||||
}
|
||||
|
||||
long sum = 0;
|
||||
int max = 0;
|
||||
for (int v : datas) {
|
||||
sum += v;
|
||||
max = Math.max(max, v);
|
||||
}
|
||||
|
||||
final int mean = NiceNumber.getNicer((int) (sum / nb));
|
||||
|
||||
final List<Step> steps = new ArrayList<Step>();
|
||||
steps.add(new Step(0, NiceNumber.getNicer(mean / 3)));
|
||||
steps.add(new Step(NiceNumber.getNicer(mean / 3), NiceNumber.getNicer(2 * mean / 3)));
|
||||
steps.add(new Step(NiceNumber.getNicer(2 * mean / 3), mean));
|
||||
final int delta = (max - mean) / 3;
|
||||
steps.add(new Step(mean, NiceNumber.getNicer(mean + delta)));
|
||||
steps.add(new Step(NiceNumber.getNicer(mean + delta), NiceNumber.getNicer(mean + 2 * delta)));
|
||||
steps.add(new Step(NiceNumber.getNicer(mean + 2 * delta), max + 1));
|
||||
|
||||
for (int v : datas) {
|
||||
count(steps, v);
|
||||
}
|
||||
final int lim = datas.size() / 50;
|
||||
while (eventuallyMerge(steps, lim)) {
|
||||
|
||||
}
|
||||
|
||||
for (Step s : steps) {
|
||||
chart.addData(s.getTitle(), s.count);
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
static class Step {
|
||||
final private int from;
|
||||
final private int to;
|
||||
private int count;
|
||||
|
||||
Step(int from, int to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
Step mergeWith(Step other) {
|
||||
if (this.to != other.from) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
final Step result = new Step(this.from, other.to);
|
||||
result.count = this.count + other.count;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + from + "->" + to + " (" + count + ")";
|
||||
}
|
||||
|
||||
boolean count(int v) {
|
||||
if (v >= from && v < to) {
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String getTitle() {
|
||||
return "" + from + " ms to " + to + " ms";
|
||||
}
|
||||
}
|
||||
|
||||
private void count(final List<Step> steps, int v) {
|
||||
for (Step s : steps) {
|
||||
if (s.count(v)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean eventuallyMerge(final List<Step> steps, final int lim) {
|
||||
for (int i = 0; i < steps.size() - 1; i++) {
|
||||
final Step s1 = steps.get(i);
|
||||
final Step s2 = steps.get(i + 1);
|
||||
if (s1.count < lim && s2.count < lim) {
|
||||
steps.set(i, s1.mergeWith(s2));
|
||||
steps.remove(i + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
156
src/main/java/net/sourceforge/plantuml/pstat/graph/Curve.java
Normal file
156
src/main/java/net/sourceforge/plantuml/pstat/graph/Curve.java
Normal file
@ -0,0 +1,156 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||
import net.sourceforge.plantuml.pstat.WriterOutputStream;
|
||||
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UEllipse;
|
||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UText;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
|
||||
|
||||
public class Curve {
|
||||
|
||||
static class Data {
|
||||
final String label;
|
||||
final int[] value;
|
||||
|
||||
Data(String label, int[] value) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private final HtmlColor backColor = HtmlColorUtils.getColorIfValid("#AFE0D0");
|
||||
// private final HtmlColor lineColor = HtmlColorUtils.getColorIfValid("DimGray");
|
||||
private final UFont fontLegend;
|
||||
private final List<Data> datas = new ArrayList<Data>();
|
||||
private int max;
|
||||
private final double heightGraph;
|
||||
private final double singleBarWidth;
|
||||
|
||||
public Curve(double height, double singleBarWidth, int fontSize) {
|
||||
this.heightGraph = height;
|
||||
this.singleBarWidth = singleBarWidth;
|
||||
this.fontLegend = new UFont("", Font.BOLD, fontSize);
|
||||
}
|
||||
|
||||
public void addData(String label, int... value) {
|
||||
datas.add(new Data(label, value));
|
||||
for (Data data : datas) {
|
||||
for (int v : data.value) {
|
||||
max = Math.max(max, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void printSvg(Writer writer) throws IOException {
|
||||
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
|
||||
ug = ug.apply(new UChangeColor(backColor));
|
||||
ug = ug.apply(new UChangeBackColor(backColor));
|
||||
|
||||
final double coef = heightGraph / max;
|
||||
|
||||
int step = getRound(max / 10.0);
|
||||
if (step == 0) {
|
||||
step = 1;
|
||||
}
|
||||
final double margeY1 = 10;
|
||||
|
||||
traceInfo(ug, coef, margeY1);
|
||||
printScale(ug.apply(new UTranslate(0, heightGraph + margeY1)), step, coef, datas.size() * singleBarWidth + 30);
|
||||
|
||||
for (int i = 0; i < datas.get(0).value.length; i++) {
|
||||
traceCurve(ug, coef, margeY1, i);
|
||||
}
|
||||
|
||||
OutputStream os = new WriterOutputStream(writer);
|
||||
ug.writeImage(os, null, 96);
|
||||
os.flush();
|
||||
|
||||
}
|
||||
|
||||
private void traceInfo(UGraphic ug, final double coef, final double margeY1) {
|
||||
ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.WHITE)).apply(new UChangeBackColor(HtmlColorUtils.WHITE));
|
||||
for (Data data : datas) {
|
||||
ug.startUrl(new Url("", data.label));
|
||||
ug.apply(new UTranslate(-3, -heightGraph - margeY1)).draw(
|
||||
new URectangle(singleBarWidth, heightGraph + margeY1));
|
||||
ug.closeAction();
|
||||
ug = ug.apply(new UTranslate(singleBarWidth, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private void traceCurve(UGraphic ug, final double coef, final double margeY1, int i) {
|
||||
ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
|
||||
Data lastData = null;
|
||||
for (Data data : datas) {
|
||||
ug.apply(new UTranslate(-3, -(data.value[i] * coef) - 3)).draw(new UEllipse(5, 5));
|
||||
if (lastData != null) {
|
||||
final ULine line = new ULine(-singleBarWidth, (data.value[i] - lastData.value[i]) * coef);
|
||||
ug.apply(new UTranslate(0, -(data.value[i] * coef))).apply(new UStroke(2)).draw(line);
|
||||
}
|
||||
ug = ug.apply(new UTranslate(singleBarWidth, 0));
|
||||
lastData = data;
|
||||
}
|
||||
}
|
||||
|
||||
private int getRound(double value) {
|
||||
final int step = (int) Math.ceil(value / 5.0);
|
||||
return step * 5;
|
||||
}
|
||||
|
||||
private void printScale(UGraphic ug, int step, double coef, double totalWidth) {
|
||||
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
|
||||
final ULine hline = new ULine(totalWidth, 0);
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.GRAY));
|
||||
for (int i = 0; i <= max; i += step) {
|
||||
final double v = i * coef;
|
||||
String label = "" + i;
|
||||
final UText text = new UText(label, fontConfiguration);
|
||||
ug.apply(new UTranslate(0, -v)).draw(text);
|
||||
ug.apply(new UTranslate(10, -v)).apply(new UStroke(2, 2, 1)).draw(hline);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||
import net.sourceforge.plantuml.pstat.WriterOutputStream;
|
||||
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UText;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
|
||||
|
||||
public class HistoList {
|
||||
|
||||
static class Data implements Comparable<Data> {
|
||||
final String label;
|
||||
final int value;
|
||||
|
||||
Data(String label, int value) {
|
||||
this.label = label;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int compareTo(Data other) {
|
||||
return other.value - this.value;
|
||||
}
|
||||
}
|
||||
|
||||
private final HtmlColor backColor = HtmlColorUtils.getColorIfValid("#AFE0D0");
|
||||
// private final HtmlColor lineColor = HtmlColorUtils.getColorIfValid("DimGray");
|
||||
private final UFont fontLegend;
|
||||
private final List<Data> datas = new ArrayList<Data>();
|
||||
private final double graphWidth;
|
||||
private int max = 1;
|
||||
private long sum;
|
||||
private final double singleBarHeight;
|
||||
|
||||
public HistoList(double graphWidth, double singleBarHeight, int fontSize) {
|
||||
this.graphWidth = graphWidth;
|
||||
this.singleBarHeight = singleBarHeight;
|
||||
this.fontLegend = new UFont("", Font.BOLD, fontSize);
|
||||
}
|
||||
|
||||
public void addData(String label, int value) {
|
||||
datas.add(new Data(label, value));
|
||||
max = Math.max(max, value);
|
||||
sum += value;
|
||||
}
|
||||
|
||||
public void printSvg(Writer writer) throws IOException {
|
||||
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
|
||||
// ug = ug.apply(new UTranslate(0, 20));
|
||||
|
||||
ug = ug.apply(new UChangeColor(backColor));
|
||||
ug = ug.apply(new UChangeBackColor(backColor));
|
||||
|
||||
Collections.sort(datas);
|
||||
final double coef = graphWidth / max;
|
||||
|
||||
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
|
||||
for (Data data : datas) {
|
||||
final long pour = data.value * 100L / sum;
|
||||
final String title = "[" + pour + "%] [" + data.value + "/" + sum + "]";
|
||||
|
||||
ug.startUrl(new Url("", title));
|
||||
ug.draw(new URectangle(data.value * coef, singleBarHeight - 4));
|
||||
ug.closeAction();
|
||||
ug.apply(new UTranslate(0, fontLegend.getSize())).draw(new UText(data.label, fontConfiguration));
|
||||
ug = ug.apply(new UTranslate(0, singleBarHeight));
|
||||
|
||||
}
|
||||
|
||||
// final double coef = heightGraph / maxValue();
|
||||
|
||||
// int step = getRound(maxValue() / 10.0);
|
||||
// if (step == 0) {
|
||||
// step = 1;
|
||||
// }
|
||||
// final double margeY1 = 10;
|
||||
//
|
||||
// traceInfo(ug, coef, margeY1);
|
||||
// printScale(ug.apply(new UTranslate(0, heightGraph + margeY1)), step, coef, datas.size() * singleBarWidth +
|
||||
// 30);
|
||||
//
|
||||
// for (int i = 0; i < datas.get(0).value.length; i++) {
|
||||
// traceCurve(ug, coef, margeY1, i);
|
||||
// }
|
||||
|
||||
OutputStream os = new WriterOutputStream(writer);
|
||||
ug.writeImage(os, null, 96);
|
||||
os.flush();
|
||||
|
||||
}
|
||||
// private void traceInfo(UGraphic ug, final double coef, final double margeY1) {
|
||||
// ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
|
||||
// ug = ug.apply(new UChangeColor(HtmlColorUtils.WHITE)).apply(new UChangeBackColor(HtmlColorUtils.WHITE));
|
||||
// for (Data data : datas) {
|
||||
// ug.startUrl(new Url("", data.label));
|
||||
// ug.apply(new UTranslate(-3, -heightGraph - margeY1)).draw(
|
||||
// new URectangle(singleBarWidth, heightGraph + margeY1));
|
||||
// ug.closeAction();
|
||||
// ug = ug.apply(new UTranslate(singleBarWidth, 0));
|
||||
// }
|
||||
// }
|
||||
|
||||
// private void traceCurve(UGraphic ug, final double coef, final double margeY1, int i) {
|
||||
// ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
|
||||
// Data lastData = null;
|
||||
// for (Data data : datas) {
|
||||
// ug.apply(new UTranslate(-3, -(data.value[i] * coef) - 3)).draw(new UEllipse(5, 5));
|
||||
// if (lastData != null) {
|
||||
// final ULine line = new ULine(-singleBarWidth, (data.value[i] - lastData.value[i]) * coef);
|
||||
// ug.apply(new UTranslate(0, -(data.value[i] * coef))).apply(new UStroke(2)).draw(line);
|
||||
// }
|
||||
// ug = ug.apply(new UTranslate(singleBarWidth, 0));
|
||||
// lastData = data;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private int getRound(double value) {
|
||||
// final int step = (int) Math.ceil(value / 5.0);
|
||||
// return step * 5;
|
||||
// }
|
||||
|
||||
// private void printScale(UGraphic ug, int step, double coef, double totalWidth) {
|
||||
// final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
|
||||
// final ULine hline = new ULine(totalWidth, 0);
|
||||
// ug = ug.apply(new UChangeColor(HtmlColorUtils.GRAY));
|
||||
// for (int i = 0; i <= maxValue(); i += step) {
|
||||
// final double v = i * coef;
|
||||
// String label = "" + i;
|
||||
// final UText text = new UText(label, fontConfiguration);
|
||||
// ug.apply(new UTranslate(0, -v)).draw(text);
|
||||
// ug.apply(new UTranslate(10, -v)).apply(new UStroke(2, 2, 1)).draw(hline);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
}
|
@ -0,0 +1,153 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.Url;
|
||||
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColor;
|
||||
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
|
||||
import net.sourceforge.plantuml.pstat.WriterOutputStream;
|
||||
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UChangeColor;
|
||||
import net.sourceforge.plantuml.ugraphic.UFont;
|
||||
import net.sourceforge.plantuml.ugraphic.UGraphic;
|
||||
import net.sourceforge.plantuml.ugraphic.ULine;
|
||||
import net.sourceforge.plantuml.ugraphic.URectangle;
|
||||
import net.sourceforge.plantuml.ugraphic.UStroke;
|
||||
import net.sourceforge.plantuml.ugraphic.UText;
|
||||
import net.sourceforge.plantuml.ugraphic.UTranslate;
|
||||
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
|
||||
|
||||
public class Histogram {
|
||||
|
||||
static class Data {
|
||||
final String label;
|
||||
final String title;
|
||||
final int value;
|
||||
|
||||
Data(String label, String title, int value) {
|
||||
this.label = label;
|
||||
this.title = title;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
private final HtmlColor backColor = HtmlColorUtils.getColorIfValid("#AFE0D0");
|
||||
private final HtmlColor lineColor = HtmlColorUtils.getColorIfValid("DimGray");
|
||||
private final UFont fontLegend;
|
||||
private final List<Data> datas = new ArrayList<Data>();
|
||||
private int max = 1;
|
||||
private final double heightGraph;
|
||||
private final double singleBarWidth;
|
||||
|
||||
public Histogram(double height, double singleBarWidth, int fontSize) {
|
||||
this.heightGraph = height;
|
||||
this.singleBarWidth = singleBarWidth;
|
||||
this.fontLegend = new UFont("", Font.BOLD, fontSize);
|
||||
}
|
||||
|
||||
public void addData(String label, int value, String title) {
|
||||
datas.add(new Data(label, title, value));
|
||||
max = Math.max(max, value);
|
||||
}
|
||||
|
||||
public void printSvg(Writer writer) throws IOException {
|
||||
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
|
||||
ug = ug.apply(new UChangeColor(null));
|
||||
ug = ug.apply(new UChangeBackColor(backColor));
|
||||
|
||||
final double coef = heightGraph / max;
|
||||
|
||||
int step = getRound(max / 10.0);
|
||||
if (step == 0) {
|
||||
step = 1;
|
||||
}
|
||||
final double margeY1 = 10;
|
||||
printScale(ug.apply(new UTranslate(0, heightGraph + margeY1)), step, coef, datas.size() * singleBarWidth + 30);
|
||||
|
||||
final int marginX = 8 + ("" + max).length() * 8;
|
||||
UGraphic ug2 = ug.apply(new UTranslate(marginX, heightGraph + margeY1));
|
||||
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
|
||||
for (Data data : datas) {
|
||||
final double v = data.value * coef;
|
||||
ug2.startUrl(new Url("", data.title));
|
||||
ug2.apply(new UTranslate(0, -v)).draw(new URectangle(singleBarWidth, v));
|
||||
ug2.closeAction();
|
||||
final double textHeight = ug.getStringBounder().calculateDimension(fontLegend, data.label).getHeight();
|
||||
final double textWidth = ug.getStringBounder().calculateDimension(fontLegend, data.label).getWidth();
|
||||
final double xtext = (singleBarWidth - textWidth) / 2;
|
||||
ug2.apply(new UTranslate(xtext, textHeight - 2)).draw(new UText(data.label, fontConfiguration));
|
||||
ug2 = ug2.apply(new UTranslate(singleBarWidth, 0));
|
||||
}
|
||||
|
||||
ug = ug.apply(new UChangeColor(lineColor)).apply(new UStroke(2)).apply(new UChangeBackColor(null));
|
||||
ug2 = ug.apply(new UTranslate(marginX, heightGraph + margeY1));
|
||||
double lastV = 0;
|
||||
for (Data data : datas) {
|
||||
final double v = data.value * coef;
|
||||
drawLine(ug2, 0, -lastV, 0, -v);
|
||||
drawLine(ug2, 0, -v, singleBarWidth, -v);
|
||||
lastV = v;
|
||||
ug2 = ug2.apply(new UTranslate(singleBarWidth, 0));
|
||||
}
|
||||
drawLine(ug2, 0, -lastV, 0, 0);
|
||||
|
||||
OutputStream os = new WriterOutputStream(writer);
|
||||
ug.writeImage(os, null, 96);
|
||||
os.flush();
|
||||
|
||||
}
|
||||
|
||||
private void drawLine(UGraphic ug, double x1, double y1, double x2, double y2) {
|
||||
ug = ug.apply(new UTranslate(x1, y1));
|
||||
ug.draw(new ULine(x2 - x1, y2 - y1));
|
||||
}
|
||||
|
||||
private int getRound(double value) {
|
||||
final int step = (int) Math.ceil(value / 5.0);
|
||||
return NiceNumber.getNicer(step * 5);
|
||||
}
|
||||
|
||||
private void printScale(UGraphic ug, int step, double coef, double totalWidth) {
|
||||
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
|
||||
final ULine hline = new ULine(totalWidth, 0);
|
||||
ug = ug.apply(new UChangeColor(HtmlColorUtils.GRAY));
|
||||
for (int i = 0; i <= max; i += step) {
|
||||
final double v = i * coef;
|
||||
String label = "" + i;
|
||||
final UText text = new UText(label, fontConfiguration);
|
||||
ug.apply(new UTranslate(0, -v)).draw(text);
|
||||
ug.apply(new UTranslate(10, -v)).apply(new UStroke(2, 2, 1)).draw(hline);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.time.DateManager;
|
||||
|
||||
public class HistogramBuilder {
|
||||
|
||||
private final DateManager dateManager;
|
||||
private final int histoSize;
|
||||
private final TreeMap<Integer, MutableInteger> data = new TreeMap<Integer, MutableInteger>();
|
||||
|
||||
public HistogramBuilder(DateManager dateManager, int histoSize) {
|
||||
this.dateManager = dateManager;
|
||||
this.histoSize = histoSize;
|
||||
}
|
||||
|
||||
public Histogram getHistogram(double height, double singleBarWidth, int fontSize) {
|
||||
final Histogram histogram = new Histogram(height, singleBarWidth, fontSize);
|
||||
if (data.size() > 0) {
|
||||
final int last = data.lastKey();
|
||||
for (int i = last - histoSize + 1; i <= last; i++) {
|
||||
final String label = dateManager.getDescriptionShort(i);
|
||||
final MutableInteger n = data.get(i);
|
||||
final int value = n == null ? 0 : n.intValue();
|
||||
final String title = "[" + value + " diagrams] at [" + dateManager.getDescription(i) + "]";
|
||||
histogram.addData(label, value, title);
|
||||
}
|
||||
}
|
||||
return histogram;
|
||||
}
|
||||
|
||||
public void incKey(long time, int value) {
|
||||
final int k = dateManager.toNumber(time);
|
||||
final MutableInteger v = data.get(k);
|
||||
if (v == null) {
|
||||
data.put(k, new MutableInteger(value));
|
||||
} else {
|
||||
v.inc(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
public class MutableInteger {
|
||||
|
||||
private int value;
|
||||
|
||||
public MutableInteger(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void inc(int delta) {
|
||||
value += delta;
|
||||
}
|
||||
|
||||
public int intValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
public class NiceNumber {
|
||||
|
||||
public static int getNicer(final int value) {
|
||||
if (value <= 18) {
|
||||
return value;
|
||||
}
|
||||
if (value < 93) {
|
||||
return ((value + 2) / 5) * 5;
|
||||
}
|
||||
if (value < 100) {
|
||||
return ((value + 5) / 10) * 10;
|
||||
}
|
||||
int m = 1;
|
||||
double head = value;
|
||||
while (head >= 100) {
|
||||
head = head / 10.0;
|
||||
m *= 10;
|
||||
}
|
||||
return getNicer((int) Math.round(head)) * m;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.graph;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class NiceNumberTest extends TestCase {
|
||||
|
||||
public void testGetNicer203() {
|
||||
assertEquals(200, NiceNumber.getNicer(203));
|
||||
assertEquals(1200, NiceNumber.getNicer(1154));
|
||||
}
|
||||
|
||||
public void testGetNicer5249() {
|
||||
assertEquals(5000, NiceNumber.getNicer(5249));
|
||||
assertEquals(5500, NiceNumber.getNicer(5250));
|
||||
}
|
||||
|
||||
public void testGetNicerFull() {
|
||||
assertEquals(-1, NiceNumber.getNicer(-1));
|
||||
assertEquals(1, NiceNumber.getNicer(1));
|
||||
assertEquals(2, NiceNumber.getNicer(2));
|
||||
assertEquals(3, NiceNumber.getNicer(3));
|
||||
assertEquals(4, NiceNumber.getNicer(4));
|
||||
assertEquals(5, NiceNumber.getNicer(5));
|
||||
assertEquals(6, NiceNumber.getNicer(6));
|
||||
assertEquals(7, NiceNumber.getNicer(7));
|
||||
assertEquals(8, NiceNumber.getNicer(8));
|
||||
assertEquals(9, NiceNumber.getNicer(9));
|
||||
assertEquals(10, NiceNumber.getNicer(10));
|
||||
assertEquals(11, NiceNumber.getNicer(11));
|
||||
assertEquals(12, NiceNumber.getNicer(12));
|
||||
assertEquals(13, NiceNumber.getNicer(13));
|
||||
assertEquals(14, NiceNumber.getNicer(14));
|
||||
assertEquals(15, NiceNumber.getNicer(15));
|
||||
assertEquals(16, NiceNumber.getNicer(16));
|
||||
assertEquals(17, NiceNumber.getNicer(17));
|
||||
assertEquals(18, NiceNumber.getNicer(18));
|
||||
assertEquals(20, NiceNumber.getNicer(19));
|
||||
assertEquals(20, NiceNumber.getNicer(20));
|
||||
assertEquals(20, NiceNumber.getNicer(21));
|
||||
assertEquals(20, NiceNumber.getNicer(22));
|
||||
assertEquals(25, NiceNumber.getNicer(23));
|
||||
assertEquals(25, NiceNumber.getNicer(24));
|
||||
assertEquals(25, NiceNumber.getNicer(25));
|
||||
assertEquals(25, NiceNumber.getNicer(26));
|
||||
assertEquals(25, NiceNumber.getNicer(27));
|
||||
assertEquals(30, NiceNumber.getNicer(28));
|
||||
assertEquals(30, NiceNumber.getNicer(29));
|
||||
assertEquals(30, NiceNumber.getNicer(30));
|
||||
assertEquals(80, NiceNumber.getNicer(80));
|
||||
assertEquals(80, NiceNumber.getNicer(81));
|
||||
assertEquals(80, NiceNumber.getNicer(82));
|
||||
assertEquals(85, NiceNumber.getNicer(83));
|
||||
assertEquals(85, NiceNumber.getNicer(84));
|
||||
assertEquals(85, NiceNumber.getNicer(85));
|
||||
assertEquals(85, NiceNumber.getNicer(86));
|
||||
assertEquals(85, NiceNumber.getNicer(87));
|
||||
assertEquals(90, NiceNumber.getNicer(88));
|
||||
assertEquals(90, NiceNumber.getNicer(89));
|
||||
assertEquals(90, NiceNumber.getNicer(90));
|
||||
assertEquals(90, NiceNumber.getNicer(91));
|
||||
assertEquals(90, NiceNumber.getNicer(92));
|
||||
assertEquals(90, NiceNumber.getNicer(93));
|
||||
assertEquals(90, NiceNumber.getNicer(94));
|
||||
assertEquals(100, NiceNumber.getNicer(95));
|
||||
assertEquals(100, NiceNumber.getNicer(96));
|
||||
assertEquals(100, NiceNumber.getNicer(97));
|
||||
assertEquals(100, NiceNumber.getNicer(98));
|
||||
assertEquals(100, NiceNumber.getNicer(99));
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.graph.Chart;
|
||||
import net.sourceforge.plantuml.pstat.graph.ChartProducer;
|
||||
import net.sourceforge.plantuml.pstat.graph.HistogramBuilder;
|
||||
import net.sourceforge.plantuml.pstat.time.DateManager;
|
||||
|
||||
public class CounterSetInteger {
|
||||
|
||||
private final List<Integer> imageGeneration = new ArrayList<Integer>();
|
||||
private final HistogramBuilder builder;
|
||||
|
||||
public HistogramBuilder getHistogramBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public Chart getChartImageGeneration(double height) {
|
||||
return new ChartProducer(imageGeneration).getChart(height);
|
||||
}
|
||||
|
||||
public CounterSetInteger(DateManager dateManager, int histoSize) {
|
||||
builder = new HistogramBuilder(dateManager, histoSize);
|
||||
}
|
||||
|
||||
public void increment(TickImageGeneration tick) {
|
||||
imageGeneration.add(tick.getDuration());
|
||||
builder.incKey(tick.getStartMinute() * 1000L * 60, 1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.graph.Chart;
|
||||
import net.sourceforge.plantuml.pstat.graph.ChartProducer;
|
||||
|
||||
public class CounterSetLoad {
|
||||
|
||||
private final Collection<Integer> pageLoad = new ArrayList<Integer>();
|
||||
private final Collection<Integer> imageLoad = new ArrayList<Integer>();
|
||||
|
||||
public CounterSetLoad() {
|
||||
}
|
||||
|
||||
public void increment(TickBrowser tick) {
|
||||
if (tick.getImageLoad() > 0) {
|
||||
imageLoad.add(tick.getImageLoad());
|
||||
}
|
||||
if (tick.getPageLoad() > 0) {
|
||||
pageLoad.add(tick.getPageLoad());
|
||||
}
|
||||
}
|
||||
|
||||
public Chart getChartPageLoad(double height) {
|
||||
return new ChartProducer(pageLoad).getChart(height);
|
||||
}
|
||||
|
||||
public Chart getChartImageLoad(double height) {
|
||||
return new ChartProducer(imageLoad).getChart(height);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.graph.Chart;
|
||||
import net.sourceforge.plantuml.pstat.graph.HistoList;
|
||||
|
||||
public class CounterSetString {
|
||||
|
||||
private final Map<String, Integer> language = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> host = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> operationSystem = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> browser = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> referer = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> type = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> incomming = new TreeMap<String, Integer>();
|
||||
private final Map<String, Integer> country = new TreeMap<String, Integer>();
|
||||
|
||||
public void increment(TickImageGeneration tick) {
|
||||
increment(language, tick.getAcceptLanguage());
|
||||
increment(host, tick.getHost());
|
||||
increment(operationSystem, tick.getOperatingSystem());
|
||||
increment(browser, tick.getBrowser());
|
||||
increment(referer, tick.getReferer());
|
||||
increment(type, tick.getType());
|
||||
increment(incomming, tick.getIncomming());
|
||||
increment(country, tick.getCountry());
|
||||
}
|
||||
|
||||
private void increment(Map<String, Integer> data, String s) {
|
||||
final Integer v = data.get(s);
|
||||
if (v == null) {
|
||||
data.put(s, 1);
|
||||
} else {
|
||||
data.put(s, v + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return "language.getTitle()";
|
||||
}
|
||||
|
||||
public Chart getChartLanguage(double height) {
|
||||
return getChart(height, language);
|
||||
}
|
||||
|
||||
public Chart getChartHost(double height) {
|
||||
return getChart(height, host);
|
||||
}
|
||||
|
||||
public Chart getChartOperationSystem(double height) {
|
||||
return getChart(height, operationSystem);
|
||||
}
|
||||
|
||||
public Chart getChartBrowser(double height) {
|
||||
return getChart(height, browser);
|
||||
}
|
||||
|
||||
public Chart getChartReferer(double height) {
|
||||
return getChart(height, referer);
|
||||
}
|
||||
|
||||
public Chart getChartType(double height) {
|
||||
return getChart(height, type);
|
||||
}
|
||||
|
||||
public Chart getChartIncomming(double height) {
|
||||
return getChart(height, incomming);
|
||||
}
|
||||
|
||||
private Chart getChart(double height, Map<String, Integer> counter) {
|
||||
final Chart chart = new Chart(height);
|
||||
for (Map.Entry<String, Integer> ent : counter.entrySet()) {
|
||||
final String s = ent.getKey();
|
||||
if ("??".equals(s)) {
|
||||
continue;
|
||||
}
|
||||
chart.addData(s, ent.getValue());
|
||||
}
|
||||
chart.compact();
|
||||
return chart;
|
||||
}
|
||||
|
||||
public Chart getChartRefererOther(double height) {
|
||||
final Chart chart = new Chart(height);
|
||||
for (Map.Entry<String, Integer> ent : referer.entrySet()) {
|
||||
final String s = ent.getKey();
|
||||
if ("??".equals(s) || "http://www.plantuml.com".equals(s) || "http://plantuml.com".equals(s)
|
||||
|| "http://plantuml.sourceforge.net".equals(s) || "Other".equals(s)) {
|
||||
continue;
|
||||
}
|
||||
chart.addData(s, ent.getValue());
|
||||
}
|
||||
chart.removeBig(0.5);
|
||||
return chart;
|
||||
}
|
||||
|
||||
public HistoList getHistoListReferer(double graphWidth, double singleBarHeight, int fontSize) {
|
||||
final HistoList chart = new HistoList(graphWidth, singleBarHeight, fontSize);
|
||||
for (Map.Entry<String, Integer> ent : referer.entrySet()) {
|
||||
final String s = ent.getKey();
|
||||
if ("??".equals(s)) {
|
||||
continue;
|
||||
}
|
||||
chart.addData(s, ent.getValue());
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
public HistoList getHistoListCountry(double graphWidth, double singleBarHeight, int fontSize) {
|
||||
final HistoList chart = new HistoList(graphWidth, singleBarHeight, fontSize);
|
||||
for (Map.Entry<String, Integer> ent : country.entrySet()) {
|
||||
final String s = ent.getKey();
|
||||
if ("??".equals(s)) {
|
||||
continue;
|
||||
}
|
||||
chart.addData(s, ent.getValue());
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
|
||||
|
||||
public class DailyStat {
|
||||
|
||||
private final AtomicInteger size = new AtomicInteger();
|
||||
|
||||
public void updateStats(StatEventImageGeneration ev) {
|
||||
size.incrementAndGet();
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size.intValue();
|
||||
}
|
||||
|
||||
}
|
56
src/main/java/net/sourceforge/plantuml/pstat/tick/Day.java
Normal file
56
src/main/java/net/sourceforge/plantuml/pstat/tick/Day.java
Normal file
@ -0,0 +1,56 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Day {
|
||||
|
||||
private final int nday;
|
||||
|
||||
public Day(long time) {
|
||||
nday = (int) (time / 1000L / 3600 / 24);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return nday;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
final Day other = (Day) o;
|
||||
return nday == other.nday;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new Date(nday * 1000L * 3600 * 24).toGMTString();
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return nday * 1000L * 3600 * 24;
|
||||
}
|
||||
|
||||
}
|
152
src/main/java/net/sourceforge/plantuml/pstat/tick/GraphData.java
Normal file
152
src/main/java/net/sourceforge/plantuml/pstat/tick/GraphData.java
Normal file
@ -0,0 +1,152 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.time.DateManager;
|
||||
|
||||
public class GraphData {
|
||||
|
||||
// private final CounterSet2 days31 = new CounterSet2();
|
||||
private final CounterSetString days15 = new CounterSetString();
|
||||
private final CounterSetString hours48 = new CounterSetString();
|
||||
private final CounterSetString minutes60 = new CounterSetString();
|
||||
private final CounterSetString minutes10 = new CounterSetString();
|
||||
|
||||
private final CounterSetInteger hdays15 = new CounterSetInteger(DateManager.DAILY, 15);
|
||||
private final CounterSetInteger hhours48 = new CounterSetInteger(DateManager.HOURLY, 48);
|
||||
private final CounterSetInteger hminutes60 = new CounterSetInteger(DateManager.MINUTELY, 60);
|
||||
private final CounterSetInteger hminutes10 = new CounterSetInteger(DateManager.MINUTELY, 10);
|
||||
|
||||
private final CounterSetLoad browserDay15 = new CounterSetLoad();
|
||||
private final CounterSetLoad browserHours48 = new CounterSetLoad();
|
||||
private final CounterSetLoad browserMinutes60 = new CounterSetLoad();
|
||||
private final CounterSetLoad browserMinutes10 = new CounterSetLoad();
|
||||
|
||||
public GraphData() {
|
||||
}
|
||||
|
||||
public GraphData(Iterator<TickImageGeneration> iterator, Iterator<TickBrowser> iterator2) {
|
||||
final int now = (int) (System.currentTimeMillis() / 1000L / 60);
|
||||
while (iterator.hasNext()) {
|
||||
final TickImageGeneration tick = iterator.next();
|
||||
final int startMinute = tick.getStartMinute();
|
||||
// if (startMinute >= now - 31 * 24 * 50) {
|
||||
// days31.increment(tick);
|
||||
// } else {
|
||||
// iterator.remove();
|
||||
// }
|
||||
if (startMinute >= now - 15 * 24 * 60) {
|
||||
days15.increment(tick);
|
||||
hdays15.increment(tick);
|
||||
} else {
|
||||
iterator.remove();
|
||||
}
|
||||
if (startMinute >= now - 48 * 60) {
|
||||
hours48.increment(tick);
|
||||
hhours48.increment(tick);
|
||||
}
|
||||
if (startMinute >= now - 60) {
|
||||
minutes60.increment(tick);
|
||||
hminutes60.increment(tick);
|
||||
}
|
||||
if (startMinute >= now - 10) {
|
||||
minutes10.increment(tick);
|
||||
hminutes10.increment(tick);
|
||||
}
|
||||
}
|
||||
while (iterator2.hasNext()) {
|
||||
final TickBrowser tick = iterator2.next();
|
||||
final int startMinute = tick.getStartMinute();
|
||||
if (startMinute >= now - 15 * 24 * 60) {
|
||||
browserDay15.increment(tick);
|
||||
} else {
|
||||
iterator2.remove();
|
||||
}
|
||||
if (startMinute >= now - 24 * 60) {
|
||||
browserHours48.increment(tick);
|
||||
}
|
||||
if (startMinute >= now - 60) {
|
||||
browserMinutes60.increment(tick);
|
||||
}
|
||||
if (startMinute >= now - 10) {
|
||||
browserMinutes10.increment(tick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public final CounterSet2 days31() {
|
||||
// return days31;
|
||||
// }
|
||||
|
||||
public final CounterSetString days15() {
|
||||
return days15;
|
||||
}
|
||||
|
||||
public final CounterSetString hours48() {
|
||||
return hours48;
|
||||
}
|
||||
|
||||
public final CounterSetString minutes60() {
|
||||
return minutes60;
|
||||
}
|
||||
|
||||
public final CounterSetString minutes10() {
|
||||
return minutes10;
|
||||
}
|
||||
|
||||
public final CounterSetInteger hdays15() {
|
||||
return hdays15;
|
||||
}
|
||||
|
||||
public final CounterSetInteger hhours48() {
|
||||
return hhours48;
|
||||
}
|
||||
|
||||
public final CounterSetInteger hminutes60() {
|
||||
return hminutes60;
|
||||
}
|
||||
|
||||
public final CounterSetInteger hminutes10() {
|
||||
return hminutes10;
|
||||
}
|
||||
|
||||
public final CounterSetLoad bdays15() {
|
||||
return browserDay15;
|
||||
}
|
||||
|
||||
public final CounterSetLoad bhours48() {
|
||||
return browserHours48;
|
||||
}
|
||||
|
||||
public final CounterSetLoad bminutes60() {
|
||||
return browserMinutes60;
|
||||
}
|
||||
|
||||
public final CounterSetLoad bminutes10() {
|
||||
return browserMinutes10;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.graph.HistogramBuilder;
|
||||
import net.sourceforge.plantuml.pstat.time.DateManager;
|
||||
|
||||
public class GraphDataLongTerm {
|
||||
|
||||
private final HistogramBuilder builder = new HistogramBuilder(DateManager.MONTHLY, 24);
|
||||
|
||||
public GraphDataLongTerm(Iterator<Entry<Day, DailyStat>> it) {
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<Day, DailyStat> ent = it.next();
|
||||
final Day day = ent.getKey();
|
||||
final DailyStat stat = ent.getValue();
|
||||
builder.incKey(day.getTime(), stat.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
public GraphDataLongTerm() {
|
||||
}
|
||||
|
||||
public HistogramBuilder getHistogramBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.event.StatEvent;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlCreate;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadImage;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadPage;
|
||||
|
||||
public class TickBrowser {
|
||||
|
||||
// private final String token;
|
||||
private int pageLoad = -1;
|
||||
private int imageLoad = -1;
|
||||
private final int startMinute;
|
||||
|
||||
public TickBrowser(StatEvent stat) {
|
||||
startMinute = (int) (stat.getStartServerTime() / 1000L / 60);
|
||||
// if (stat instanceof StatEventHtmlLoadImage) {
|
||||
// final StatEventHtmlLoadImage ev = (StatEventHtmlLoadImage) stat;
|
||||
// // token = ev.getToken();
|
||||
//
|
||||
// } else if (stat instanceof StatEventHtmlLoadPage) {
|
||||
// final StatEventHtmlLoadPage ev = (StatEventHtmlLoadPage) stat;
|
||||
// // token = ev.getToken();
|
||||
//
|
||||
// } else if (stat instanceof StatEventHtmlCreate) {
|
||||
// final StatEventHtmlCreate ev = (StatEventHtmlCreate) stat;
|
||||
// // token = ev.getToken();
|
||||
// } else {
|
||||
// throw new IllegalArgumentException();
|
||||
// }
|
||||
update(stat);
|
||||
|
||||
}
|
||||
|
||||
public void update(StatEvent stat) {
|
||||
if (stat instanceof StatEventHtmlLoadImage) {
|
||||
final StatEventHtmlLoadImage ev = (StatEventHtmlLoadImage) stat;
|
||||
imageLoad = ev.getImageLoad();
|
||||
|
||||
} else if (stat instanceof StatEventHtmlLoadPage) {
|
||||
final StatEventHtmlLoadPage ev = (StatEventHtmlLoadPage) stat;
|
||||
pageLoad = ev.getPageLoad();
|
||||
|
||||
} else if (stat instanceof StatEventHtmlCreate) {
|
||||
final StatEventHtmlCreate ev = (StatEventHtmlCreate) stat;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final int getPageLoad() {
|
||||
return pageLoad;
|
||||
}
|
||||
|
||||
public final int getImageLoad() {
|
||||
return imageLoad;
|
||||
}
|
||||
|
||||
public final int getStartMinute() {
|
||||
return startMinute;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.AbstractCollection;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
class TickCollectionFilterTime extends AbstractCollection<TickImageGeneration> {
|
||||
|
||||
private final Collection<TickImageGeneration> all;
|
||||
private final int timeLimitMinute;
|
||||
|
||||
TickCollectionFilterTime(Collection<TickImageGeneration> all, int timeLimitMinute) {
|
||||
this.all = all;
|
||||
this.timeLimitMinute = timeLimitMinute;
|
||||
}
|
||||
|
||||
public Iterator<TickImageGeneration> iterator() {
|
||||
return new TickFilterIterator(all.iterator(), timeLimitMinute);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.event.StatEvent;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlCreate;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadImage;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadPage;
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
|
||||
|
||||
public class TickDatabase {
|
||||
|
||||
private final LinkedBlockingDeque<TickImageGeneration> all = new LinkedBlockingDeque<TickImageGeneration>();
|
||||
private final ConcurrentHashMap<String, TickBrowser> browser = new ConcurrentHashMap<String, TickBrowser>();
|
||||
private final ConcurrentHashMap<Day, DailyStat> dailyStats = new ConcurrentHashMap<Day, DailyStat>();
|
||||
|
||||
public void updateStats(StatEvent ev) {
|
||||
if (ev instanceof StatEventImageGeneration) {
|
||||
final StatEventImageGeneration ev2 = (StatEventImageGeneration) ev;
|
||||
final TickImageGeneration tick = new TickImageGeneration(ev2);
|
||||
final int duration = tick.getDuration();
|
||||
if (duration > 0) {
|
||||
all.add(tick);
|
||||
}
|
||||
final Day day = new Day(ev2.getStartServerTime());
|
||||
DailyStat dailyStat = dailyStats.get(day);
|
||||
if (dailyStat == null) {
|
||||
dailyStat = new DailyStat();
|
||||
final DailyStat old = dailyStats.putIfAbsent(day, dailyStat);
|
||||
if (old != null) {
|
||||
dailyStat = old;
|
||||
}
|
||||
}
|
||||
dailyStat.updateStats(ev2);
|
||||
} else if (ev instanceof StatEventHtmlLoadImage || ev instanceof StatEventHtmlLoadPage
|
||||
|| ev instanceof StatEventHtmlCreate) {
|
||||
final String token = getToken(ev);
|
||||
TickBrowser tickBrowser = browser.get(token);
|
||||
if (tickBrowser == null) {
|
||||
tickBrowser = new TickBrowser(ev);
|
||||
final TickBrowser old = browser.putIfAbsent(token, tickBrowser);
|
||||
if (old != null) {
|
||||
tickBrowser = old;
|
||||
}
|
||||
}
|
||||
tickBrowser.update(ev);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static private String getToken(StatEvent ev) {
|
||||
if (ev instanceof StatEventHtmlLoadImage) {
|
||||
return ((StatEventHtmlLoadImage) ev).getToken();
|
||||
}
|
||||
if (ev instanceof StatEventHtmlLoadPage) {
|
||||
return ((StatEventHtmlLoadPage) ev).getToken();
|
||||
}
|
||||
if (ev instanceof StatEventHtmlCreate) {
|
||||
return ((StatEventHtmlCreate) ev).getToken();
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public GraphData getGraphData() {
|
||||
return new GraphData(all.iterator(), browser.values().iterator());
|
||||
}
|
||||
|
||||
public GraphDataLongTerm getGraphDataLongTerm() {
|
||||
return new GraphDataLongTerm(dailyStats.entrySet().iterator());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
class TickFilterIterator implements Iterator<TickImageGeneration> {
|
||||
|
||||
private final Iterator<TickImageGeneration> it;
|
||||
private final int timeLimitMinute;
|
||||
private TickImageGeneration potentialNext;
|
||||
|
||||
TickFilterIterator(Iterator<TickImageGeneration> it, int timeLimitMinute) {
|
||||
this.it = it;
|
||||
this.timeLimitMinute = timeLimitMinute;
|
||||
this.potentialNext = getPotentialNext();
|
||||
}
|
||||
|
||||
private TickImageGeneration getPotentialNext() {
|
||||
while (it.hasNext()) {
|
||||
potentialNext = it.next();
|
||||
if (potentialNext.getStartMinute() >= timeLimitMinute) {
|
||||
return potentialNext;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return potentialNext != null;
|
||||
}
|
||||
|
||||
public TickImageGeneration next() {
|
||||
if (potentialNext == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
final TickImageGeneration result = potentialNext;
|
||||
potentialNext = getPotentialNext();
|
||||
return result;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.tick;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
|
||||
|
||||
public class TickImageGeneration {
|
||||
|
||||
private final String country;
|
||||
private final String acceptLanguage;
|
||||
private final String browser;
|
||||
private final String operatingSystem;
|
||||
private final String referer;
|
||||
private final String type;
|
||||
private final String incomming;
|
||||
private final String host;
|
||||
private final int startMinute;
|
||||
private final int duration;
|
||||
|
||||
public TickImageGeneration(StatEventImageGeneration stat) {
|
||||
this.country = stat.getCountry();
|
||||
this.acceptLanguage = stat.getAcceptLanguage();
|
||||
this.browser = stat.getBrowser();
|
||||
this.operatingSystem = stat.getOperatingSystem();
|
||||
this.referer = stat.getReferer();
|
||||
this.incomming = stat.getIncomming();
|
||||
this.host = stat.getHost();
|
||||
this.type = stat.getType();
|
||||
this.startMinute = (int) (stat.getStartServerTime() / 1000L / 60);
|
||||
this.duration = stat.getDuration();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "tick " + new Date(startMinute * 1000L * 60).toGMTString();
|
||||
}
|
||||
|
||||
public final String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public final String getAcceptLanguage() {
|
||||
return acceptLanguage;
|
||||
}
|
||||
|
||||
public final String getBrowser() {
|
||||
return browser;
|
||||
}
|
||||
|
||||
public final String getOperatingSystem() {
|
||||
return operatingSystem;
|
||||
}
|
||||
|
||||
public final String getReferer() {
|
||||
return referer;
|
||||
}
|
||||
|
||||
public final String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public final int getStartMinute() {
|
||||
return startMinute;
|
||||
}
|
||||
|
||||
public final int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public final String getIncomming() {
|
||||
return incomming;
|
||||
}
|
||||
|
||||
public final String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.time;
|
||||
|
||||
public interface DateManager {
|
||||
|
||||
public static final DateManager DAILY = new DateManagerDaily();
|
||||
public static final DateManager HOURLY = new DateManagerHourly();
|
||||
public static final DateManager MINUTELY = new DateManagerMinutely();
|
||||
public static final DateManager MONTHLY = new DateManagerMonthly();
|
||||
public static final DateManager YEARLY = new DateManagerYear();
|
||||
|
||||
public int toNumber(long date);
|
||||
|
||||
public String getDescription(int number);
|
||||
|
||||
public String getDescriptionShort(int number);
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.time;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
class DateManagerDaily implements DateManager {
|
||||
|
||||
private static final long COEF = 1000L * 3600 * 24;
|
||||
|
||||
public int toNumber(long date) {
|
||||
final long m = date / COEF;
|
||||
return (int) m;
|
||||
}
|
||||
|
||||
// private static DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd", Locale.US);
|
||||
// private static DateFormat dfShort = new SimpleDateFormat("dd", Locale.US);
|
||||
|
||||
public String getDescription(int number) {
|
||||
final DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd", Locale.US);
|
||||
final Date date = new Date(number * COEF);
|
||||
return df.format(date);
|
||||
}
|
||||
|
||||
public String getDescriptionShort(int number) {
|
||||
final DateFormat dfShort = new SimpleDateFormat("dd", Locale.US);
|
||||
final Date date = new Date(number * COEF);
|
||||
return dfShort.format(date);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.time;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
class DateManagerHourly implements DateManager {
|
||||
|
||||
private static final long COEF = 1000L * 3600;
|
||||
|
||||
public int toNumber(long date) {
|
||||
final long m = date / COEF;
|
||||
return (int) m;
|
||||
}
|
||||
|
||||
// private static DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:00", Locale.US);
|
||||
// private static DateFormat dfShort = new SimpleDateFormat("HH", Locale.US);
|
||||
|
||||
public String getDescription(int number) {
|
||||
final DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:00", Locale.US);
|
||||
final Date date = new Date(number * COEF);
|
||||
return df.format(date);
|
||||
// return date.toString();
|
||||
}
|
||||
|
||||
public String getDescriptionShort(int number) {
|
||||
final DateFormat dfShort = new SimpleDateFormat("HH", Locale.US);
|
||||
final Date date = new Date(number * COEF);
|
||||
return dfShort.format(date);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.time;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
class DateManagerMinutely implements DateManager {
|
||||
|
||||
private static final long COEF = 1000L * 60;
|
||||
|
||||
public int toNumber(long date) {
|
||||
final long m = date / COEF;
|
||||
return (int) m;
|
||||
}
|
||||
|
||||
// private static DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:mm", Locale.US);
|
||||
// private static DateFormat dfShort = new SimpleDateFormat("mm", Locale.US);
|
||||
|
||||
public String getDescription(int number) {
|
||||
final DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:mm", Locale.US);
|
||||
final Date date = new Date(number * COEF);
|
||||
return df.format(date);
|
||||
// return date.toString();
|
||||
}
|
||||
|
||||
public String getDescriptionShort(int number) {
|
||||
final DateFormat dfShort = new SimpleDateFormat("mm", Locale.US);
|
||||
final Date date = new Date(number * COEF);
|
||||
return dfShort.format(date);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.time;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
class DateManagerMonthly implements DateManager {
|
||||
|
||||
static private final String[] MONTH = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
|
||||
"Nov", "Dec" };
|
||||
|
||||
public int toNumber(long d) {
|
||||
final Date date = new Date(d);
|
||||
return date.getYear() * 12 + date.getMonth();
|
||||
}
|
||||
|
||||
public String getDescription(int number) {
|
||||
final int month = number % 12;
|
||||
final int year = number / 12;
|
||||
return MONTH[month] + " " + (1900 + year);
|
||||
}
|
||||
|
||||
public String getDescriptionShort(int number) {
|
||||
final int month = number % 12;
|
||||
return MONTH[month];
|
||||
// final int month = number % 12;
|
||||
// final int year = number / 12;
|
||||
// return "" + (year - 100) + "/" + String.format("%02d", month + 1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/* ========================================================================
|
||||
* PlantUML : a free UML diagram generator
|
||||
* ========================================================================
|
||||
*
|
||||
* Project Info: http://plantuml.sourceforge.net
|
||||
*
|
||||
* This file is part of PlantUML.
|
||||
*
|
||||
* PlantUML is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* PlantUML distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
package net.sourceforge.plantuml.pstat.time;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
class DateManagerYear implements DateManager {
|
||||
|
||||
public int toNumber(long d) {
|
||||
final Date date = new Date(d);
|
||||
return date.getYear();
|
||||
}
|
||||
|
||||
public String getDescription(int number) {
|
||||
return "Year " + (1900 + number);
|
||||
}
|
||||
|
||||
public String getDescriptionShort(int number) {
|
||||
return "" + (1900 + number);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user