Skip to content

Commit

Permalink
[#8072] Fix bind.pinpoint api to return json
Browse files Browse the repository at this point in the history
  • Loading branch information
emeroad committed Jan 3, 2022
1 parent 23c8dc1 commit 57f7d0d
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,37 @@

import com.navercorp.pinpoint.common.hbase.bo.ColumnGetCount;
import com.navercorp.pinpoint.common.hbase.bo.ColumnGetCountFactory;
import com.navercorp.pinpoint.common.profiler.sql.DefaultSqlParser;
import com.navercorp.pinpoint.common.profiler.sql.OutputParameterParser;
import com.navercorp.pinpoint.common.profiler.sql.SqlParser;
import com.navercorp.pinpoint.common.profiler.util.TransactionId;
import com.navercorp.pinpoint.common.profiler.util.TransactionIdUtils;
import com.navercorp.pinpoint.common.server.bo.SpanBo;
import com.navercorp.pinpoint.web.applicationmap.ApplicationMap;
import com.navercorp.pinpoint.web.applicationmap.histogram.TimeHistogramFormat;
import com.navercorp.pinpoint.web.calltree.span.CallTreeIterator;
import com.navercorp.pinpoint.web.calltree.span.SpanFilters;
import com.navercorp.pinpoint.web.calltree.span.TraceState;
import com.navercorp.pinpoint.web.config.LogConfiguration;
import com.navercorp.pinpoint.web.query.BindType;
import com.navercorp.pinpoint.web.query.QueryService;
import com.navercorp.pinpoint.web.query.QueryServiceFactory;
import com.navercorp.pinpoint.web.service.FilteredMapService;
import com.navercorp.pinpoint.web.service.FilteredMapServiceOption;
import com.navercorp.pinpoint.web.service.SpanResult;
import com.navercorp.pinpoint.web.service.SpanService;
import com.navercorp.pinpoint.web.service.TransactionInfoService;
import com.navercorp.pinpoint.web.util.DefaultMongoJsonParser;
import com.navercorp.pinpoint.web.util.MongoJsonParser;
import com.navercorp.pinpoint.web.util.OutputParameterMongoJsonParser;
import com.navercorp.pinpoint.web.view.TraceViewerDataViewModel;
import com.navercorp.pinpoint.web.view.TransactionInfoViewModel;
import com.navercorp.pinpoint.web.view.TransactionTimelineInfoViewModel;
import com.navercorp.pinpoint.web.vo.callstacks.RecordSet;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.function.Predicate;

Expand All @@ -75,21 +68,21 @@ public class BusinessTransactionController {
private final TransactionInfoService transactionInfoService;
private final FilteredMapService filteredMapService;
private final LogConfiguration logConfiguration;
private final QueryServiceFactory queryServiceFactory;


@Value("${web.callstack.selectSpans.limit:-1}")
private int callstackSelectSpansLimit;

private final SqlParser sqlParser = new DefaultSqlParser();
private final OutputParameterParser parameterParser = new OutputParameterParser();
private final MongoJsonParser mongoJsonParser = new DefaultMongoJsonParser();
private final OutputParameterMongoJsonParser parameterJsonParser = new OutputParameterMongoJsonParser();

public BusinessTransactionController(SpanService spanService, TransactionInfoService transactionInfoService,
FilteredMapService filteredMapService, LogConfiguration logConfiguration) {
FilteredMapService filteredMapService, LogConfiguration logConfiguration,
QueryServiceFactory queryServiceFactory) {
this.spanService = Objects.requireNonNull(spanService, "spanService");
this.transactionInfoService = Objects.requireNonNull(transactionInfoService, "transactionInfoService");
this.filteredMapService = Objects.requireNonNull(filteredMapService, "filteredMapService");
this.logConfiguration = Objects.requireNonNull(logConfiguration, "logConfiguration");
this.queryServiceFactory = Objects.requireNonNull(queryServiceFactory, "queryServiceFactory");
}

/**
Expand Down Expand Up @@ -153,22 +146,16 @@ public TransactionTimelineInfoViewModel transactionTimelineInfo(@RequestParam("t
SpanResult spanResult = this.spanService.selectSpan(transactionId, spanMatchFilter, columnGetCount);
final CallTreeIterator callTreeIterator = spanResult.getCallTree();

String traceViewerDataURL = null;
try {
traceViewerDataURL = ServletUriComponentsBuilder.fromPath("traceViewerData.pinpoint")
.queryParam("traceId", URLEncoder.encode(traceId,"UTF-8"))
.queryParam("focusTimestamp", focusTimestamp)
.queryParam("agentId", URLEncoder.encode(agentId,"UTF-8"))
.queryParam("spanId", spanId)
.build()
.toUriString();
} catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
}
String traceViewerDataURL = ServletUriComponentsBuilder.fromPath("traceViewerData.pinpoint")
.queryParam("traceId", URLEncoder.encode(traceId, StandardCharsets.UTF_8))
.queryParam("focusTimestamp", focusTimestamp)
.queryParam("agentId", URLEncoder.encode(agentId, StandardCharsets.UTF_8))
.queryParam("spanId", spanId)
.build()
.toUriString();

RecordSet recordSet = this.transactionInfoService.createRecordSet(callTreeIterator, spanMatchFilter);
TransactionTimelineInfoViewModel result = new TransactionTimelineInfoViewModel(transactionId, spanId, recordSet, traceViewerDataURL, logConfiguration);
return result;
return new TransactionTimelineInfoViewModel(transactionId, spanId, recordSet, traceViewerDataURL, logConfiguration);
}

@GetMapping(value = "/traceViewerData")
Expand All @@ -188,41 +175,44 @@ public TraceViewerDataViewModel traceViewerData(@RequestParam("traceId") String
final CallTreeIterator callTreeIterator = spanResult.getCallTree();

RecordSet recordSet = this.transactionInfoService.createRecordSet(callTreeIterator, spanMatchFilter);
TraceViewerDataViewModel result = new TraceViewerDataViewModel(recordSet);
return result;
return new TraceViewerDataViewModel(recordSet);
}

@PostMapping(value = "/bind")
public String metaDataBind(@RequestParam("type") String type,
public BindSqlView metaDataBind(@RequestParam("type") String type,
@RequestParam("metaData") String metaData,
@RequestParam("bind") String bind) {
if (logger.isDebugEnabled()) {
logger.debug("POST /bind params {metaData={}, bind={}}", metaData, bind);
}

if (metaData == null) {
return "";
final BindType bindType = BindType.of(type);
if (bindType == null) {
throw new IllegalArgumentException("Unknown Type:" + type);
}

List<String> bindValues;
String combinedResult = "";

if (type.equals("sql")) {
bindValues = parameterParser.parseOutputParameter(bind);
combinedResult = sqlParser.combineBindValues(metaData, bindValues);
} else if (type.equals("mongoJson")) {
bindValues = parameterJsonParser.parseOutputParameter(bind);
combinedResult = mongoJsonParser.combineBindValues(metaData, bindValues);
if (metaData == null) {
return new BindSqlView("");
}

final QueryService service = queryServiceFactory.getService(bindType);
final String bindedQuery = service.bind(metaData, bind);
if (logger.isDebugEnabled()) {
logger.debug("Combined result={}", combinedResult);
logger.debug("bindedQuery={}", bindedQuery);
}

if (type.equals("mongoJson")) {
return StringEscapeUtils.unescapeHtml4(combinedResult);
return new BindSqlView(bindedQuery);
}

public static class BindSqlView {
private final String bindedQuery;

public BindSqlView(String bindedQuery) {
this.bindedQuery = Objects.requireNonNull(bindedQuery, "bindedQuery");
}

return StringEscapeUtils.escapeHtml4(combinedResult);
public String getBindedQuery() {
return bindedQuery;
}
}
}
31 changes: 31 additions & 0 deletions web/src/main/java/com/navercorp/pinpoint/web/query/BindType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.navercorp.pinpoint.web.query;

import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;

public enum BindType {
SQL("sql"),
MONGO_JSON("mongoJson");

private static final Set<BindType> BIND_TYPE = EnumSet.allOf(BindType.class);

private final String typeName;

BindType(String typeName) {
this.typeName = Objects.requireNonNull(typeName, "typeName");
}

public String getTypeName() {
return typeName;
}

public static BindType of(String typeName) {
for (BindType bindType : BIND_TYPE) {
if (bindType.getTypeName().equalsIgnoreCase(typeName)) {
return bindType;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
* limitations under the License.
*/

package com.navercorp.pinpoint.web.util;
package com.navercorp.pinpoint.web.query;

import com.navercorp.pinpoint.common.util.CollectionUtils;
import com.navercorp.pinpoint.common.util.StringUtils;
import com.navercorp.pinpoint.web.util.MongoJsonParser;

import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -61,7 +62,7 @@ public String combineBindValues(String json, List<String> bindValues) {
}

int additionalSize = 0;
final Queue<String> bindValueQueue = new LinkedList<String>();
final Queue<String> bindValueQueue = new LinkedList<>();
for (String value : bindValues) {
bindValueQueue.add(value);
additionalSize += value.length();
Expand All @@ -70,7 +71,7 @@ public String combineBindValues(String json, List<String> bindValues) {
final int length = json.length();
final StringBuilder result = new StringBuilder(length + additionalSize);

Stack<Character> stack = new Stack<Character>();
Stack<Character> stack = new Stack<>();

boolean statusKey = true;
boolean inString = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.navercorp.pinpoint.web.query;

import org.apache.commons.text.StringEscapeUtils;

import java.util.Objects;

public class EscapeJsonFilter implements QueryService {
private final QueryService delegate;

public EscapeJsonFilter(QueryService delegate) {
this.delegate = Objects.requireNonNull(delegate, "delegate");
}

@Override
public String bind(String metaData, String bind) {
String bindedQuery = delegate.bind(metaData, bind);
return StringEscapeUtils.escapeJson(bindedQuery);
}

@Override
public BindType getBindType() {
return delegate.getBindType();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.navercorp.pinpoint.web.query;

import com.navercorp.pinpoint.web.util.MongoJsonParser;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class MongoQueryService implements QueryService {

private final MongoJsonParser mongoJsonParser = new DefaultMongoJsonParser();
private final OutputParameterMongoJsonParser parameterJsonParser = new OutputParameterMongoJsonParser();

@Override
public String bind(String metaData, String bind) {
List<String> bindValues = parameterJsonParser.parseOutputParameter(bind);
return mongoJsonParser.combineBindValues(metaData, bindValues);
}

@Override
public BindType getBindType() {
return BindType.MONGO_JSON;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package com.navercorp.pinpoint.web.util;
package com.navercorp.pinpoint.web.query;

import com.navercorp.pinpoint.common.util.StringUtils;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.navercorp.pinpoint.web.query;

public interface QueryService {
BindType getBindType();
String bind(String metaData, String bind);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.navercorp.pinpoint.web.query;

import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.stream.Stream;

@Component
public class QueryServiceFactory {

private final QueryService[] queryServices;

public QueryServiceFactory(QueryService[] services) {
Objects.requireNonNull(services, "services");

this.queryServices = Stream.of(services)
.map(this::wrapFilter)
.toArray(QueryService[]::new);
}

private QueryService wrapFilter(QueryService service) {
return new EscapeJsonFilter(service);
}

public QueryService getService(BindType bindType) {
Objects.requireNonNull(bindType, "bindType");

for (QueryService queryService : queryServices) {
if (queryService.getBindType().equals(bindType)) {
return queryService;
}
}
throw new IllegalArgumentException("Unknown BindType" + bindType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.navercorp.pinpoint.web.query;

import com.navercorp.pinpoint.common.profiler.sql.DefaultSqlParser;
import com.navercorp.pinpoint.common.profiler.sql.OutputParameterParser;
import com.navercorp.pinpoint.common.profiler.sql.SqlParser;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class SqlQueryService implements QueryService {

private final SqlParser sqlParser = new DefaultSqlParser();
private final OutputParameterParser parameterParser = new OutputParameterParser();

@Override
public String bind(String metaData, String bind) {
List<String> bindValues = parameterParser.parseOutputParameter(bind);
return sqlParser.combineBindValues(metaData, bindValues);
}

@Override
public BindType getBindType() {
return BindType.SQL;
}
}
1 change: 1 addition & 0 deletions web/src/main/resources/applicationContext-web.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
com.navercorp.pinpoint.web.filter,
com.navercorp.pinpoint.web.view,
com.navercorp.pinpoint.web.applicationmap,
com.navercorp.pinpoint.web.query,
com.navercorp.pinpoint.common.server.bo,
com.navercorp.pinpoint.common.server.util,
com.navercorp.pinpoint.common.server.config" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
* limitations under the License.
*/

package com.navercorp.pinpoint.web.util;
package com.navercorp.pinpoint.web.query;

import com.navercorp.pinpoint.web.util.MongoJsonParser;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Assert;
import org.junit.Test;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

import java.util.List;

Expand Down
Loading

0 comments on commit 57f7d0d

Please sign in to comment.