mirror of
https://github.com/OpenLiberty/liberty-bikes.git
synced 2025-01-18 10:23:58 +08:00
Enable MP Metrics and add some application specific metrics
This commit is contained in:
parent
823c3b8dca
commit
c5b0f505a8
@ -18,6 +18,8 @@ import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.eclipse.microprofile.metrics.annotation.Counted;
|
||||
import org.libertybikes.auth.service.ConfigBean;
|
||||
import org.libertybikes.auth.service.JwtAuth;
|
||||
import org.libertybikes.auth.service.github.GitHubOAuthAPI.GithubTokenResponse;
|
||||
@ -50,6 +52,12 @@ public class GitHubCallback extends JwtAuth {
|
||||
}
|
||||
|
||||
@GET
|
||||
@Counted(unit = MetricUnits.NONE,
|
||||
name = "num_github_logins",
|
||||
monotonic = true,
|
||||
displayName = "Number of Github Logins",
|
||||
description = "Metrics to show how many times a user has logged in through Github Auth.",
|
||||
absolute = true)
|
||||
public Response getGitHubCallbackURL(@Context HttpServletRequest request) throws URISyntaxException {
|
||||
try {
|
||||
String githubCode = request.getParameter("code");
|
||||
|
@ -18,6 +18,8 @@ import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.eclipse.microprofile.metrics.annotation.Counted;
|
||||
import org.libertybikes.auth.service.ConfigBean;
|
||||
import org.libertybikes.auth.service.JwtAuth;
|
||||
|
||||
@ -85,6 +87,12 @@ public class GoogleCallback extends JwtAuth {
|
||||
}
|
||||
|
||||
@GET
|
||||
@Counted(unit = MetricUnits.NONE,
|
||||
name = "num_google_logins",
|
||||
monotonic = true,
|
||||
displayName = "Number of Google Logins",
|
||||
description = "Metrics to show how many times a user has logged in through Google Auth.",
|
||||
absolute = true)
|
||||
public Response getGoogleAuthURL(@Context HttpServletRequest request) throws IOException, URISyntaxException {
|
||||
// google calls us back at this app when a user has finished authing with them.
|
||||
// when it calls us back here, it passes an oauth_verifier token that we
|
||||
|
@ -13,6 +13,8 @@ import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.eclipse.microprofile.metrics.annotation.Counted;
|
||||
import org.libertybikes.auth.service.ConfigBean;
|
||||
import org.libertybikes.auth.service.JwtAuth;
|
||||
|
||||
@ -31,6 +33,12 @@ public class TwitterCallback extends JwtAuth {
|
||||
ConfigBean config;
|
||||
|
||||
@GET
|
||||
@Counted(unit = MetricUnits.NONE,
|
||||
name = "num_twitter_logins",
|
||||
monotonic = true,
|
||||
displayName = "Number of Twitter Logins",
|
||||
description = "Metrics to show how many times a user has logged in through Twitter Auth.",
|
||||
absolute = true)
|
||||
public Response getTwitterCallbackURL(@Context HttpServletRequest request) throws URISyntaxException {
|
||||
try {
|
||||
Twitter twitter = (Twitter) request.getSession().getAttribute("twitter");
|
||||
|
@ -10,7 +10,10 @@
|
||||
<feature>mpJwt-1.0</feature>
|
||||
<feature>mpRestClient-1.0</feature>
|
||||
<feature>mpOpenAPI-1.0</feature>
|
||||
<feature>mpMetrics-1.1</feature>
|
||||
</featureManager>
|
||||
|
||||
<mpMetrics authentication="false"/>
|
||||
|
||||
<httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="${httpPort}" httpsPort="${httpsPort}" />
|
||||
|
||||
|
@ -186,7 +186,7 @@ public class GameBoard {
|
||||
|
||||
public void broadcastToAI() {
|
||||
for (Player p : players) {
|
||||
if (p.isAlive()) {
|
||||
if (p.isAlive() && !p.isRealPlayer()) {
|
||||
short[][] boardCopy = board.clone();
|
||||
p.processAIMove(boardCopy);
|
||||
}
|
||||
|
@ -32,6 +32,11 @@ import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.websocket.Session;
|
||||
|
||||
import org.eclipse.microprofile.metrics.Metadata;
|
||||
import org.eclipse.microprofile.metrics.MetricRegistry;
|
||||
import org.eclipse.microprofile.metrics.MetricType;
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.eclipse.microprofile.metrics.Timer.Context;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.libertybikes.game.core.Player.STATUS;
|
||||
import org.libertybikes.restclient.PlayerService;
|
||||
@ -87,6 +92,57 @@ public class GameRound implements Runnable {
|
||||
|
||||
String keyStoreAlias;
|
||||
|
||||
// MpMetric Metadatas
|
||||
private Metadata currentRoundsCounter = new Metadata("current_num_of_rounds", // name
|
||||
"Current Number of Rounds", // display name
|
||||
"Number of rounds currently running", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
private Metadata totalRoundsCounter = new Metadata("total_num_of_rounds", // name
|
||||
"Total Number of Rounds", // display name
|
||||
"Number of rounds that have been created", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
private Metadata currentPlayersCounter = new Metadata("current_num_of_players", // name
|
||||
"Current Number of Players", // display name
|
||||
"Number of players that are currently playing in a round", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
private Metadata totalPlayersCounter = new Metadata("total_num_of_players", // name
|
||||
"Total Number of Players That Have Played", // display name
|
||||
"Number of players that have played in a round, requeuing and replaying increases the count", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
private Metadata totalMobilePlayersCounter = new Metadata("total_num_of_mobile_players", // name
|
||||
"Total Number of Mobile Players That Have Played", // display name
|
||||
"Number of mobile players that have played in a round, requeuing and replaying increases the count", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
Metadata gameRoundTimerMetadata = new Metadata("game_round_timer", // name
|
||||
"Game Round Timer", // display name
|
||||
"The Time Game Rounds Last", // description
|
||||
MetricType.TIMER, // type
|
||||
MetricUnits.SECONDS); // units
|
||||
|
||||
private static MetricRegistry registry;
|
||||
private Context timerContext;
|
||||
|
||||
@JsonbTransient
|
||||
private static MetricRegistry getRegistry() {
|
||||
try {
|
||||
return registry == null ? registry = CDI.current().select(MetricRegistry.class).get() : registry;
|
||||
} catch (IllegalStateException ise) {
|
||||
System.out.println("WARNING: Unable to locate CDIProvider");
|
||||
ise.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get a string of 4 random uppercase letters (A-Z)
|
||||
private static String getRandomId() {
|
||||
char[] chars = new char[4];
|
||||
@ -120,6 +176,13 @@ public class GameRound implements Runnable {
|
||||
log("Unable to perform JNDI lookup to determine time between rounds, using default value");
|
||||
}
|
||||
MAX_TIME_BETWEEN_ROUNDS = (maxTimeBetweenRounds < 5 || maxTimeBetweenRounds > 60) ? MAX_TIME_BETWEEN_ROUNDS_DEFAULT : maxTimeBetweenRounds;
|
||||
|
||||
// Increment round counter metrics
|
||||
MetricRegistry registry = getRegistry();
|
||||
if (registry != null) {
|
||||
registry.counter(totalRoundsCounter).inc();
|
||||
registry.counter(currentRoundsCounter).inc();
|
||||
}
|
||||
}
|
||||
|
||||
public GameBoard getBoard() {
|
||||
@ -172,6 +235,14 @@ public class GameRound implements Runnable {
|
||||
isPhone = c.isPhone = hasGameBoard ? false : true;
|
||||
clients.put(s, c);
|
||||
log("Player " + playerId + " has joined.");
|
||||
|
||||
// Increment player counter metrics
|
||||
getRegistry().counter(currentPlayersCounter).inc();
|
||||
getRegistry().counter(totalPlayersCounter).inc();
|
||||
if (isPhone) {
|
||||
getRegistry().counter(totalMobilePlayersCounter).inc();
|
||||
}
|
||||
|
||||
} else {
|
||||
log("Player " + playerId + " already exists.");
|
||||
}
|
||||
@ -228,7 +299,7 @@ public class GameRound implements Runnable {
|
||||
return c != null && c.player.isPresent();
|
||||
}
|
||||
|
||||
private void removePlayer(Player p) {
|
||||
private void removePlayer(Player p, boolean isMobile) {
|
||||
p.disconnect();
|
||||
log(p.name + " disconnected.");
|
||||
|
||||
@ -239,18 +310,29 @@ public class GameRound implements Runnable {
|
||||
|
||||
if (isOpen()) {
|
||||
board.removePlayer(p);
|
||||
|
||||
// Decrement player counters because they didn't play
|
||||
getRegistry().counter(totalPlayersCounter).dec();
|
||||
if (isMobile) {
|
||||
getRegistry().counter(totalMobilePlayersCounter).dec();
|
||||
}
|
||||
|
||||
} else if (gameState == State.RUNNING) {
|
||||
checkForWinner();
|
||||
}
|
||||
|
||||
if (gameState != State.FINISHED)
|
||||
broadcastPlayerList();
|
||||
|
||||
// Decrement current players counter
|
||||
getRegistry().counter(currentPlayersCounter).dec();
|
||||
}
|
||||
|
||||
public int removeClient(Session client) {
|
||||
Client c = clients.remove(client);
|
||||
if (c != null && c.player.isPresent())
|
||||
removePlayer(c.player.get());
|
||||
if (c != null && c.player.isPresent()) {
|
||||
removePlayer(c.player.get(), c.isPhone);
|
||||
}
|
||||
return clients.size();
|
||||
}
|
||||
|
||||
@ -263,6 +345,7 @@ public class GameRound implements Runnable {
|
||||
public void run() {
|
||||
gameRunning.set(true);
|
||||
log(">>> Starting round");
|
||||
|
||||
ticksFromGameEnd = 0;
|
||||
int numGames = runningGames.incrementAndGet();
|
||||
if (numGames > 3)
|
||||
@ -484,7 +567,13 @@ public class GameRound implements Runnable {
|
||||
|
||||
private void endGame() {
|
||||
runningGames.decrementAndGet();
|
||||
|
||||
log("<<< Finished round");
|
||||
|
||||
// Decrement current rounds counter and close round timer
|
||||
getRegistry().counter(currentRoundsCounter).dec();
|
||||
timerContext.close();
|
||||
|
||||
broadcastPlayerList();
|
||||
|
||||
ManagedScheduledExecutorService exec = executor();
|
||||
@ -544,6 +633,10 @@ public class GameRound implements Runnable {
|
||||
executor().submit(GameRound.this);
|
||||
}
|
||||
gameState = State.RUNNING;
|
||||
|
||||
// Start round timer metric
|
||||
timerContext = getRegistry().timer(gameRoundTimerMetadata).time();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,20 @@ package org.libertybikes.game.party;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.enterprise.context.Dependent;
|
||||
import javax.inject.Inject;
|
||||
import javax.json.bind.annotation.JsonbTransient;
|
||||
import javax.ws.rs.sse.Sse;
|
||||
import javax.ws.rs.sse.SseEventSink;
|
||||
|
||||
import org.eclipse.microprofile.metrics.Counter;
|
||||
import org.eclipse.microprofile.metrics.Metadata;
|
||||
import org.eclipse.microprofile.metrics.MetricRegistry;
|
||||
import org.eclipse.microprofile.metrics.MetricType;
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.eclipse.microprofile.metrics.annotation.Counted;
|
||||
import org.libertybikes.game.core.GameRound;
|
||||
import org.libertybikes.game.core.GameRound.LifecycleCallback;
|
||||
import org.libertybikes.game.round.service.GameRoundService;
|
||||
@ -27,7 +35,34 @@ public class Party {
|
||||
private final PartyQueue queue = new PartyQueue(this);
|
||||
private volatile GameRound currentRound;
|
||||
|
||||
Metadata currentPartiesCounterMetadata = new Metadata("current_number_of_parties", // name
|
||||
"Current Number of Parties", // display name
|
||||
"Number of parties currently running", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
@Inject
|
||||
private MetricRegistry registry;
|
||||
|
||||
private Counter currentPartiesCounter;
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
currentPartiesCounter = registry.counter(currentPartiesCounterMetadata);
|
||||
currentPartiesCounter.inc();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void preDestroy() {
|
||||
currentPartiesCounter.dec();
|
||||
}
|
||||
|
||||
@Inject
|
||||
@Counted(unit = MetricUnits.NONE,
|
||||
name = "number_of_parties",
|
||||
monotonic = true,
|
||||
description = "Total Number of Parties",
|
||||
absolute = true)
|
||||
public Party() {
|
||||
this(getRandomPartyID());
|
||||
}
|
||||
|
@ -3,11 +3,16 @@ package org.libertybikes.game.party;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
import javax.enterprise.inject.spi.CDI;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.sse.OutboundSseEvent;
|
||||
import javax.ws.rs.sse.Sse;
|
||||
import javax.ws.rs.sse.SseEventSink;
|
||||
|
||||
import org.eclipse.microprofile.metrics.Metadata;
|
||||
import org.eclipse.microprofile.metrics.MetricRegistry;
|
||||
import org.eclipse.microprofile.metrics.MetricType;
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.libertybikes.game.core.GameRound;
|
||||
import org.libertybikes.game.core.OutboundMessage;
|
||||
import org.libertybikes.game.core.Player;
|
||||
@ -17,6 +22,18 @@ public class PartyQueue {
|
||||
private final ConcurrentLinkedDeque<QueuedClient> waitingPlayers = new ConcurrentLinkedDeque<>();
|
||||
private final Party party;
|
||||
|
||||
private Metadata currentPlayersCounter = new Metadata("current_num_of_players_in_queue", // name
|
||||
"Current Number of Players Waiting In A Queue", // display name
|
||||
"Number of players that are currently waiting in a queue", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
private MetricRegistry registry;
|
||||
|
||||
private MetricRegistry getRegistry() {
|
||||
return registry == null ? registry = CDI.current().select(MetricRegistry.class).get() : registry;
|
||||
}
|
||||
|
||||
public PartyQueue(Party p) {
|
||||
this.party = p;
|
||||
}
|
||||
@ -26,9 +43,12 @@ public class PartyQueue {
|
||||
// If this client was already in the queue, remove them and add them at the end
|
||||
if (waitingPlayers.removeFirstOccurrence(client)) {
|
||||
party.log("Removed client " + playerId + " from queue before adding at end");
|
||||
getRegistry().counter(currentPlayersCounter).dec();
|
||||
}
|
||||
party.log("Adding client " + playerId + " into the queue in position " + client.queuePosition());
|
||||
waitingPlayers.add(client);
|
||||
|
||||
getRegistry().counter(currentPlayersCounter).inc();
|
||||
if (party.getCurrentRound().isOpen())
|
||||
promoteClients();
|
||||
else
|
||||
@ -42,6 +62,7 @@ public class PartyQueue {
|
||||
QueuedClient first = waitingPlayers.pollFirst();
|
||||
if (first != null) {
|
||||
first.promoteToGame(newRound.id);
|
||||
getRegistry().counter(currentPlayersCounter).dec();
|
||||
}
|
||||
}
|
||||
for (QueuedClient client : waitingPlayers)
|
||||
@ -51,8 +72,10 @@ public class PartyQueue {
|
||||
public void close() {
|
||||
party.log("Closing party queue");
|
||||
QueuedClient client = null;
|
||||
while ((client = waitingPlayers.pollFirst()) != null)
|
||||
while ((client = waitingPlayers.pollFirst()) != null) {
|
||||
client.close();
|
||||
getRegistry().counter(currentPlayersCounter).dec();
|
||||
}
|
||||
}
|
||||
|
||||
private class QueuedClient {
|
||||
|
@ -48,14 +48,17 @@ public class GameRoundService {
|
||||
|
||||
@POST
|
||||
public GameRound createRoundById(@QueryParam("gameId") String gameId) {
|
||||
if (allRounds.containsKey(gameId)) {
|
||||
System.out.println("Round " + gameId + " already exists, returning it");
|
||||
return allRounds.get(gameId);
|
||||
}
|
||||
GameRound newRound = new GameRound(gameId);
|
||||
GameRound existingRound = allRounds.putIfAbsent(gameId, newRound);
|
||||
GameRound round = existingRound == null ? newRound : existingRound;
|
||||
System.out.println("Created round id=" + round.id);
|
||||
allRounds.put(gameId, newRound);
|
||||
System.out.println("Created round id=" + newRound.id);
|
||||
if (allRounds.size() > 5)
|
||||
System.out.println("WARNING: Found " + allRounds.size() + " active games in GameRoundService. " +
|
||||
"They are probably not being cleaned up properly: " + allRounds.keySet());
|
||||
return round;
|
||||
return newRound;
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -18,6 +18,12 @@ import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
|
||||
import org.eclipse.microprofile.faulttolerance.Retry;
|
||||
import org.eclipse.microprofile.metrics.Metadata;
|
||||
import org.eclipse.microprofile.metrics.MetricRegistry;
|
||||
import org.eclipse.microprofile.metrics.MetricType;
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.eclipse.microprofile.metrics.Timer.Context;
|
||||
import org.eclipse.microprofile.metrics.annotation.Metered;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.libertybikes.game.core.GameRound;
|
||||
import org.libertybikes.game.core.GameRound.State;
|
||||
@ -39,14 +45,28 @@ public class GameRoundWebsocket {
|
||||
|
||||
private final static Jsonb jsonb = JsonbBuilder.create();
|
||||
|
||||
@Inject
|
||||
private MetricRegistry registry;
|
||||
|
||||
private Context timerContext;
|
||||
|
||||
Metadata openWebsocketTimerMetadata = new Metadata("open_game_websocket_timer", // name
|
||||
"Open Game Round Websocket Timer", // display name
|
||||
"The Time Game Round Websockets Are Open", // description
|
||||
MetricType.TIMER, // type
|
||||
MetricUnits.SECONDS); // units
|
||||
|
||||
@OnOpen
|
||||
public void onOpen(@PathParam("roundId") String roundId, Session session) {
|
||||
log(roundId, "Opened a session");
|
||||
timerContext = registry.timer(openWebsocketTimerMetadata).time();
|
||||
}
|
||||
|
||||
@OnClose
|
||||
public void onClose(@PathParam("roundId") String roundId, Session session) {
|
||||
log(roundId, "Closed a session");
|
||||
timerContext.close();
|
||||
|
||||
try {
|
||||
GameRound round = gameSvc.getRound(roundId);
|
||||
if (round != null)
|
||||
@ -58,6 +78,10 @@ public class GameRoundWebsocket {
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
@Metered(name = "rate_of_websocket_calls",
|
||||
displayName = "Rate of GameRound Websocket Calls",
|
||||
description = "Rate of incoming messages to the game round websocket",
|
||||
absolute = true)
|
||||
public void onMessage(@PathParam("roundId") final String roundId, String message, Session session) {
|
||||
try {
|
||||
final InboundMessage msg = jsonb.fromJson(message, InboundMessage.class);
|
||||
|
@ -11,7 +11,12 @@
|
||||
<feature>mpRestClient-1.1</feature>
|
||||
<feature>mpOpenAPI-1.0</feature>
|
||||
<feature>websocket-1.1</feature>
|
||||
<feature>mpMetrics-1.1</feature>
|
||||
</featureManager>
|
||||
|
||||
<mpMetrics authentication="false"/>
|
||||
|
||||
<logging traceSpecification="com.ibm.ws.microprofile.metrics*=all"/>
|
||||
|
||||
<httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="${httpPort}" httpsPort="${httpsPort}" />
|
||||
|
||||
|
@ -14,6 +14,10 @@ import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||
import org.eclipse.microprofile.metrics.Metadata;
|
||||
import org.eclipse.microprofile.metrics.MetricRegistry;
|
||||
import org.eclipse.microprofile.metrics.MetricType;
|
||||
import org.eclipse.microprofile.metrics.MetricUnits;
|
||||
import org.libertybikes.player.data.PlayerDB;
|
||||
|
||||
@Path("/player")
|
||||
@ -32,6 +36,15 @@ public class PlayerService {
|
||||
return db.getAll();
|
||||
}
|
||||
|
||||
@Inject
|
||||
private MetricRegistry registry;
|
||||
|
||||
private Metadata numLoginsCounter = new Metadata("num_player_logins", // name
|
||||
"Number of Total Logins", // display name
|
||||
"Metrics to show how many times a user has logged in.", // description
|
||||
MetricType.COUNTER, // type
|
||||
MetricUnits.NONE); // units
|
||||
|
||||
@POST
|
||||
@Produces(MediaType.TEXT_HTML)
|
||||
public String createPlayer(@QueryParam("name") String name, @QueryParam("id") String id) {
|
||||
@ -49,6 +62,10 @@ public class PlayerService {
|
||||
System.out.println("Created a new player with id=" + p.id);
|
||||
else
|
||||
System.out.println("A player already existed with id=" + p.id);
|
||||
|
||||
if (id != null && registry != null) {
|
||||
registry.counter(numLoginsCounter).inc();
|
||||
}
|
||||
return p.id;
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,11 @@
|
||||
<feature>mpConfig-1.3</feature>
|
||||
<feature>mpJwt-1.0</feature>
|
||||
<feature>mpOpenAPI-1.0</feature>
|
||||
<feature>mpMetrics-1.1</feature>
|
||||
</featureManager>
|
||||
|
||||
<mpMetrics authentication="false"/>
|
||||
|
||||
<applicationManager autoExpand="true"/>
|
||||
|
||||
<sslDefault sslRef="RpSSLConfig" />
|
||||
|
Loading…
Reference in New Issue
Block a user