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
  • Loading branch information
feelform committed Nov 28, 2022
1 parent 7497ee5 commit b90c840
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ public void insert(ApiMetaDataBo apiMetaData) {
buffer.putInt(apiMetaData.getLineNumber());
buffer.putInt(apiMetaData.getMethodTypeEnum().getCode());

String location = apiMetaData.getLocation();
if (location != null) {
buffer.putPrefixedString(location);
}

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 @@ -33,6 +33,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 +43,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 +73,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 +88,46 @@ 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) {
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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,16 @@ public List<ApiMetaDataBo> mapRow(Result result, int rowNum) throws Exception {
if (buffer.hasRemaining()) {
methodTypeEnum = MethodTypeEnum.valueOf(buffer.readInt());
}
String location = null;
if (buffer.hasRemaining()) {
location = buffer.readPrefixedString();
}

ApiMetaDataBo apiMetaDataBo = new ApiMetaDataBo(key.getAgentId(), key.getAgentStartTime(), key.getId(), lineNumber, methodTypeEnum, apiInfo);
ApiMetaDataBo.Builder builder = new ApiMetaDataBo.Builder(key.getAgentId(), key.getAgentStartTime(), key.getId(), lineNumber, methodTypeEnum, apiInfo);
if (location != null) {
builder.setLocation(location);
}
ApiMetaDataBo apiMetaDataBo = builder.build();

apiMetaDataList.add(apiMetaDataBo);
if (logger.isDebugEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.navercorp.pinpoint.web.mapper;

import com.navercorp.pinpoint.common.buffer.AutomaticBuffer;
import com.navercorp.pinpoint.common.buffer.Buffer;
import com.navercorp.pinpoint.common.server.bo.ApiMetaDataBo;
import com.navercorp.pinpoint.common.server.bo.MethodTypeEnum;
import com.navercorp.pinpoint.common.server.bo.serializer.metadata.MetadataEncoder;
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.CellUtil;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class ApiMetaDataMapperTest {
// 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 testMapRow() throws Exception {
ApiMetaDataBo expected = 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();

RowKeyDistributorByHashPrefix givenRowKeyDistributorByHashPrefix = new DistributorConfiguration().getMetadataRowKeyDistributor();
final byte[] rowKey = givenRowKeyDistributorByHashPrefix.getDistributedKey(new MetadataEncoder().encodeRowKey(expected));
final Buffer buffer = new AutomaticBuffer(64);
final String api = expected.getApiInfo();
buffer.putPrefixedString(api);
buffer.putInt(expected.getLineNumber());
buffer.putInt(expected.getMethodTypeEnum().getCode());

String location = expected.getLocation();
if (location != null) {
buffer.putPrefixedString(location);
}
byte[] bufferArray = buffer.getBuffer();
byte[] valueArray = Bytes.toBytes(1L);
Cell cell = CellUtil.createCell(HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, bufferArray, HConstants.LATEST_TIMESTAMP, KeyValue.Type.Maximum.getCode(), valueArray);

Result mockedResult = mock(Result.class);
when(mockedResult.rawCells()).thenReturn(new Cell[] { cell });
when(mockedResult.getRow()).thenReturn(rowKey);

ApiMetaDataMapper dut = new ApiMetaDataMapper(givenRowKeyDistributorByHashPrefix);
ApiMetaDataBo actual = dut.mapRow(mockedResult, 0).get(0);

assertThat(actual).extracting("agentId", "startTime", "apiId", "apiInfo", "lineNumber", "methodTypeEnum", "location")
.contains(expected.getAgentId(), expected.getAgentStartTime(), expected.getId(), expected.getApiInfo(), expected.getLineNumber(), expected.getMethodTypeEnum(), expected.getLocation());
}
}

0 comments on commit b90c840

Please sign in to comment.