Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/292 requestresponselogger memoria tuning v2 #379

Merged
merged 37 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5467c24
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 12, 2023
1f71288
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
922f0c8
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
113a052
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
a5f4a87
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
f8534b0
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
cacd874
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
faab11b
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 16, 2023
f387cb5
OSP-55 - sonatype-lift fixes
mate-biro Jan 18, 2023
ce3f81f
OSP-55 - sonatype-lift fixes
mate-biro Jan 16, 2023
e4075f6
OSP-55 - sonatype-lift fixes
mate-biro Jan 16, 2023
85a14a6
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 17, 2023
8906687
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 17, 2023
a05f852
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 17, 2023
f18d796
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 17, 2023
b01df54
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 17, 2023
236b25c
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 17, 2023
daed1e6
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 18, 2023
a979632
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 18, 2023
7fa625f
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 18, 2023
27fe62b
OSP-55 - sonatype-lift fixes
mate-biro Jan 18, 2023
5f25ce7
Merge branch 'master' into bugfix/292-requestresponselogger-memoria-t…
mate-biro Jan 23, 2023
fc00000
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 23, 2023
dbd6300
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 23, 2023
3c01a99
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 23, 2023
834c1fb
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Jan 23, 2023
64b0849
Merge branch 'master' into bugfix/292-requestresponselogger-memoria-t…
mate-biro Oct 15, 2023
4c0179b
Merge branch 'master' into bugfix/292-requestresponselogger-memoria-t…
mate-biro Oct 27, 2023
36ed568
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 2, 2023
2d15cd9
Merge branch 'master' into bugfix/292-requestresponselogger-memoria-t…
mate-biro Nov 8, 2023
2ee8a0f
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 8, 2023
fa3f25c
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 8, 2023
7673301
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 8, 2023
11a4f85
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 8, 2023
18d3063
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 8, 2023
6b0a136
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 24, 2023
70d8723
OSP-55 - RequestResponseLogger memoria tuning
mate-biro Nov 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
/*-
* #%L
* Coffee
* %%
* Copyright (C) 2020 - 2023 i-Cell Mobilsoft Zrt.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package hu.icellmobilsoft.coffee.rest.log.optimized;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriInfo;
import jakarta.ws.rs.ext.WriterInterceptor;
import jakarta.ws.rs.ext.WriterInterceptorContext;

import org.apache.commons.lang3.StringUtils;

import hu.icellmobilsoft.coffee.cdi.logger.AppLogger;
import hu.icellmobilsoft.coffee.cdi.logger.ThisLogger;
import hu.icellmobilsoft.coffee.dto.common.LogConstants;
import hu.icellmobilsoft.coffee.rest.cdi.BaseApplicationContainer;
import hu.icellmobilsoft.coffee.rest.log.annotation.LogSpecifier;
import hu.icellmobilsoft.coffee.rest.log.annotation.enumeration.LogSpecifierTarget;
import hu.icellmobilsoft.coffee.rest.utils.RestLoggerUtil;
import hu.icellmobilsoft.coffee.se.logging.mdc.MDC;
import hu.icellmobilsoft.coffee.tool.utils.stream.RequestLoggerInputStream;
import hu.icellmobilsoft.coffee.tool.utils.stream.ResponseEntityCollectorOutputStream;
import hu.icellmobilsoft.coffee.tool.utils.string.RandomUtil;

/**
* Base class for REST logging
*
* @author ischeffer
* @author mate.biro
* @since 2.4.0
*/
public abstract class BaseRestLogger implements ContainerRequestFilter, WriterInterceptor {

@Inject
@ThisLogger
private AppLogger log;

@Inject
private BaseApplicationContainer baseApplicationContainer;

@Inject
private @Named("optimized_RequestResponseLogger") RequestResponseLogger requestResponseLogger;

@Context
private UriInfo uriInfo;

@Context
private HttpServletResponse httpServletResponse;

/**
* Default constructor, constructs a new object.
*/
public BaseRestLogger() {
super();
}

/** {@inheritDoc} */
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
MDC.clear();
MDC.put(LogConstants.LOG_SERVICE_NAME, baseApplicationContainer.getCoffeeAppName());
processRequest(requestContext);
}

/** {@inheritDoc} */
@Override
public void aroundWriteTo(WriterInterceptorContext context) throws IOException {
processResponse(context);
}

/**
* Processes HTTP request.
*
* @param requestContext
* context
*/
protected void processRequest(ContainerRequestContext requestContext) {
if (RestLoggerUtil.logDisabled(requestContext, LogSpecifierTarget.REQUEST)) {
return;
}

var logMessage = new StringBuilder();
appendRequestLine(logMessage, requestContext);
appendRequestHeaders(logMessage, requestContext);

int maxRequestEntityLogSize = requestResponseLogger.getMaxRequestEntityLogSize(requestContext);

var requestLoggerInputStream = new RequestLoggerInputStream(
requestContext.getEntityStream(),
maxRequestEntityLogSize,
RequestResponseLogger.REQUEST_PREFIX,
logMessage);

// a saját InputStream-et állítjuk be a context-be, ami majd az entity stream olvasáskor log-olja a request-et
requestContext.setEntityStream(requestLoggerInputStream);
}

/**
* Processes HTTP response.
*
* @param context
* context
* @throws IOException
* if response cannot be processed.
*/
@SuppressWarnings("Var")
protected void processResponse(WriterInterceptorContext context) throws IOException {
if (RestLoggerUtil.logDisabled(context, LogSpecifierTarget.RESPONSE)) {
context.proceed();
return;
}

StringBuilder message = new StringBuilder();
try {
printResponseLine(message, context);
printResponseHeaders(message, context);

OutputStream originalResponseStream = context.getOutputStream();
byte[] entity = new byte[0];
int maxResponseEntityLogSize = requestResponseLogger.getMaxResponseEntityLogSize(context);
if (maxResponseEntityLogSize != LogSpecifier.NO_LOG) {
var responseEntityCollectorOutputStream = new ResponseEntityCollectorOutputStream(originalResponseStream, maxResponseEntityLogSize);
// a saját OutputStream-et állítjuk be a context-be, ami majd az entity stream-be írásakor gyűjti azt a log-olás számára
context.setOutputStream(responseEntityCollectorOutputStream);
context.proceed();
entity = responseEntityCollectorOutputStream.getEntityText().getBytes(StandardCharsets.UTF_8);
} else {
context.proceed();
}

printResponseEntity(message, context, entity);
} finally {
log.info(message.toString());
}
}

/**
* HTTP headerben szereplo session kulcs neve. Ezt a kulcsot fogja a logger keresni a http headerekből, aminek az értékét fel használja a
* <code>MDC.put(LogConstants.LOG_SESSION_ID, ertek)</code> részben.<br>
* <br>
* Folyamat azonosítás, Graylog loggolásban van nagy értelme
*
* @return session key
*/
public abstract String sessionKey();

/**
* Prints request headers from {@link ContainerRequestContext} and appends given {@link StringBuilder} with the print result.
*
* @param b
* request message
* @param requestContext
* context
* @see RequestResponseLogger#printRequestHeaders(java.util.Map)
*/
protected void appendRequestHeaders(StringBuilder b, ContainerRequestContext requestContext) {
MultivaluedMap<String, String> headers = requestContext.getHeaders();
b.append(requestResponseLogger.printRequestHeaders(headers));
String sessionId = null;
if (headers != null && headers.containsKey(sessionKey())) {
sessionId = headers.get(sessionKey()).get(0);
}
MDC.put(LogConstants.LOG_SESSION_ID, StringUtils.defaultIfBlank(sessionId, RandomUtil.generateId()));
}

/**
* Prints http path info from {@link ContainerRequestContext} and appends given {@link StringBuilder} with the print result.
*
* @param b
* request message
* @param requestContext
* context
* @see RequestResponseLogger#printRequestLine(ContainerRequestContext)
*/
protected void appendRequestLine(StringBuilder b, ContainerRequestContext requestContext) {
b.append(requestResponseLogger.printRequestLine(requestContext));
}

/**
* Prints response URL line and appends given {@link StringBuilder} with the print result.
*
* @param b
* response message
* @param context
* context
* @see RequestResponseLogger#printResponseLine(String, int, String, String)
*/
protected void printResponseLine(StringBuilder b, WriterInterceptorContext context) {
String fullPath = uriInfo.getAbsolutePath().toASCIIString();
int status = httpServletResponse.getStatus();
Status statusEnum = Status.fromStatusCode(status);
String statusInfo = statusEnum != null ? statusEnum.getReasonPhrase() : null;
MediaType mediaType = context.getMediaType();
b.append(requestResponseLogger.printResponseLine(fullPath, status, String.valueOf(statusInfo), String.valueOf(mediaType)));
}

/**
* Prints response header values and appends given {@link StringBuilder} with the print result.
*
* @param b
* response message
* @param context
* context
* @see RequestResponseLogger#printResponseHeaders(java.util.Map)
*/
protected void printResponseHeaders(StringBuilder b, WriterInterceptorContext context) {
b.append(requestResponseLogger.printResponseHeaders(context.getHeaders()));
}

/**
* Prints response from {@link WriterInterceptorContext} and appends given {@link StringBuilder} with the print result.
*
* @param b
* response message
* @param context
* context
* @param entityCopy
* entity
* @see RequestResponseLogger#printResponseEntity(String, WriterInterceptorContext, byte[])
*/
protected void printResponseEntity(StringBuilder b, WriterInterceptorContext context, byte[] entityCopy) {
b.append(requestResponseLogger.printResponseEntity(uriInfo.getAbsolutePath().toASCIIString(), context, entityCopy));
}
}
Loading