More metrics, metrics renaming
- Add units using heuristics - Scale time unit ms to seconds - Add rate event counters - Add frequency event counters - Add version infos - build.xml cleanups
This commit is contained in:
@ -1,2 +1,11 @@
|
||||
2025-04-xx [0.2]
|
||||
- Add units using heuristics
|
||||
- Scale time unit ms to seconds
|
||||
- Add rate event counters
|
||||
- Add frequency event counters
|
||||
- Add version infos
|
||||
- build.xml cleanups
|
||||
- CSS updates courtesy drzed
|
||||
|
||||
2025-04-09 [0.1]
|
||||
- Initial release
|
||||
|
@ -11,10 +11,11 @@
|
||||
<target name="plugin" depends="war">
|
||||
<!-- get version number -->
|
||||
<buildnumber file="scripts/build.number" />
|
||||
<!-- change version in servlet when you change this -->
|
||||
<!-- change version in PromManager when you change this -->
|
||||
<property name="release.number" value="0.1" />
|
||||
|
||||
<!-- make the update su3 -->
|
||||
<copy file="CHANGES.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="LICENSE.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="README.txt" todir="plugin/" overwrite="true" />
|
||||
<copy file="scripts/plugin.config" todir="plugin/" overwrite="true" />
|
||||
@ -59,6 +60,7 @@
|
||||
</delete>
|
||||
<delete file="plugin/plugin.config" />
|
||||
<delete file="plugin/console/webapps/prometheus.war" />
|
||||
<delete file="plugin/CHANGES.txt" />
|
||||
<delete file="plugin/LICENSE.txt" />
|
||||
<delete file="plugin/README.txt" />
|
||||
<delete file="prometheus.su3" />
|
||||
|
@ -3,13 +3,6 @@
|
||||
<property name="i2pbase" value="../../i2p.i2p"/>
|
||||
<property name="i2plib" value="${i2pbase}/build"/>
|
||||
<property name="jettylib" value="${i2pbase}/apps/jetty/jettylib"/>
|
||||
<path id="cp">
|
||||
<pathelement path="${java.class.path}" />
|
||||
<pathelement location="${i2plib}/i2p.jar" />
|
||||
<pathelement location="${jettylib}/jasper-runtime.jar" />
|
||||
<pathelement location="${jettylib}/javax.servlet.jar" />
|
||||
<pathelement location="${jettylib}/jetty-util.jar" />
|
||||
</path>
|
||||
|
||||
<target name="all" depends="clean, build" />
|
||||
<target name="build" depends="war" />
|
||||
@ -43,7 +36,7 @@
|
||||
debug="true" deprecation="on" source="${javac.version}" target="${javac.version}"
|
||||
destdir="./build/obj"
|
||||
includeAntRuntime="false"
|
||||
classpath="${i2plib}/i2p.jar:${jettylib}/javax.servlet.jar:build/prometheus.jar" >
|
||||
classpath="${i2plib}/i2p.jar:${i2plib}/router.jar:${jettylib}/javax.servlet.jar:build/prometheus.jar" >
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
</javac>
|
||||
</target>
|
||||
|
@ -15,18 +15,25 @@ package net.i2p.prometheus;
|
||||
*/
|
||||
|
||||
import java.net.Socket;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
|
||||
import io.prometheus.metrics.core.metrics.CounterWithCallback;
|
||||
import io.prometheus.metrics.core.metrics.GaugeWithCallback;
|
||||
import io.prometheus.metrics.core.metrics.Info;
|
||||
import io.prometheus.metrics.instrumentation.jvm.JvmMetrics;
|
||||
import io.prometheus.metrics.model.snapshots.Unit;
|
||||
import io.prometheus.metrics.model.registry.PrometheusRegistry;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.*;
|
||||
import static net.i2p.app.ClientAppState.*;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.router.RouterVersion;
|
||||
import net.i2p.stat.Frequency;
|
||||
import net.i2p.stat.FrequencyStat;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.stat.StatManager;
|
||||
@ -44,6 +51,8 @@ public class PromManager implements ClientApp {
|
||||
|
||||
private ClientAppState _state = UNINITIALIZED;
|
||||
|
||||
public static final String VERSION = "0.1";
|
||||
|
||||
public PromManager(I2PAppContext ctx, ClientAppManager mgr, String args[]) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(PromManager.class);
|
||||
@ -62,7 +71,7 @@ public class PromManager implements ClientApp {
|
||||
}
|
||||
|
||||
/**
|
||||
* This adds the stats present at plugin startup.
|
||||
* This adds the rate and frequency stats present at plugin startup.
|
||||
* TODO: add a monitor to add stats that appear later.
|
||||
*/
|
||||
private void addStats() {
|
||||
@ -74,18 +83,28 @@ public class PromManager implements ClientApp {
|
||||
String pfx = "i2p.";
|
||||
for (String s : e.getValue()) {
|
||||
RateStat rs = sm.getRate(s);
|
||||
if (rs == null)
|
||||
continue;
|
||||
String desc = rs.getDescription();
|
||||
if (desc == null)
|
||||
desc = "";
|
||||
long[] pers = rs.getPeriods();
|
||||
final long per = pers[0];
|
||||
final Rate rate = rs.getRate(per);
|
||||
if (rate == null)
|
||||
continue;
|
||||
FrequencyStat fs = null;
|
||||
Rate rate = null;
|
||||
long per = 0;
|
||||
String desc;
|
||||
|
||||
String name = pfx + s + '.' + DataHelper.formatDuration(per);
|
||||
if (rs != null) {
|
||||
desc = rs.getDescription();
|
||||
if (desc == null)
|
||||
desc = "";
|
||||
long[] pers = rs.getPeriods();
|
||||
per = pers[0];
|
||||
rate = rs.getRate(per);
|
||||
if (rate == null)
|
||||
continue;
|
||||
} else {
|
||||
fs = _context.statManager().getFrequency(s);
|
||||
if (fs == null)
|
||||
continue;
|
||||
desc = fs.getDescription();
|
||||
}
|
||||
|
||||
String name = pfx + s;
|
||||
name = name.replace(".", "_");
|
||||
name = name.replace("-", "_");
|
||||
// https://prometheus.io/docs/concepts/data_model/#metric-names-and-labels
|
||||
@ -96,17 +115,16 @@ public class PromManager implements ClientApp {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("adding gauge " + name);
|
||||
|
||||
GaugeWithCallback.builder()
|
||||
.name(name)
|
||||
.help(desc)
|
||||
.labelNames("state")
|
||||
.callback(callback -> {
|
||||
callback.call(rate.getAvgOrLifetimeAvg(), "average");
|
||||
})
|
||||
.register();
|
||||
if (rate != null) {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("adding gauge " + name);
|
||||
if (addStat(rate, per, name, desc))
|
||||
n++;
|
||||
} else {
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("adding counter " + name);
|
||||
addFreq(fs, name, desc);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@ -115,6 +133,88 @@ public class PromManager implements ClientApp {
|
||||
_log.info(n + " PromManager I2P metrics registered");
|
||||
}
|
||||
|
||||
/**
|
||||
* This adds a single stat.
|
||||
* It adds bytes or seconds units based on some heuristics.
|
||||
* If the units cannot be determined, it also adds an event counter.
|
||||
* @return true if we added an event counter also.
|
||||
*/
|
||||
private static boolean addStat(final Rate rate, long period, String name, String desc) {
|
||||
boolean rv = false;
|
||||
GaugeWithCallback.Builder gwcb = GaugeWithCallback.builder()
|
||||
.help(desc)
|
||||
.labelNames("state");
|
||||
// heuristics
|
||||
String nlc = name.toLowerCase(Locale.US);
|
||||
if (nlc.contains("time") || nlc.contains("delay") || nlc.contains("lag")) {
|
||||
// All our stats are in ms
|
||||
gwcb.unit(Unit.SECONDS)
|
||||
.callback(callback -> {
|
||||
callback.call(rate.getAvgOrLifetimeAvg() / 1000, "average");
|
||||
});
|
||||
} else if (nlc.contains("size") || nlc.contains("memory") ||
|
||||
nlc.contains("bps") || nlc.contains("bandwidth")) {
|
||||
gwcb.unit(Unit.BYTES)
|
||||
.callback(callback -> {
|
||||
callback.call(rate.getAvgOrLifetimeAvg(), "average");
|
||||
});
|
||||
} else {
|
||||
gwcb.callback(callback -> {
|
||||
callback.call(rate.getAvgOrLifetimeAvg(), "average");
|
||||
});
|
||||
// events
|
||||
// Add a _count unit
|
||||
// Prometheus adds _total
|
||||
CounterWithCallback.builder()
|
||||
.name(name + "_count")
|
||||
.help(desc)
|
||||
.callback(callback -> {
|
||||
callback.call(rate.getLifetimeEventCount());
|
||||
})
|
||||
.register();
|
||||
rv = true;
|
||||
}
|
||||
name += '_' + DataHelper.formatDuration(period);
|
||||
gwcb.name(name)
|
||||
.register();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* This adds a single counter.
|
||||
*/
|
||||
private static void addFreq(final FrequencyStat fs, String name, String desc) {
|
||||
// Add a _count unit
|
||||
// Prometheus adds _total
|
||||
CounterWithCallback.builder()
|
||||
.name(name + "_count")
|
||||
.help(desc)
|
||||
.callback(callback -> {
|
||||
callback.call(fs.getEventCount());
|
||||
})
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some constant "Info" metrics
|
||||
*/
|
||||
private static void addInfos() {
|
||||
addInfo("i2p_info", "I2P info", "version", RouterVersion.FULL_VERSION);
|
||||
addInfo("i2p_plugin_info", "I2P Plugin Info", "version", VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some constant "Info" metrics
|
||||
*/
|
||||
private static void addInfo(String name, String help, String label, String value) {
|
||||
Info.builder()
|
||||
.name(name)
|
||||
.help(help)
|
||||
.labelNames(label)
|
||||
.register()
|
||||
.addLabelValues(value);
|
||||
}
|
||||
|
||||
|
||||
/////// ClientApp methods
|
||||
|
||||
@ -130,6 +230,7 @@ public class PromManager implements ClientApp {
|
||||
_log.info(jvmCount + " PromManager JVM metrics registered");
|
||||
|
||||
addStats();
|
||||
addInfos();
|
||||
changeState(RUNNING);
|
||||
_mgr.register(this);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public class PrometheusServlet extends BasicServlet {
|
||||
// for now, use console bundle, hope to pick up a few translations for free
|
||||
private static final String BUNDLE = "net.i2p.router.web.messages";
|
||||
private static final String RESOURCES = "/prometheus/resources/";
|
||||
private static final String VERSION = "0.1";
|
||||
private static final String VERSION = PromManager.VERSION;
|
||||
|
||||
public PrometheusServlet() {
|
||||
super();
|
||||
@ -212,7 +212,7 @@ public class PrometheusServlet extends BasicServlet {
|
||||
buf.append("<p>Full stats are enabled.</p>\n");
|
||||
else
|
||||
buf.append("<p>For more metrics, <a href=\"/configstats\">enable full stats</a> and restart.</p>\n");
|
||||
buf.append("<p>Prometheus server configuration - add to /etc/prometheus/prometheus.yml:</p>\n");
|
||||
buf.append("<p>Prometheus server configuration: add to <code>/etc/prometheus/prometheus.yml</code>:</p>\n");
|
||||
int port = _context.portMapper().getPort(PortMapper.SVC_CONSOLE);
|
||||
if (port <= 0)
|
||||
port = 7657;
|
||||
@ -223,9 +223,9 @@ public class PrometheusServlet extends BasicServlet {
|
||||
" static_configs:\n" +
|
||||
" - targets: ['localhost:").append(port).append("']\n" +
|
||||
"</pre>\n");
|
||||
buf.append("<p>For password-protected or SSL consoles, see the file <tt>")
|
||||
buf.append("<p>For password-protected or SSL consoles, see the file <code>")
|
||||
.append(_context.getConfigDir())
|
||||
.append("/plugins/prometheus/README.txt</tt> for instructions.</p>\n");
|
||||
.append("/plugins/prometheus/README.txt</code> for instructions.</p>\n");
|
||||
buf.append("</div>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
Reference in New Issue
Block a user