Skip to content

Commit

Permalink
[pinpoint-apm#9380] Supports Line number and location in Callstack
Browse files Browse the repository at this point in the history
Add Line number and location in APIMetaDataBO
If Line number is null, value `0`
location value is nullable
* Warning:(91, 29) 'StringBuilder sb' can be replaced with 'String'
* Hbase must save data with null because of saved data order
* Add linenumber and location in TransactionInfoViewModel
  • Loading branch information
feelform authored and emeroad committed Dec 21, 2022
1 parent 2f706e2 commit 0eb0596
Show file tree
Hide file tree
Showing 24 changed files with 1,141 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void insert(ApiMetaDataBo apiMetaData) {
buffer.putPrefixedString(api);
buffer.putInt(apiMetaData.getLineNumber());
buffer.putInt(apiMetaData.getMethodTypeEnum().getCode());
buffer.putPrefixedString(apiMetaData.getLocation());

final byte[] apiMetaDataBytes = buffer.getBuffer();
put.addColumn(description.getName(), description.QUALIFIER_SIGNATURE, apiMetaDataBytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void handleRequest(ServerRequest<GeneratedMessageV3> serverRequest, Serve
}
}

private GeneratedMessageV3 handleApiMetaData(final PApiMetaData apiMetaData) {
GeneratedMessageV3 handleApiMetaData(final PApiMetaData apiMetaData) {
if (isDebug) {
logger.debug("Handle PApiMetaData={}", MessageFormatUtils.debugLog(apiMetaData));
}
Expand All @@ -76,8 +76,10 @@ private GeneratedMessageV3 handleApiMetaData(final PApiMetaData apiMetaData) {

final MethodTypeEnum type = MethodTypeEnum.defaultValueOf(apiMetaData.getType());

final ApiMetaDataBo apiMetaDataBo = new ApiMetaDataBo(agentId, agentStartTime, apiMetaData.getApiId(),
line, type, apiMetaData.getApiInfo());
final ApiMetaDataBo apiMetaDataBo = new ApiMetaDataBo.Builder(agentId, agentStartTime, apiMetaData.getApiId(),
line, type, apiMetaData.getApiInfo())
.setLocation(apiMetaData.getLocation())
.build();

this.apiMetaDataService.insert(apiMetaDataBo);
return PResult.newBuilder().setSuccess(true).build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.navercorp.pinpoint.collector.dao.hbase;

import com.navercorp.pinpoint.common.hbase.HbaseColumnFamily;
import com.navercorp.pinpoint.common.hbase.HbaseOperations2;
import com.navercorp.pinpoint.common.hbase.TableNameProvider;
import com.navercorp.pinpoint.common.server.bo.ApiMetaDataBo;
import com.navercorp.pinpoint.common.server.bo.MethodTypeEnum;
import com.navercorp.pinpoint.common.server.hbase.DistributorConfiguration;
import com.sematext.hbase.wd.RowKeyDistributorByHashPrefix;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.client.Put;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.assertj.core.api.Assertions.assertThat;

public class HbaseApiMetaDataDaoTest {

// from node: ApiMetaDataBo{agentId='express-node-sample-id', startTime=1669280767548, apiId=12, apiInfo='express.Function.proto.get(path, callback)', lineNumber=169, methodTypeEnum=DEFAULT, location='/Users/workspace/pinpoint/@pinpoint-naver-apm/pinpoint-agent-node/samples/express/src/routes/index.js'}
@Test
public void testInsert() {
HbaseOperations2 mockedHbaseTemplate = mock(HbaseOperations2.class);
TableNameProvider mockedProvider = mock(TableNameProvider.class);
DistributorConfiguration givenConfiguration = new DistributorConfiguration();
RowKeyDistributorByHashPrefix givenRowKeyDistributorByHashPrefix = givenConfiguration.getMetadataRowKeyDistributor();
HbaseApiMetaDataDao dut = new HbaseApiMetaDataDao(mockedHbaseTemplate, mockedProvider, givenRowKeyDistributorByHashPrefix);

doAnswer((invocation) -> {
Put actual = invocation.getArgument(1);
List<Cell> actualCells = actual.get(HbaseColumnFamily.API_METADATA_API.getName(), HbaseColumnFamily.API_METADATA_API.QUALIFIER_SIGNATURE);
assertThat(actualCells).hasSize(1);
return null;
}).when(mockedHbaseTemplate).put(any(), any(Put.class));

ApiMetaDataBo stub = new ApiMetaDataBo.Builder("express-node-sample-id", 1669280767548L, 12, 169, MethodTypeEnum.DEFAULT, "express.Function.proto.get(path, callback)")
.setLocation("/Users/workspace/pinpoint/@pinpoint-naver-apm/pinpoint-agent-node/samples/express/src/routes/index.js")
.build();
dut.insert(stub);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.navercorp.pinpoint.collector.handler.grpc;

import com.navercorp.pinpoint.collector.service.ApiMetaDataService;
import com.navercorp.pinpoint.common.server.bo.ApiMetaDataBo;
import com.navercorp.pinpoint.common.server.bo.MethodTypeEnum;
import com.navercorp.pinpoint.grpc.Header;
import com.navercorp.pinpoint.grpc.server.ServerContext;
import com.navercorp.pinpoint.grpc.trace.PApiMetaData;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import java.util.Collections;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;

public class GrpcApiMetaDataHandlerTest {
// ApiMetaDataBo{agentId='express-node-sample-id', startTime=1668495162817, apiId=11, apiInfo='express.Function.proto.get(path, callback)', lineNumber=177, methodTypeEnum=DEFAULT}
// from Node agent [11, 'express.Function.proto.get(path, callback)', 24, null, '/Users/workspace/pinpoint/@pinpoint-naver-apm/pinpoint-agent-node/samples/express/src/routes/index.js']
@Test
public void stubToApiMetaData() {
ApiMetaDataService mockedService = mock(ApiMetaDataService.class);
GrpcApiMetaDataHandler dut = new GrpcApiMetaDataHandler(mockedService);

PApiMetaData actualStub = PApiMetaData.newBuilder()
.setApiId(13)
.setApiInfo("express.Function.proto.get(path, callback)")
.setLine(177)
.setType(MethodTypeEnum.DEFAULT.getCode())
.setLocation("/Users/workspace/pinpoint/@pinpoint-naver-apm/pinpoint-agent-node/samples/express/src/routes/index.js")
.build();
try (MockedStatic<ServerContext> mocked = mockStatic(ServerContext.class)) {
mocked.when(ServerContext::getAgentInfo).thenReturn(new Header("name", "express-node-sample-id", "agentName", "applicationName", 0, 1668495162817L, 0, Collections.emptyList()));
doAnswer((invocation) -> {
ApiMetaDataBo actual = invocation.getArgument(0);
assertThat(actual).extracting("agentId", "startTime", "apiId", "apiInfo", "lineNumber", "methodTypeEnum", "location")
.contains("express-node-sample-id", 1668495162817L, 13, "express.Function.proto.get(path, callback)", 177, MethodTypeEnum.DEFAULT, "/Users/workspace/pinpoint/@pinpoint-naver-apm/pinpoint-agent-node/samples/express/src/routes/index.js");
return null;
}).when(mockedService).insert(any());

dut.handleApiMetaData(actualStub);

mocked.verify(ServerContext::getAgentInfo);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mock-maker-inline
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,26 @@ public String toString() {
", isAuthorized=" + isAuthorized +
'}';
}

public static class Builder {
private final int key;
private final Object value;
private boolean isAuthorized;

public Builder(int key, Object value) {
this.key = key;
this.value = value;
}

public Builder isAuthorized(boolean isAuthorized) {
this.isAuthorized = isAuthorized;
return this;
}

public AnnotationBo build() {
AnnotationBo result = new AnnotationBo(this.key, this.value);
result.setAuthorized(this.isAuthorized);
return result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.navercorp.pinpoint.common.server.bo.serializer.metadata.MetaDataRowKey;
import com.navercorp.pinpoint.common.util.LineNumber;
import com.navercorp.pinpoint.common.util.StringUtils;

import java.util.Objects;

Expand All @@ -33,6 +34,7 @@ public class ApiMetaDataBo implements MetaDataRowKey {
private final String apiInfo;
private final int lineNumber;
private final MethodTypeEnum methodTypeEnum;
private String location;

public ApiMetaDataBo(String agentId, long startTime, int apiId, int lineNumber,
MethodTypeEnum methodTypeEnum, String apiInfo) {
Expand All @@ -42,6 +44,7 @@ public ApiMetaDataBo(String agentId, long startTime, int apiId, int lineNumber,
this.lineNumber = lineNumber;
this.apiInfo = apiInfo;
this.methodTypeEnum = Objects.requireNonNull(methodTypeEnum, "methodTypeEnum");
this.location = null;
}

@Override
Expand Down Expand Up @@ -71,6 +74,10 @@ public MethodTypeEnum getMethodTypeEnum() {
return methodTypeEnum;
}

public String getLocation() {
return location;
}

public String getDescription() {
if (LineNumber.isLineNumber(lineNumber)) {
return apiInfo + ":" + lineNumber;
Expand All @@ -82,14 +89,49 @@ public String getDescription() {

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ApiMetaDataBo{");
sb.append("agentId='").append(agentId).append('\'');
sb.append(", startTime=").append(startTime);
sb.append(", apiId=").append(apiId);
sb.append(", apiInfo='").append(apiInfo).append('\'');
sb.append(", lineNumber=").append(lineNumber);
sb.append(", methodTypeEnum=").append(methodTypeEnum);
sb.append('}');
return sb.toString();
return "ApiMetaDataBo{" +
"agentId='" + agentId + '\'' +
", startTime=" + startTime +
", apiId=" + apiId +
", apiInfo='" + apiInfo + '\'' +
", lineNumber=" + lineNumber +
", methodTypeEnum=" + methodTypeEnum +
", location='" + location + '\'' +
'}';
}

public static class Builder {
private final String agentId;
private final long startTime;
private final int apiId;
private final int lineNumber;
private final MethodTypeEnum methodTypeEnum;
private final String apiInfo;
private String location;

public Builder(String agentId, long startTime, int apiId, int lineNumber,
MethodTypeEnum methodTypeEnum, String apiInfo) {
this.agentId = agentId;
this.startTime = startTime;
this.apiId = apiId;
this.lineNumber = lineNumber;
this.methodTypeEnum = methodTypeEnum;
this.apiInfo = apiInfo;
this.location = null;
}

public Builder setLocation(String location) {
if (StringUtils.isEmpty(location)) {
return this;
}
this.location = location;
return this;
}

public ApiMetaDataBo build() {
ApiMetaDataBo result = new ApiMetaDataBo(this.agentId, this.startTime, this.apiId, this.lineNumber, this.methodTypeEnum, this.apiInfo);
result.location = this.location;
return result;
}
}
}
Loading

0 comments on commit 0eb0596

Please sign in to comment.