diff --git a/src/main/java/org/codelibs/fess/app/service/SearchLogService.java b/src/main/java/org/codelibs/fess/app/service/SearchLogService.java index 50086577e..7fe47ea3b 100644 --- a/src/main/java/org/codelibs/fess/app/service/SearchLogService.java +++ b/src/main/java/org/codelibs/fess/app/service/SearchLogService.java @@ -544,6 +544,9 @@ public class SearchLogService { e.getSearchFieldLogList().stream().forEach(p -> { params.put(p.getFirst(), p.getSecond()); }); + e.getRequestHeaderList().stream().forEach(p -> { + params.put(p.getFirst(), p.getSecond()); + }); return params; }).get(); } diff --git a/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java b/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java index d6c35a915..e69dd6b56 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/backup/AdminBackupAction.java @@ -451,7 +451,10 @@ public class AdminBackupAction extends FessAdminAction { appendJson("requested-at", entity.getRequestedAt(), buf).append(','); final Map> searchFieldMap = entity.getSearchFieldLogList().stream() .collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList()))); - appendJson("search-field", searchFieldMap, buf); + appendJson("search-field", searchFieldMap, buf).append(','); + final Map> requestHeaderMap = entity.getRequestHeaderList().stream() + .collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList()))); + appendJson("headers", requestHeaderMap, buf); buf.append('}'); buf.append('\n'); try { diff --git a/src/main/java/org/codelibs/fess/es/log/exbhv/SearchLogBhv.java b/src/main/java/org/codelibs/fess/es/log/exbhv/SearchLogBhv.java index 6467b22f5..74f0c9693 100644 --- a/src/main/java/org/codelibs/fess/es/log/exbhv/SearchLogBhv.java +++ b/src/main/java/org/codelibs/fess/es/log/exbhv/SearchLogBhv.java @@ -86,6 +86,24 @@ public class SearchLogBhv extends BsSearchLogBhv { } }); } + final Object headersObj = source.get("headers"); + if (headersObj instanceof Map) { + ((Map) headersObj).entrySet().stream().forEach(e -> { + if (e.getValue() instanceof String[]) { + final String[] values = (String[]) e.getValue(); + for (final String v : values) { + result.getRequestHeaderList().add(new Pair<>(e.getKey(), v)); + } + } else if (e.getValue() instanceof List) { + final List values = (List) e.getValue(); + for (final String v : values) { + result.getRequestHeaderList().add(new Pair<>(e.getKey(), v)); + } + } else if (e.getValue() != null) { + result.getRequestHeaderList().add(new Pair<>(e.getKey(), e.getValue().toString())); + } + }); + } return result; } catch (final Exception e) { final String msg = "Cannot create a new instance: " + entityType.getName(); diff --git a/src/main/java/org/codelibs/fess/es/log/exentity/SearchLog.java b/src/main/java/org/codelibs/fess/es/log/exentity/SearchLog.java index fc507aee2..913bf9638 100644 --- a/src/main/java/org/codelibs/fess/es/log/exentity/SearchLog.java +++ b/src/main/java/org/codelibs/fess/es/log/exentity/SearchLog.java @@ -43,6 +43,8 @@ public class SearchLog extends BsSearchLog implements SearchLogEvent { private final List> searchFieldLogList = new ArrayList<>(); + private final List> headerList = new ArrayList<>(); + private OptionalEntity userInfo; private Map fields; @@ -73,6 +75,12 @@ public class SearchLog extends BsSearchLog implements SearchLogEvent { } } + public void addRequestHeaderValue(final String name, final String value) { + if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(value)) { + headerList.add(new Pair<>(name, value)); + } + } + public void addDocument(final Map doc) { documentList.add(doc); } @@ -103,6 +111,10 @@ public class SearchLog extends BsSearchLog implements SearchLogEvent { return searchFieldLogList; } + public List> getRequestHeaderList() { + return headerList; + } + public void addField(final String key, final Object value) { fields.put(key, value); } @@ -120,6 +132,9 @@ public class SearchLog extends BsSearchLog implements SearchLogEvent { final Map> searchFieldMap = searchFieldLogList.stream() .collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList()))); sourceMap.put("searchField", searchFieldMap); + final Map> headerMap = headerList.stream() + .collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList()))); + sourceMap.put("headers", headerMap); sourceMap.put("documents", documentList); return sourceMap; } @@ -142,12 +157,12 @@ public class SearchLog extends BsSearchLog implements SearchLogEvent { @Override public String toString() { - return "SearchLog [searchFieldLogList=" + searchFieldLogList + ", userInfo=" + userInfo + ", fields=" + fields + ", accessType=" - + accessType + ", clientIp=" + clientIp + ", hitCount=" + hitCount + ", languages=" + languages + ", queryId=" + queryId - + ", queryOffset=" + queryOffset + ", queryPageSize=" + queryPageSize + ", queryTime=" + queryTime + ", referer=" + referer - + ", requestedAt=" + requestedAt + ", responseTime=" + responseTime + ", roles=" + Arrays.toString(roles) + ", searchWord=" - + searchWord + ", user=" + user + ", userAgent=" + userAgent + ", userInfoId=" + userInfoId + ", userSessionId=" - + userSessionId + ", virtualHost=" + virtualHost + ", documents=" + documentList + "]"; + return "SearchLog [searchFieldLogList=" + searchFieldLogList + ", headerList=" + headerList + ", userInfo=" + userInfo + ", fields=" + + fields + ", accessType=" + accessType + ", clientIp=" + clientIp + ", hitCount=" + hitCount + ", languages=" + languages + + ", queryId=" + queryId + ", queryOffset=" + queryOffset + ", queryPageSize=" + queryPageSize + ", queryTime=" + queryTime + + ", referer=" + referer + ", requestedAt=" + requestedAt + ", responseTime=" + responseTime + ", roles=" + + Arrays.toString(roles) + ", searchWord=" + searchWord + ", user=" + user + ", userAgent=" + userAgent + ", userInfoId=" + + userInfoId + ", userSessionId=" + userSessionId + ", virtualHost=" + virtualHost + ", documents=" + documentList + "]"; } @Override diff --git a/src/main/java/org/codelibs/fess/helper/SearchLogHelper.java b/src/main/java/org/codelibs/fess/helper/SearchLogHelper.java index e94ff0333..a832ad4c0 100644 --- a/src/main/java/org/codelibs/fess/helper/SearchLogHelper.java +++ b/src/main/java/org/codelibs/fess/helper/SearchLogHelper.java @@ -20,8 +20,10 @@ import static org.codelibs.core.stream.StreamUtil.stream; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -109,7 +111,8 @@ public class SearchLogHelper { final UserInfoHelper userInfoHelper = ComponentUtil.getUserInfoHelper(); final SearchLog searchLog = new SearchLog(); - if (ComponentUtil.getFessConfig().isUserInfo()) { + final FessConfig fessConfig = ComponentUtil.getFessConfig(); + if (fessConfig.isUserInfo()) { final String userCode = userInfoHelper.getUserCode(); if (userCode != null) { searchLog.setUserSessionId(userCode); @@ -164,7 +167,7 @@ public class SearchLogHelper { @SuppressWarnings("unchecked") final Map> fieldLogMap = (Map>) request.getAttribute(Constants.FIELD_LOGS); if (fieldLogMap != null) { - final int queryMaxLength = ComponentUtil.getFessConfig().getQueryMaxLengthAsInteger(); + final int queryMaxLength = fessConfig.getQueryMaxLengthAsInteger(); for (final Map.Entry> logEntry : fieldLogMap.entrySet()) { for (final String value : logEntry.getValue()) { searchLog.addSearchFieldLogValue(logEntry.getKey(), StringUtils.abbreviate(value, queryMaxLength)); @@ -172,6 +175,15 @@ public class SearchLogHelper { } } + LaRequestUtil.getOptionalRequest().ifPresent(req -> { + for (final String s : fessConfig.getSearchlogRequestHeadersAsArray()) { + final String key = s.replace('-', '_').toLowerCase(Locale.ENGLISH); + Collections.list(req.getHeaders(s)).stream().forEach(v -> { + searchLog.addRequestHeaderValue(key, v); + }); + } + }); + addDocumentsInResponse(queryResponseList, searchLog); searchLogQueue.add(searchLog); diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java index bd48921a2..4e56be8a6 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java @@ -1256,6 +1256,9 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction /** The key of the configuration. e.g. -1 */ String SEARCHLOG_AGG_SHARD_SIZE = "searchlog.agg.shard.size"; + /** The key of the configuration. e.g. */ + String SEARCHLOG_REQUEST_HEADERS = "searchlog.request.headers"; + /** The key of the configuration. e.g. 100 */ String THUMBNAIL_HTML_IMAGE_MIN_WIDTH = "thumbnail.html.image.min.width"; @@ -5800,6 +5803,21 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction */ Integer getSearchlogAggShardSizeAsInteger(); + /** + * Get the value for the key 'searchlog.request.headers'.
+ * The value is, e.g.
+ * @return The value of found property. (NotNull: if not found, exception but basically no way) + */ + String getSearchlogRequestHeaders(); + + /** + * Get the value for the key 'searchlog.request.headers' as {@link Integer}.
+ * The value is, e.g.
+ * @return The value of found property. (NotNull: if not found, exception but basically no way) + * @throws NumberFormatException When the property is not integer. + */ + Integer getSearchlogRequestHeadersAsInteger(); + /** * Get the value for the key 'thumbnail.html.image.min.width'.
* The value is, e.g. 100
@@ -9312,6 +9330,14 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction return getAsInteger(FessConfig.SEARCHLOG_AGG_SHARD_SIZE); } + public String getSearchlogRequestHeaders() { + return get(FessConfig.SEARCHLOG_REQUEST_HEADERS); + } + + public Integer getSearchlogRequestHeadersAsInteger() { + return getAsInteger(FessConfig.SEARCHLOG_REQUEST_HEADERS); + } + public String getThumbnailHtmlImageMinWidth() { return get(FessConfig.THUMBNAIL_HTML_IMAGE_MIN_WIDTH); } @@ -10458,6 +10484,7 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction defaultMap.put(FessConfig.PAGING_SEARCH_PAGE_SIZE, "10"); defaultMap.put(FessConfig.PAGING_SEARCH_PAGE_MAX_SIZE, "100"); defaultMap.put(FessConfig.SEARCHLOG_AGG_SHARD_SIZE, "-1"); + defaultMap.put(FessConfig.SEARCHLOG_REQUEST_HEADERS, ""); defaultMap.put(FessConfig.THUMBNAIL_HTML_IMAGE_MIN_WIDTH, "100"); defaultMap.put(FessConfig.THUMBNAIL_HTML_IMAGE_MIN_HEIGHT, "100"); defaultMap.put(FessConfig.THUMBNAIL_HTML_IMAGE_MAX_ASPECT_RATIO, "3.0"); diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java index 5d7aeaebe..8cd0bb374 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java @@ -2106,4 +2106,11 @@ public interface FessProp { default String getFesenType() { return getElasticsearchType(); } + + String getSearchlogRequestHeaders(); + + default String[] getSearchlogRequestHeadersAsArray() { + return split(getSearchlogRequestHeaders(), ",") + .get(stream -> stream.filter(StringUtil::isNotBlank).map(String::trim).toArray(n -> new String[n])); + } } diff --git a/src/main/resources/fess_config.properties b/src/main/resources/fess_config.properties index a9c553c37..562ce7072 100644 --- a/src/main/resources/fess_config.properties +++ b/src/main/resources/fess_config.properties @@ -679,6 +679,7 @@ paging.search.page.size=10 paging.search.page.max.size=100 searchlog.agg.shard.size=-1 +searchlog.request.headers= thumbnail.html.image.min.width=100 thumbnail.html.image.min.height=100 diff --git a/src/main/resources/fess_indices/fess_log.search_log/search_log.json b/src/main/resources/fess_indices/fess_log.search_log/search_log.json index a2b3fa5bf..3bac41a5b 100644 --- a/src/main/resources/fess_indices/fess_log.search_log/search_log.json +++ b/src/main/resources/fess_indices/fess_log.search_log/search_log.json @@ -1,5 +1,13 @@ { "dynamic_templates": [ + { + "headers": { + "path_match": "headers.*", + "mapping": { + "type": "keyword" + } + } + }, { "search_fields": { "path_match": "searchField.*",