Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* LanguageTool, a natural language style checker
* Copyright (C) 2019 Fabian Richter
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is 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 Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*/
package org.languagetool.server;
import com.google.common.cache.Cache;
import io.prometheus.client.Counter;
import io.prometheus.client.Gauge;
import io.prometheus.client.Histogram;
import io.prometheus.client.Info;
import io.prometheus.client.exporter.HTTPServer;
import io.prometheus.client.guava.cache.CacheMetricsCollector;
import io.prometheus.client.hotspot.DefaultExports;
import org.languagetool.JLanguageTool;
import org.languagetool.Language;
import org.languagetool.Premium;
import java.io.IOException;
import java.util.Objects;
public class ServerMetricsCollector {
public static final String UNKNOWN = "unknown";
public enum RequestErrorType {
QUEUE_FULL,
TOO_MANY_ERRORS,
MAX_CHECK_TIME,
MAX_TEXT_SIZE,
INVALID_REQUEST
}
private static final double[] LATENCY_BUCKETS = {
0.025, 0.05, .1, .25, .5, .75, 1., 2., 4., 6., 8., 10., 15.
};
private static final double[] SIZE_BUCKETS = {
25, 100, 500, 1000, 2500, 5000, 10000, 20000, 40000
};
// buckets for processing speed in chars/s;
private static final double[] SPEED_BUCKETS = {
10, 100, 500, 1000, 2500, 5000, 7500, 10000, 20000, 50000
};
private static final ServerMetricsCollector collector = new ServerMetricsCollector();
private static HTTPServer server;
private final Counter matchCounter = Counter
.build("languagetool_check_matches_total", "Total amount of rule matches")
.labelNames("language", "mode").register();
// TODO: deprecate - replaced by histograms below
private final Counter checkCounter = Counter
.build("languagetool_checks_total", "Total text checks")
.labelNames("language", "mode").register();
private final Counter charactersCounter = Counter
.build("languagetool_characters_total", "Total processed characters")
.labelNames("language", "mode").register();
private final Counter computationTimeCounter = Counter
.build("languagetool_computation_time_seconds_total", "Total computation time, in seconds")
.labelNames("language", "mode").register();
// need to be very careful about cardinality with those
private final Histogram checkLatency = Histogram
.build("languagetool_check_latency_seconds", "Histogram of check times")
.buckets(LATENCY_BUCKETS)
.labelNames("language", "mode").register();
private final Histogram checkSize = Histogram
.build("languagetool_check_size_characters", "Histogram of check sizes")
.buckets(SIZE_BUCKETS).labelNames("language", "mode").register();
private final Histogram checkSpeed = Histogram
.build("languagetool_check_speed_chars_per_second", "Histogram of relative check speed")
.buckets(SPEED_BUCKETS).labelNames("language", "mode").register();
private final Counter requestErrorCounter = Counter
.build("languagetool_request_errors_total", "Various request errors")
.labelNames("reason").register();
// TODO add label for route, method, ...?
private final Counter httpRequestCounter = Counter
.build("languagetool_http_requests_total", "Received HTTP requests").register();
private final Counter httpResponseCounter = Counter
.build("languagetool_http_responses_total", "HTTP responses by code")
.labelNames("code").register();
private final Counter failedHealthcheckCounter = Counter
.build("languagetool_failed_healthchecks_total", "Failed healthchecks").register();
private final Info buildInfo = Info
.build("languagetool_build", "Build information").register();
private final Gauge configValues = Gauge
.build("languagetool_configuration_values", "Configuration settings").labelNames("name").register();
private final CacheMetricsCollector cacheMetrics = new CacheMetricsCollector().register();
public static void init(HTTPServerConfig config) throws IOException {
DefaultExports.initialize();
server = new HTTPServer(config.getPrometheusPort(), true);
Gauge c = getInstance().configValues;
exposeConfigurationValues(config, c);
}
private static void exposeConfigurationValues(HTTPServerConfig config, Gauge c) {
c.labels("maxCheckThreads").set(config.getMaxCheckThreads());
c.labels("maxWorkQueueSize").set(config.getMaxWorkQueueSize());
c.labels("cacheSize").set(config.getCacheSize());
c.labels("cacheTTLSeconds").set(config.getCacheTTLSeconds());
c.labels("maxCheckTimeMillisAnonymous").set(config.getMaxCheckTimeMillisAnonymous());
c.labels("maxCheckTimeMillisLoggedIn").set(config.getMaxCheckTimeMillisLoggedIn());
c.labels("maxCheckTimeMillisPremium").set(config.getMaxCheckTimeMillisPremium());
c.labels("maxTextLengthAnonymous").set(config.getMaxTextLengthAnonymous());
c.labels("maxTextLengthLoggedIn").set(config.getMaxTextLengthLoggedIn());
c.labels("maxTextLengthPremium").set(config.getMaxTextLengthPremium());
}
public static void stop() {
server.stop();
}
public static ServerMetricsCollector getInstance() {
return collector;
}
public ServerMetricsCollector() {
buildInfo.info(
"version", Objects.toString(JLanguageTool.VERSION),
"buildDate", Objects.toString(JLanguageTool.BUILD_DATE),
"revision", Objects.toString(JLanguageTool.GIT_SHORT_ID),
"premium", Objects.toString(String.valueOf(Premium.isPremiumVersion())),
"premiumVersion", Objects.toString(Premium.get().getVersion()),
"premiumBuildDate",Objects.toString(Premium.get().getBuildDate()),
"premiumRevision",Objects.toString(Premium.get().getShortGitId())
);
}
public void monitorCache(String name, Cache cache) {
cacheMetrics.addCache(name, cache);
}
public void logCheck(Language language, long milliseconds, int textSize, int matchCount,
JLanguageTool.Mode mode) {
String langLabel = language != null ? language.getShortCode() : UNKNOWN;
String modeLabel = mode != null ? mode.name() : UNKNOWN;
checkCounter.labels(langLabel, modeLabel).inc();
matchCounter.labels(langLabel, modeLabel).inc(matchCount);
// split metrics: measure latency by language/mode, but not combined
// so we can e.g. notice latency increases in a language or
// create an alert for check speed of ALL_BUT_TEXT_LEVEL_ONLY requests
charactersCounter.labels(langLabel, modeLabel).inc(textSize);
checkSize.labels(langLabel, "").observe(textSize);
checkSize.labels("", modeLabel).observe(textSize);
double seconds = (double) milliseconds / 1000.0;
computationTimeCounter.labels(langLabel, modeLabel).inc(seconds);
checkLatency.labels(langLabel, "").observe(seconds);
checkLatency.labels("", modeLabel).observe(seconds);
double speed = textSize / seconds;
checkSpeed.labels(langLabel, "").observe(speed);
checkSpeed.labels("", modeLabel).observe(speed);
}
public void logRequestError(RequestErrorType type) {
requestErrorCounter.labels(type.name().toLowerCase()).inc();
}
public void logRequest() {
httpRequestCounter.inc();
}
public void logResponse(int httpCode) {
httpResponseCounter.labels(String.valueOf(httpCode)).inc();
}
public void logFailedHealthcheck() {
failedHealthcheckCounter.inc();
}
}