diff --git a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/controller/ExceptionTraceController.java b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/controller/ExceptionTraceController.java index 349eb410440cf..7dea07ebb2c7d 100644 --- a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/controller/ExceptionTraceController.java +++ b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/controller/ExceptionTraceController.java @@ -108,7 +108,7 @@ public List getListOfExceptionMetaDataByGivenRange( @RequestParam("from") @PositiveOrZero long from, @RequestParam("to") @PositiveOrZero long to, - @RequestParam(value = "query", required = false) List tags, + @RequestParam(value = "filters", required = false) List filters, @RequestParam("orderBy") String orderBy, @RequestParam("isDesc") boolean isDesc, @RequestParam("count") int count @@ -124,6 +124,7 @@ public List getListOfExceptionMetaDataByGivenRange( .setRange(range) .setTimePrecision(DETAILED_TIME_PRECISION) .setHardLimit(count) + .addAllFilters(filters) .setOrderBy(orderBy) .setIsDesc(isDesc) .build(); diff --git a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/mapper/ExceptionMetaDataEntityMapper.java b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/mapper/ExceptionMetaDataEntityMapper.java index 32ec5b2e65c95..536efd4186007 100644 --- a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/mapper/ExceptionMetaDataEntityMapper.java +++ b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/mapper/ExceptionMetaDataEntityMapper.java @@ -26,6 +26,7 @@ import com.navercorp.pinpoint.exceptiontrace.web.model.ExceptionTraceValueView; import com.navercorp.pinpoint.exceptiontrace.web.model.Grouped; import com.navercorp.pinpoint.exceptiontrace.web.model.GroupedFieldName; +import com.navercorp.pinpoint.exceptiontrace.web.model.RawGroupedFieldName; import com.navercorp.pinpoint.exceptiontrace.web.util.GroupByAttributes; import com.navercorp.pinpoint.exceptiontrace.web.view.ExceptionMetaDataView; import org.mapstruct.AfterMapping; @@ -78,12 +79,32 @@ ExceptionTraceValueView toValueView( @Mappings({ @Mapping(target = "groupedFieldName", ignore = true), + @Mapping(source = "entity", target = "rawFieldName"), }) ExceptionTraceSummary toSummary( ExceptionTraceSummaryEntity entity, List attributesList ); + @AfterMapping + default void addRawGroupedFieldName( + ExceptionTraceSummaryEntity entity, + List attributesList, + @MappingTarget ExceptionTraceSummary summary + ) { + RawGroupedFieldName groupedFieldName = new RawGroupedFieldName(); + for (GroupByAttributes attributes : attributesList) { + switch (attributes) { + case STACK_TRACE -> groupedFieldName.setStackTraceHash(checkIfNull(entity.getStackTraceHash())); + case URI_TEMPLATE -> groupedFieldName.setUriTemplate(checkIfNull(entity.getUriTemplate())); + case ERROR_CLASS_NAME -> groupedFieldName.setErrorClassName(checkIfNull(entity.getErrorClassName())); + case ERROR_MESSAGE_LOG_TYPE -> + groupedFieldName.setErrorMessage_logtype(checkIfNull(selectErrorMessage(entity))); + } + } + summary.setRawFieldName(groupedFieldName); + } + @AfterMapping default void addGroupedFieldName( GroupedFieldNameEntity entity, @@ -96,7 +117,8 @@ default void addGroupedFieldName( case STACK_TRACE -> groupedFieldName.setStackTraceHash(checkIfNull(entity.getStackTraceHash())); case URI_TEMPLATE -> groupedFieldName.setUriTemplate(checkIfNull(entity.getUriTemplate())); case ERROR_CLASS_NAME -> groupedFieldName.setErrorClassName(checkIfNull(entity.getErrorClassName())); - case ERROR_MESSAGE_LOG_TYPE -> groupedFieldName.setErrorMessage(checkIfNull(selectErrorMessage(entity))); + case ERROR_MESSAGE_LOG_TYPE -> + groupedFieldName.setErrorMessage(checkIfNull(selectErrorMessage(entity))); } } grouped.setGroupedFieldName(groupedFieldName); diff --git a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/ExceptionTraceSummary.java b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/ExceptionTraceSummary.java index de25933bbe67f..667492c9eb2b8 100644 --- a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/ExceptionTraceSummary.java +++ b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/ExceptionTraceSummary.java @@ -23,6 +23,7 @@ public class ExceptionTraceSummary implements Grouped { private GroupedFieldName groupedFieldName; + private RawGroupedFieldName rawFieldName; private String mostRecentErrorClass; private String mostRecentErrorMessage; private long count; @@ -41,6 +42,15 @@ public void setGroupedFieldName(GroupedFieldName groupedFieldName) { this.groupedFieldName = groupedFieldName; } + @JsonProperty("rawFieldName") + public RawGroupedFieldName getRawFieldName() { + return rawFieldName; + } + + public void setRawFieldName(RawGroupedFieldName rawFieldName) { + this.rawFieldName = rawFieldName; + } + public String getMostRecentErrorClass() { return mostRecentErrorClass; } diff --git a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/RawGroupedFieldName.java b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/RawGroupedFieldName.java new file mode 100644 index 0000000000000..2eb80073fda4d --- /dev/null +++ b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/model/RawGroupedFieldName.java @@ -0,0 +1,73 @@ +/* + * Copyright 2024 NAVER Corp. + * + * 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. + */ +package com.navercorp.pinpoint.exceptiontrace.web.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +/** + * @author intr3p1d + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RawGroupedFieldName { + private String uriTemplate; + private String errorClassName; + private String errorMessage_logtype; + private String stackTraceHash; + + + public String getUriTemplate() { + return uriTemplate; + } + + public void setUriTemplate(String uriTemplate) { + this.uriTemplate = uriTemplate; + } + + public String getErrorClassName() { + return errorClassName; + } + + public void setErrorClassName(String errorClassName) { + this.errorClassName = errorClassName; + } + + public String getErrorMessage_logtype() { + return errorMessage_logtype; + } + + public void setErrorMessage_logtype(String errorMessage_logtype) { + this.errorMessage_logtype = errorMessage_logtype; + } + + public String getStackTraceHash() { + return stackTraceHash; + } + + public void setStackTraceHash(String stackTraceHash) { + this.stackTraceHash = stackTraceHash; + } + + + @Override + public String toString() { + return "RawGroupedFieldName{" + + "uriTemplate='" + uriTemplate + '\'' + + ", errorClassName='" + errorClassName + '\'' + + ", errorMessage_logtype='" + errorMessage_logtype + '\'' + + ", stackTraceHash='" + stackTraceHash + '\'' + + '}'; + } +} diff --git a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/ExceptionTraceQueryParameter.java b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/ExceptionTraceQueryParameter.java index d5c6fa8690ac9..24bcb2406ae7c 100644 --- a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/ExceptionTraceQueryParameter.java +++ b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/ExceptionTraceQueryParameter.java @@ -49,6 +49,7 @@ public class ExceptionTraceQueryParameter extends QueryParameter { private final OrderByAttributes orderBy; private final String isDesc; private final List groupByAttributes; + private final FilterByAttributes filterByAttributes; private final long timeWindowRangeCount; @@ -67,6 +68,7 @@ protected ExceptionTraceQueryParameter( this.orderBy = builder.orderBy; this.isDesc = builder.isDesc; this.groupByAttributes = builder.groupByAttributes; + this.filterByAttributes = builder.filterByAttributes; this.timeWindowRangeCount = builder.timeWindowRangeCount; } @@ -94,6 +96,7 @@ public static class Builder extends QueryParameter.Builder { private OrderByAttributes orderBy; private String isDesc; private final List groupByAttributes = new ArrayList<>(); + private final FilterByAttributes filterByAttributes = new FilterByAttributes(); private long timeWindowRangeCount = 0; @@ -182,11 +185,22 @@ public Builder addAllGroupByList(Collection strings) { GroupByAttributes::fromValue ) .filter(Objects::nonNull) - .distinct().sorted().collect(Collectors.toList()); + .distinct().sorted().toList(); this.groupByAttributes.addAll(groupByAttributesList); return self(); } + public Builder addAllFilters(Collection strings) { + if (strings == null) { + return self(); + } + for (String string : strings) { + String[] tag = string.split(":", 2); + filterByAttributes.put(tag[0], tag[1]); + } + return self(); + } + public long useLimitIfSet() { if (hardLimit != null) { return hardLimit; @@ -216,7 +230,8 @@ public ExceptionTraceQueryParameter build() { @Override public String toString() { return "ExceptionTraceQueryParameter{" + - "tenantId='" + tenantId + '\'' + + "tableName='" + tableName + '\'' + + ", tenantId='" + tenantId + '\'' + ", applicationName='" + applicationName + '\'' + ", agentId='" + agentId + '\'' + ", transactionId='" + transactionId + '\'' + @@ -226,6 +241,7 @@ public String toString() { ", orderBy=" + orderBy + ", isDesc='" + isDesc + '\'' + ", groupByAttributes=" + groupByAttributes + + ", filterByAttributes=" + filterByAttributes + ", timeWindowRangeCount=" + timeWindowRangeCount + '}'; } diff --git a/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/FilterByAttributes.java b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/FilterByAttributes.java new file mode 100644 index 0000000000000..c2138cc3aa527 --- /dev/null +++ b/exceptiontrace/exceptiontrace-web/src/main/java/com/navercorp/pinpoint/exceptiontrace/web/util/FilterByAttributes.java @@ -0,0 +1,69 @@ +/* + * Copyright 2024 NAVER Corp. + * + * 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. + */ +package com.navercorp.pinpoint.exceptiontrace.web.util; + +import com.navercorp.pinpoint.common.server.util.EnumGetter; +import com.navercorp.pinpoint.exceptiontrace.common.pinot.PinotColumns; + +import java.util.EnumMap; +import java.util.Map; + +/** + * @author intr3p1d + */ +public class FilterByAttributes { + + public enum FilterByColumn { + URI_TEMPLATE(PinotColumns.URI_TEMPLATE), + ERROR_MESSAGE_LOG_TYPE(PinotColumns.ERROR_MESSAGE_LOG_TYPE), + ERROR_CLASS_NAME(PinotColumns.ERROR_CLASS_NAME), + STACK_TRACE(PinotColumns.STACK_TRACE_HASH); + + private static final EnumGetter GETTER = new EnumGetter<>(FilterByColumn.class); + + private final PinotColumns column; + + FilterByColumn(PinotColumns column) { + this.column = column; + } + + public PinotColumns getColumn() { + return column; + } + + public static FilterByColumn fromValue(String column) { + return GETTER.fromValue((FilterByColumn x) -> x.getColumn().getName(), column); + } + } + + + private final Map map = new EnumMap<>(FilterByColumn.class); + + public void put(String column, String value) { + this.map.put(FilterByColumn.fromValue(column), value); + } + + public Map getMap() { + return map; + } + + @Override + public String toString() { + return "FilterByAttributes{" + + "map=" + map + + '}'; + } +} diff --git a/exceptiontrace/exceptiontrace-web/src/main/resources/exceptiontrace/mapper/ExceptionTraceMapper.xml b/exceptiontrace/exceptiontrace-web/src/main/resources/exceptiontrace/mapper/ExceptionTraceMapper.xml index 36279349d79f2..a9826c4e0b5b6 100644 --- a/exceptiontrace/exceptiontrace-web/src/main/resources/exceptiontrace/mapper/ExceptionTraceMapper.xml +++ b/exceptiontrace/exceptiontrace-web/src/main/resources/exceptiontrace/mapper/ExceptionTraceMapper.xml @@ -20,6 +20,12 @@ + + + AND ${key.column.name}=#{value} + + + @@ -125,11 +131,7 @@ AND agentId = #{agentId} - - AND transactionId = #{transactionId} - AND spanId = #{spanId} - AND exceptionId = #{exceptionId} - + ORDER BY ${orderBy.getAttributeName} ${isDesc} LIMIT ${limit}