Reduce DDoS impact of access log transactions

Made Plan skip access logging if transaction queue is larger than 500 transactions
Reduced amount of objects held by access log transaction by serializing request properties to objects before passing to transaction.

Affects issues:
- #3486
This commit is contained in:
Aurora Lahtela 2024-02-27 10:11:32 +02:00
parent a3a2085c8a
commit b50fa10e12
2 changed files with 35 additions and 31 deletions

View File

@ -75,8 +75,14 @@ public class AccessLogger {
} }
} }
try { try {
long timestamp = internalRequest.getTimestamp();
String accessAddress = internalRequest.getAccessAddress(webserverConfiguration);
String method = internalRequest.getMethod();
method = method != null ? method : "?";
String url = StoreRequestTransaction.getTruncatedURI(request, internalRequest);
int responseCode = response.getCode();
dbSystem.getDatabase().executeTransaction( dbSystem.getDatabase().executeTransaction(
new StoreRequestTransaction(webserverConfiguration, internalRequest, request, response) new StoreRequestTransaction(timestamp, accessAddress, method, url, responseCode)
); );
} catch (CompletionException | DBOpException e) { } catch (CompletionException | DBOpException e) {
errorLogger.warn(e, ErrorContext.builder() errorLogger.warn(e, ErrorContext.builder()

View File

@ -16,49 +16,33 @@
*/ */
package com.djrapitops.plan.storage.database.transactions.events; package com.djrapitops.plan.storage.database.transactions.events;
import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.request.Request; import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.webserver.configuration.WebserverConfiguration;
import com.djrapitops.plan.delivery.webserver.http.InternalRequest; import com.djrapitops.plan.delivery.webserver.http.InternalRequest;
import com.djrapitops.plan.storage.database.sql.tables.AccessLogTable; import com.djrapitops.plan.storage.database.sql.tables.AccessLogTable;
import com.djrapitops.plan.storage.database.transactions.ExecStatement; import com.djrapitops.plan.storage.database.transactions.ExecStatement;
import com.djrapitops.plan.storage.database.transactions.Transaction; import com.djrapitops.plan.storage.database.transactions.ThrowawayTransaction;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
public class StoreRequestTransaction extends Transaction { public class StoreRequestTransaction extends ThrowawayTransaction {
private final WebserverConfiguration webserverConfiguration; private final long timestamp;
private final String accessAddress;
private final String method;
private final String url;
private final int responseCode;
private final InternalRequest internalRequest; public StoreRequestTransaction(long timestamp, String accessAddress, String method, String url, int responseCode) {
private final Request request; // can be null this.timestamp = timestamp;
private final Response response; this.accessAddress = accessAddress;
this.method = method;
public StoreRequestTransaction(WebserverConfiguration webserverConfiguration, InternalRequest internalRequest, Request request, Response response) { this.url = url;
this.webserverConfiguration = webserverConfiguration; this.responseCode = responseCode;
this.internalRequest = internalRequest;
this.request = request;
this.response = response;
} }
@Override public static String getTruncatedURI(Request request, InternalRequest internalRequest) {
protected void performOperations() {
execute(new ExecStatement(AccessLogTable.INSERT_NO_USER) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, internalRequest.getTimestamp());
statement.setString(2, internalRequest.getAccessAddress(webserverConfiguration));
String method = internalRequest.getMethod();
statement.setString(3, method != null ? method : "?");
statement.setString(4, getTruncatedURI());
statement.setInt(5, response.getCode());
}
});
}
private String getTruncatedURI() {
String uri = request != null ? request.getPath().asString() + request.getQuery().asString() String uri = request != null ? request.getPath().asString() + request.getQuery().asString()
: internalRequest.getRequestedURIString(); : internalRequest.getRequestedURIString();
if (uri == null) { if (uri == null) {
@ -66,4 +50,18 @@ public class StoreRequestTransaction extends Transaction {
} }
return StringUtils.truncate(uri, 65000); return StringUtils.truncate(uri, 65000);
} }
@Override
protected void performOperations() {
execute(new ExecStatement(AccessLogTable.INSERT_NO_USER) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, timestamp);
statement.setString(2, accessAddress);
statement.setString(3, method);
statement.setString(4, url);
statement.setInt(5, responseCode);
}
});
}
} }