diff --git a/README.md b/README.md new file mode 100644 index 000000000..b0be57ff0 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# pinpoint-commons diff --git a/SPAN Performance.txt b/SPAN Performance.txt new file mode 100644 index 000000000..b7aa44889 --- /dev/null +++ b/SPAN Performance.txt @@ -0,0 +1,37 @@ +처음에 한 4k나옴. +TraceID를 +3114 + +annotation을 코드로 변경. +2638 + +Span에 있는 데이터를 좀더 정형화함. +read size:2445 +로 줄음. +대신 추가로 서버 정보를 더 넘기면 약간은 더 증가할듯하다. + +desinationId, destinationAddress로 더 fix하게되어 +jdbc url이 중복되고 있어 개선하면 데이터 사이즈가 상당히 줄듯함. + +jdbc에서 rpc name제거시. +1865 + +-Xms512m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128m + +com.nhn.pinpoint.collector.TomcatProfileDataReceiverMain + +릴리즈전 + + +1.0.4 annotation에 api레코딩 하였을 경우 +3687 +635 +- 4250 +annotation 말고 apiid를 span이나. spanevent에 넣고, traceAgentId를 agentid와 같을 경우 레코딩하지 않도록 변경한 경우. +5%성능향상. +- 4023 +mysql 최초 connect시 이벤트가 30개 이상 발생한 경우 + +IntString으로 멀티 Value를 가질수 있도록 수정후. +Sql에 대한 metadata를 던질 때, SqlId와 Sql-param을 같이 던지게 변경함. +- 4002 \ No newline at end of file diff --git a/VersionScript.groovy b/VersionScript.groovy new file mode 100644 index 000000000..f744fbf80 --- /dev/null +++ b/VersionScript.groovy @@ -0,0 +1,22 @@ +println("==== Creating Version.java ===="); +File mainDir = new File("src/main"); +if (mainDir.exists() && !mainDir.isDirectory()) { + println("Main dir does not exist, wont create Version.java!"); + return; +} +File versionFile = new File("src/main/java/com/nhn/pinpoint/common/Version.java"); +if (versionFile.exists() && versionFile.isDirectory()) { + println("Version file exists and is directory! Wont overwrite"); + return; +} +if (versionFile.exists()) { + println("Version file already exists, overwriting!"); +} +println("Creating Version.java File"); +BufferedWriter writer = new BufferedWriter(new FileWriter(versionFile)); + +writer.write("package com.nhn.pinpoint.common;\n"); +writer.write("public final class Version {\n"); +writer.write(" public static final String VERSION = \"${project.version}\";\n"); +writer.write("}"); +writer.close(); \ No newline at end of file diff --git a/alterMapStatisticsCallee.sh b/alterMapStatisticsCallee.sh new file mode 100644 index 000000000..e014e82cd --- /dev/null +++ b/alterMapStatisticsCallee.sh @@ -0,0 +1,7 @@ +disable 'ApplicationMapStatisticsCallee' +alter 'ApplicationMapStatisticsCallee', {NAME => 'D', TTL => 5184000, VERSION => 1} +enable 'ApplicationMapStatisticsCallee' + +disable 'ApplicationMapStatisticsCallee' +alter 'ApplicationMapStatisticsCallee', {NAME => 'D', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY'} +enable 'ApplicationMapStatisticsCallee' diff --git a/build.bat b/build.bat new file mode 100644 index 000000000..bea130034 --- /dev/null +++ b/build.bat @@ -0,0 +1 @@ +mvn package install -Dmaven.test.skip -Dthrift.executable=D:\workspace\thrift-win\thrift.exe \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..6323727af --- /dev/null +++ b/build.sh @@ -0,0 +1,12 @@ +#! /bin/bash +# common은 install만 하면 된다. +# bootstrap이 빌드될 때 common의 class를 bootstrap.jar에 포함시킴. + +# common lib +mvn clean eclipse:eclipse package dependency:copy-dependencies install -Dmaven.test.skip -Dthrift.executable.property=/Users/netspider/DEV-TOOLS/thrift-0.9.0/bin/thrift + +rc=$? +if [[ $rc != 0 ]] ; then + echo "BUILD FAILED $rc" + exit $rc +fi \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 000000000..239773b53 --- /dev/null +++ b/build.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compile.txt b/compile.txt new file mode 100644 index 000000000..658d35663 --- /dev/null +++ b/compile.txt @@ -0,0 +1,5 @@ +mvn package -Dmaven.test.skip +이렇게 하면 그냥 패키징 + +mvn package -Dmaven.test.skip -P withThrift +antrun 하고 패키징 \ No newline at end of file diff --git a/findbugs-exclude.xml b/findbugs-exclude.xml new file mode 100644 index 000000000..a4b4e8251 --- /dev/null +++ b/findbugs-exclude.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/flush_htable.sh b/flush_htable.sh new file mode 100644 index 000000000..b8b88219b --- /dev/null +++ b/flush_htable.sh @@ -0,0 +1,20 @@ +#!/bin/sh +exec hbase shell < 'Info', COMPRESSION => 'SNAPPY' } +create 'AgentStat', { NAME => 'S', TTL => 5184000, COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'ApplicationIndex', { NAME => 'Agents', COMPRESSION => 'SNAPPY' } + +create 'StringMetaData', { NAME => 'Str', COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'SqlMetaData', { NAME => 'Sql', COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'ApiMetaData', { NAME => 'Api', COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} + +create 'Traces', { NAME => 'S', TTL => 5184000, COMPRESSION => 'SNAPPY' }, { NAME => 'A', TTL => 5184000, COMPRESSION => 'SNAPPY' }, { NAME => 'T', TTL => 5184000, COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x24\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x25\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x26\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x29\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'ApplicationTraceIndex', { NAME => 'I', TTL => 5184000, COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} + +create 'ApplicationMapStatisticsCaller', { NAME => 'C', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY' } +create 'ApplicationMapStatisticsCallee', { NAME => 'C', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY' }, { NAME => 'D', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY'} +create 'ApplicationMapStatisticsSelf', { NAME => 'C', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY' } + +create 'ApplicationStatistics', { NAME => 'C', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY' } +create 'HostApplicationMap', { NAME => 'M', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY' } +create 'HostApplicationMap_Ver2', { NAME => 'M', TTL => 5184000, VERSION => 1, COMPRESSION => 'SNAPPY' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} + +list +EOF diff --git a/pinpoint-hbase-reset.sh b/pinpoint-hbase-reset.sh new file mode 100644 index 000000000..7af3ae135 --- /dev/null +++ b/pinpoint-hbase-reset.sh @@ -0,0 +1,63 @@ +exec ../pinpoint-testbed/hbase-0.94.0/bin/hbase shell < 'Info' } +create 'AgentStat', { NAME => 'S', TTL => 5184000 }, {SPLITS=>["\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'ApplicationIndex', { NAME => 'Agents' } + +create 'StringMetaData', { NAME => 'Str' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'SqlMetaData', { NAME => 'Sql' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'ApiMetaData', { NAME => 'Api' }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} + +create 'Traces', { NAME => 'S', TTL => 5184000 }, { NAME => 'A', TTL => 5184000 }, { NAME => 'T', TTL => 5184000 }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x19\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x24\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x25\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x26\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x27\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x29\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x35\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x39\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x3f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} +create 'ApplicationTraceIndex', { NAME => 'I', TTL => 5184000 }, {SPLITS=>["\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} + +create 'ApplicationMapStatisticsCaller', { NAME => 'C', TTL => 5184000, VERSION => 1 } +create 'ApplicationMapStatisticsCallee', { NAME => 'C', TTL => 5184000, VERSION => 1 }, { NAME => 'D', TTL => 5184000, VERSION => 1 } +create 'ApplicationMapStatisticsSelf', { NAME => 'C', TTL => 5184000, VERSION => 1 } + +create 'ApplicationStatistics', { NAME => 'C', TTL => 5184000, VERSION => 1 } + +create 'HostApplicationMap', { NAME => 'M', TTL => 5184000, VERSION => 1 } +create 'HostApplicationMap_Ver2', { NAME => 'M', TTL => 5184000, VERSION => 1 }, {SPLITS=>["\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00","\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]} + +list +EOF diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..9b4192a7b --- /dev/null +++ b/pom.xml @@ -0,0 +1,728 @@ + + 4.0.0 + com.nhn.pinpoint + pinpoint-commons + 1.0.2 + pinpoint-commons + jar + + + 3.2.3.RELEASE + 1.7.5 + 1.9.13 + + + + + nhn.release.repository + http://repo.nhncorp.com/maven2 + + false + + + true + + + + nhn.snapshot.repository + http://repo.nhncorp.com/m2-snapshot-repository + + + + true + + + false + + + + cloudera + https://repository.cloudera.com/artifactory/cloudera-repos/ + + + + + + com.nhn.pinpoint + pinpoint-thrift + 1.0.2 + provided + + + + org.apache.hadoop + hadoop-common + 2.0.0-cdh4.5.0 + compile + true + + + org.apache.hadoop + hadoop-annotations + + + commons-cli + commons-cli + + + xmlenc + xmlenc + + + commons-httpclient + commons-httpclient + + + commons-codec + commons-codec + + + commons-io + commons-io + + + commons-net + commons-net + + + javax.servlet + servlet-api + + + org.mortbay.jetty + jetty + + + org.mortbay.jetty + jetty-util + + + com.sun.jersey + jersey-core + + + com.sun.jersey + jersey-json + + + jersey-server + com.sun.jersey + + + jsp-api + javax.servlet.jsp + + + commons-el + commons-el + + + log4j + log4j + + + net.java.dev.jets3t + jets3t + + + commons-lang + commons-lang + + + commons-configuration + commons-configuration + + + org.apache.avro + avro + + + com.google.protobuf + protobuf-java + + + org.apache.zookeeper + zookeeper + + + com.jcraft + jsch + + + com.google.guava + guava + + + org.apache.commons + commons-math + + + commons-logging + commons-logging + + + net.sf.kosmosfs + kfs + + + tomcat + jasper-compiler + + + tomcat + jasper-runtime + + + + + + org.apache.hadoop + hadoop-core + 2.0.0-mr1-cdh4.5.0 + compile + true + + + commons-cli + commons-cli + + + xmlenc + xmlenc + + + commons-codec + commons-codec + + + commons-net + commons-net + + + org.codehaus.jackson + jackson-core-asl + + + org.codehaus.jackson + jackson-mapper-asl + + + javax.servlet.jsp + jsp-api + + + commons-el + commons-el + + + net.java.dev.jets3t + jets3t + + + javax.servlet + servlet-api + + + hsqldb + hsqldb + + + org.apache.zookeeper + zookeeper + + + tomcat + jasper-runtime + + + tomcat + jasper-compiler + + + org.eclipse.jdt + core + + + commons-httpclient + commons-httpclient + + + org.mortbay.jetty + jetty + + + jetty-util + org.mortbay.jetty + + + + + + org.apache.hbase + hbase + 0.94.6-cdh4.5.0 + compile + true + + + org.mortbay.jetty + jetty + + + org.mortbay.jetty + jetty-util + + + org.mortbay.jetty + jsp-2.1 + + + org.mortbay.jetty + jsp-api-2.1 + + + org.mortbay.jetty + servlet-api-2.5 + + + tomcat + jasper-runtime + + + tomcat + jasper-compiler + + + jersey-core + com.sun.jersey + + + com.sun.jersey + jersey-json + + + com.sun.jersey + jersey-server + + + javax.xml.bind + jaxb-api + + + stax + stax-api + + + commons-logging + commons-logging + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + slf4j-api + org.slf4j + + + + netty + org.jboss.netty + + + org.jruby + jruby-complete + + + org.apache.thrift + libthrift + + + commons-cli + commons-cli + + + org.jamon + jamon-runtime + + + com.yammer.metrics + metrics-core + + + commons-httpclient + commons-httpclient + + + + + + + com.sematext.hbasewd + hbasewd + 0.1.0 + compile + true + + + + org.apache.thrift + libthrift + 0.9.1 + compile + true + + + org.apache.httpcomponents + httpclient + + + org.apache.httpcomponents + httpcore + + + org.slf4j + slf4j-api + + + + + + org.springframework + spring-core + ${spring.version} + compile + true + + + commons-logging + commons-logging + + + + + org.springframework + spring-orm + ${spring.version} + compile + true + + + org.springframework.data + spring-data-hadoop + 1.0.2.RELEASE + compile + true + + + org.springframework + spring-context-support + + + org.springframework + spring-core + + + org.apache.hbase + hbase + + + slf4j-api + org.slf4j + + + slf4j-log4j12 + org.slf4j + + + org.apache.hadoop + hadoop-streaming + + + org.apache.hadoop + hadoop-tools + + + + + + + org.codehaus.jackson + jackson-core-asl + ${codehaus.jackson.version} + true + + + org.codehaus.jackson + jackson-mapper-asl + ${codehaus.jackson.version} + true + + + org.codehaus.jackson + jackson-xc + ${codehaus.jackson.version} + true + + + org.codehaus.jackson + jackson-jaxrs + ${codehaus.jackson.version} + true + + + + + org.slf4j + slf4j-api + ${slf4j.version} + compile + true + + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + test + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + test + + + log4j + log4j + 1.2.16 + test + + + + + + + + + + + + junit + junit + 4.8.2 + test + + + org.hamcrest + hamcrest-library + 1.3 + test + + + org.mockito + mockito-all + 1.8.4 + test + + + + + + + ${basedir}/src/main/java + + **/*.java + + + + true + ${basedir}/src/main/resources + + + + + + ${basedir}/src/test/java + + **/*.java + + + + true + ${basedir}/src/test/resources + + + + + + maven-resources-plugin + 2.6 + + UTF-8 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + true + + 1.6 + 1.6 + true + true + UTF-8 + true + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + + **/Abstract* + **/*$* + **/TestInterceptor*.java + **/Mock*.java + + + + + + + + + + + + + org.codehaus.gmaven + gmaven-plugin + 1.5 + + + generate-sources + + execute + + + ${pom.basedir}/VersionScript.groovy + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.5.2 + + + + com.atlassian.maven.plugins + maven-clover2-plugin + 3.0.2 + + UTF-8 + 1.6 + true + true + false + clover.license + false + false + + + + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 2.5.2 + + findbugs-exclude.xml + true + ${project.build.directory}/findbugs + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.0.1 + + + true + UTF-8 + 1.6 + + + + + + + + + + + com.atlassian.maven.plugins + maven-clover2-plugin + 3.0.2 + + true + clover.license + UTF-8 + 1.6 + + + + + + + + + klocwork + + + + com.klocwork.ps + kwmaven + + ${KWINJECT_OUT_PATH} + + + + validate + + run + + + + + + + + + + diff --git a/src/main/java/com/nhn/pinpoint/common/AnnotationKey.java b/src/main/java/com/nhn/pinpoint/common/AnnotationKey.java new file mode 100644 index 000000000..69faf95c1 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/AnnotationKey.java @@ -0,0 +1,225 @@ +package com.nhn.pinpoint.common; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author netspider + * @author emeroad + */ +public enum AnnotationKey { + // 가변 인코딩을 사용하므로, 작은 숫자는 패킷에 전송 되는 데이터로 위주로 사용하고 내부 사용 코드는 숫자를 크게 잡아야 한다. +// 2147483647 +// -2147483648 + +// @Deprecated // spanEvent와 span으로 apiId를 직접 이동 시킴. int 로 덤프 +// API_DID(10, "API-DID"), +// @Deprecated // 정적 api 코드를 제거해야 한다. API-DID만 사용할것. int로 덤프 +// API_ID(11, "API-ID"), +// api를 string으로 덤프하는 anntation 최초 개발시 사용함. 추후 이것도 없애야 될듯. + API(12, "API"), + API_METADATA(13, "API-METADATA"), + + // 정확한 에러 원인을 모를 경우. + ERROR_API_METADATA_ERROR(10000010, "API-METADATA-ERROR"), + // agentInfo를 못찾앗을 경우 + ERROR_API_METADATA_AGENT_INFO_NOT_FOUND(10000011, "API-METADATA-AGENT-INFO-NOT-FOUND"), + // agentInfo를 찾았으나 체크섬이 맞지 않는경우 + ERROR_API_METADATA_IDENTIFIER_CHECK_ERROR(10000012, "API-METADATA-IDENTIFIER-CHECK_ERROR"), + // meta data자체를 못찾은 경우. + ERROR_API_METADATA_NOT_FOUND(10000013, "API-METADATA-NOT-FOUND"), + // meta data의 동일 hashid가 존재할 경우 + ERROR_API_METADATA_DID_COLLSION(10000014, "API-METADATA-DID-COLLSION"), + // ERROR code 처리가 애매한데 ERROR_API_META_DATA_을 검색해서 ApiMetaDataError로 처리하였음. + // 자동 id + + SQL_ID(20, "SQL-ID"), + SQL(21, "SQL", true), + SQL_METADATA(22, "SQL-METADATA"), + SQL_PARAM(23, "SQL-PARAM"), + SQL_BINDVALUE(24, "SQL-BindValue", true), + + STRING_ID(30, "STRING_ID"), + + // HTTP_URL은 argument로 치환되므로 true가 아님.. + HTTP_URL(40, "http.url"), + HTTP_PARAM(41, "http.param", true), + HTTP_PARAM_ENTITY(42, "http.entity", true), + HTTP_COOKIE(45, "http.cookie", true), + // httpclient일때 post 파라미터 + + // ARCUS_COMMAND(50, "arcus.command"), + + NPC_URL(60, "npc.url"), + NPC_PARAM(61, "npc.param"), + NPC_CONNECT_OPTION(62, "npc.connect.options"), + + NIMM_OBJECT_NAME(70, "nimm.objectName"), + NIMM_METHOD_NAME(71, "nimm.methodName"), + NIMM_PARAM(72, "nimm.param"), + NIMM_CONNECT_OPTION(73, "nimm.connect.options"), + + ARGS0(-1, "args[0]"), + ARGS1(-2, "args[1]"), + ARGS2(-3, "args[2]"), + ARGS3(-4, "args[3]"), + ARGS4(-5, "args[4]"), + ARGS5(-6, "args[5]"), + ARGS6(-7, "args[6]"), + ARGS7(-8, "args[7]"), + ARGS8(-9, "args[8]"), + ARGS9(-10, "args[9]"), + ARGSN(-11, "args[N]"), + + CACHE_ARGS0(-30, "cached_args[0]"), + CACHE_ARGS1(-31, "cached_args[1]"), + CACHE_ARGS2(-32, "cached_args[2]"), + CACHE_ARGS3(-33, "cached_args[3]"), + CACHE_ARGS4(-34, "cached_args[4]"), + CACHE_ARGS5(-35, "cached_args[5]"), + CACHE_ARGS6(-36, "cached_args[6]"), + CACHE_ARGS7(-37, "cached_args[7]"), + CACHE_ARGS8(-38, "cached_args[8]"), + CACHE_ARGS9(-39, "cached_args[9]"), + CACHE_ARGSN(-40, "cached_args[N]"), + @Deprecated + EXCEPTION(-50, "Exception", true), + @Deprecated + EXCEPTION_CLASS(-51, "ExceptionClass"), + UNKNOWN(-9999, "UNKNOWN"); + + private final int code; + private final String value; + private final boolean viewInRecordSet; + + public final static int MAX_ARGS_SIZE = 10; + + private AnnotationKey(int code, String value) { + this(code, value, false); + } + + private AnnotationKey(int code, String value, boolean viewInRecordSet) { + this.code = code; + this.value = value; + this.viewInRecordSet = viewInRecordSet; + } + + public String getValue() { + return value; + } + + public int getCode() { + return code; + } + + public boolean isViewInRecordSet() { + return viewInRecordSet; + } + + private static final IntHashMap CODE_LOOKUP_TABLE = new IntHashMap(); + static { + initializeLookupTable(); + } + + public static void initializeLookupTable() { + AnnotationKey[] values = AnnotationKey.values(); + for (AnnotationKey name : values) { + AnnotationKey check = CODE_LOOKUP_TABLE.put(name.getCode(), name); + if (check != null) { + throw new IllegalStateException("duplicated code found. code:" + name.getCode()); + } + } + } + + public static AnnotationKey findAnnotationKey(int code) { + AnnotationKey annotationKey = CODE_LOOKUP_TABLE.get(code); + if (annotationKey == null) { + return UNKNOWN; + } + return annotationKey; + } + + public static AnnotationKey getArgs(int index) { + if (index < 0) { + throw new IllegalArgumentException("negative index:" + index); + } + switch (index) { + case 0: + return ARGS0; + case 1: + return ARGS1; + case 2: + return ARGS2; + case 3: + return ARGS3; + case 4: + return ARGS4; + case 5: + return ARGS5; + case 6: + return ARGS6; + case 7: + return ARGS7; + case 8: + return ARGS8; + case 9: + return ARGS9; + default: + return ARGSN; + } + } + + public static boolean isArgsKey(int index) { + if (index <= ARGS0.getCode() && index >= ARGSN.getCode()) { + return true; + } + return false; + } + + public static AnnotationKey getCachedArgs(int index) { + if (index < 0) { + throw new IllegalArgumentException("negative index:" + index); + } + switch (index) { + case 0: + return CACHE_ARGS0; + case 1: + return CACHE_ARGS1; + case 2: + return CACHE_ARGS2; + case 3: + return CACHE_ARGS3; + case 4: + return CACHE_ARGS4; + case 5: + return CACHE_ARGS5; + case 6: + return CACHE_ARGS6; + case 7: + return CACHE_ARGS7; + case 8: + return CACHE_ARGS8; + case 9: + return CACHE_ARGS9; + default: + return CACHE_ARGSN; + } + } + + public static boolean isCachedArgsKey(int index) { + if (index <= CACHE_ARGS0.getCode() && index >= CACHE_ARGSN.getCode()) { + return true; + } + return false; + } + + public static int cachedArgsToArgs(int index) { + if (!isCachedArgsKey(index)) { + throw new IllegalArgumentException("non CACHED_ARGS:" + index); + } + + final int cachedIndex = CACHE_ARGS0.getCode() - ARGS0.getCode(); + // 음수라서 -해야 된다. + return index - cachedIndex; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/HistogramSchema.java b/src/main/java/com/nhn/pinpoint/common/HistogramSchema.java new file mode 100644 index 000000000..92cc1180d --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/HistogramSchema.java @@ -0,0 +1,136 @@ +package com.nhn.pinpoint.common; + +/** + * @author emeroad + */ +public class HistogramSchema { + + public static final short VERY_SLOW_SLOT_TIME = 0; + + public static final short ERROR_SLOT_TIME = -1; + + public static final HistogramSchema FAST_SCHEMA; + public static final HistogramSchema NORMAL_SCHEMA; + + static { + FAST_SCHEMA = new HistogramSchema(1, (short)100, "100ms", (short)300, "300ms", (short)500, "500ms", "Slow", "Error"); + + NORMAL_SCHEMA = new HistogramSchema(2, (short)1000, "1s", (short)3000, "3s", (short)5000, "5s", "Slow", "Error"); + } + + private final int typeCode; + + private final HistogramSlot fastSlot; + private final HistogramSlot normalSlot; + private final HistogramSlot slowSlot; + private final HistogramSlot verySlowSlot; + private final HistogramSlot errorSlot; + + // 내부에서 생성한 FAST_SCHEMA, NORMAL등의 참조만 사용할것 + private HistogramSchema(int typeCode, short fast, String fastName, short normal, String normalName, short slow, String slowName, String verySlowName, String errorName) { + this.typeCode = typeCode; + this.fastSlot = new HistogramSlot(fast, SlotType.FAST, fastName); + this.normalSlot = new HistogramSlot(normal, SlotType.NORMAL, normalName); + this.slowSlot = new HistogramSlot(slow, SlotType.SLOW, slowName); + this.verySlowSlot = new HistogramSlot(VERY_SLOW_SLOT_TIME, SlotType.VERY_SLOW, verySlowName); + this.errorSlot = new HistogramSlot(ERROR_SLOT_TIME, SlotType.ERROR, errorName); + } + + public int getTypeCode() { + return typeCode; + } + + /** + * elapsedTime 기준으로 가장 적합한 슬롯을 찾는다. + * @param elapsedTime + * @return + */ + public HistogramSlot findHistogramSlot(int elapsedTime) { + if (elapsedTime == ERROR_SLOT_TIME) { + return errorSlot; + } + if (elapsedTime <= this.fastSlot.getSlotTime()) { + return fastSlot; + } + if (elapsedTime <= this.normalSlot.getSlotTime()) { + return normalSlot; + } + if (elapsedTime <= this.slowSlot.getSlotTime()) { + return slowSlot; + } + return verySlowSlot; + } + + public HistogramSlot getHistogramSlot(final short slotTime) { + if (slotTime == ERROR_SLOT_TIME) { + return errorSlot; + } + if (slotTime == this.fastSlot.getSlotTime()) { + return fastSlot; + } + if (slotTime == this.normalSlot.getSlotTime()) { + return normalSlot; + } + if (slotTime == this.slowSlot.getSlotTime()) { + return slowSlot; + } + if (slotTime == this.verySlowSlot.getSlotTime()) { + return slowSlot; + } + throw new IllegalArgumentException("HistogramSlot not found. slotTime:" + slotTime); + } + + public HistogramSlot getFastSlot() { + return fastSlot; + } + + public HistogramSlot getNormalSlot() { + return normalSlot; + } + + public HistogramSlot getSlowSlot() { + return slowSlot; + } + + public HistogramSlot getVerySlowSlot() { + return verySlowSlot; + } + + public HistogramSlot getErrorSlot() { + return errorSlot; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + typeCode; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + HistogramSchema other = (HistogramSchema) obj; + if (typeCode != other.typeCode) + return false; + return true; + } + + @Override + public String toString() { + return "HistogramSchema{" + + "typeCode=" + typeCode + + ", fastSlot=" + fastSlot + + ", normalSlot=" + normalSlot + + ", slowSlot=" + slowSlot + + ", verySlowSlot=" + verySlowSlot + + ", errorSlot=" + errorSlot + + '}'; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/HistogramSlot.java b/src/main/java/com/nhn/pinpoint/common/HistogramSlot.java new file mode 100644 index 000000000..e65b5a083 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/HistogramSlot.java @@ -0,0 +1,46 @@ +package com.nhn.pinpoint.common; + +/** + * @author emeroad + */ +public class HistogramSlot { + + private final short slotTime; + private final SlotType slotType; + private final String slotName; + + + public HistogramSlot(short slotTime, SlotType slotType, String slotName) { + if (slotType == null) { + throw new NullPointerException("slotType must not be null"); + } + if (slotName == null) { + throw new NullPointerException("slotName must not be null"); + } + this.slotTime = slotTime; + this.slotType = slotType; + this.slotName = slotName; + } + + public short getSlotTime() { + return slotTime; + } + + + public SlotType getSlotType() { + return slotType; + } + + public String getSlotName() { + return slotName; + } + + @Override + public String toString() { + return "HistogramSlot{" + + "slotTime=" + slotTime + + ", slotType=" + slotType + + ", slotName='" + slotName + '\'' + + '}'; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/IntHashMap.java b/src/main/java/com/nhn/pinpoint/common/IntHashMap.java new file mode 100644 index 000000000..d16a12f2b --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/IntHashMap.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +/* + * Note: originally released under the GNU LGPL v2.1, + * but rereleased by the original author under the ASF license (above). + */ +package com.nhn.pinpoint.common; + +/** + *

A hash map that uses primitive ints for the key rather than objects.

+ * + *

Note that this class is for internal optimization purposes only, and may + * not be supported in future releases of Apache Commons Lang. Utilities of + * this sort may be included in future releases of Apache Commons Collections.

+ * + * @author Apache Software Foundation + * @author Justin Couch + * @author Alex Chaffee (alex@apache.org) + * @since 2.0 + * @version $Revision$ + * @see java.util.HashMap + */ +// 내부 튜닝용 가져다 사용하지 말것 +public class IntHashMap { + + /** + * The hash table data. + */ + private transient Entry table[]; + + /** + * The total number of entries in the hash table. + */ + private transient int count; + + /** + * The table is rehashed when its size exceeds this threshold. (The + * value of this field is (int)(capacity * loadFactor).) + * + * @serial + */ + private int threshold; + + /** + * The load factor for the hashtable. + * + * @serial + */ + private final float loadFactor; + + /** + *

Innerclass that acts as a datastructure to create a new entry in the + * table.

+ */ + private static class Entry { + final int hash; + final int key; // TODO not read; seems to be always same as hash + T value; + Entry next; + + /** + *

Create a new entry with the given values.

+ * + * @param hash The code used to hash the object with + * @param key The key used to enter this in the table + * @param value The value for this key + * @param next A reference to the next entry in the table + */ + protected Entry(int hash, int key, T value, Entry next) { + this.hash = hash; + this.key = key; + this.value = value; + this.next = next; + } + } + + /** + *

Constructs a new, empty hashtable with a default capacity and load + * factor, which is 20 and 0.75 respectively.

+ */ + public IntHashMap() { + this(20, 0.75f); + } + + /** + *

Constructs a new, empty hashtable with the specified initial capacity + * and default load factor, which is 0.75.

+ * + * @param initialCapacity the initial capacity of the hashtable. + * @throws IllegalArgumentException if the initial capacity is less + * than zero. + */ + public IntHashMap(int initialCapacity) { + this(initialCapacity, 0.75f); + } + + /** + *

Constructs a new, empty hashtable with the specified initial + * capacity and the specified load factor.

+ * + * @param initialCapacity the initial capacity of the hashtable. + * @param loadFactor the load factor of the hashtable. + * @throws IllegalArgumentException if the initial capacity is less + * than zero, or if the load factor is nonpositive. + */ + public IntHashMap(int initialCapacity, float loadFactor) { + super(); + if (initialCapacity < 0) { + throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); + } + if (loadFactor <= 0) { + throw new IllegalArgumentException("Illegal Load: " + loadFactor); + } + if (initialCapacity == 0) { + initialCapacity = 1; + } + + this.loadFactor = loadFactor; + table = new Entry[initialCapacity]; + threshold = (int) (initialCapacity * loadFactor); + } + + /** + *

Returns the number of keys in this hashtable.

+ * + * @return the number of keys in this hashtable. + */ + public int size() { + return count; + } + + /** + *

Tests if this hashtable maps no keys to values.

+ * + * @return true if this hashtable maps no keys to values; + * false otherwise. + */ + public boolean isEmpty() { + return count == 0; + } + + + /** + *

Returns the value to which the specified key is mapped in this map.

+ * + * @param key a key in the hashtable. + * @return the value to which the key is mapped in this hashtable; + * null if the key is not mapped to any value in + * this hashtable. + * @see #put(int, T) + */ + public T get(int key) { + Entry tab[] = table; + int hash = key; + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index]; e != null; e = e.next) { + if (e.hash == hash) { + return e.value; + } + } + return null; + } + + /** + *

Increases the capacity of and internally reorganizes this + * hashtable, in order to accommodate and access its entries more + * efficiently.

+ * + *

This method is called automatically when the number of keys + * in the hashtable exceeds this hashtable's capacity and load + * factor.

+ */ + protected void rehash() { + int oldCapacity = table.length; + Entry oldMap[] = table; + + int newCapacity = oldCapacity * 2 + 1; + Entry newMap[] = new Entry[newCapacity]; + + threshold = (int) (newCapacity * loadFactor); + table = newMap; + + for (int i = oldCapacity; i-- > 0;) { + for (Entry old = oldMap[i]; old != null;) { + Entry e = old; + old = old.next; + + int index = (e.hash & 0x7FFFFFFF) % newCapacity; + e.next = newMap[index]; + newMap[index] = e; + } + } + } + + /** + *

Maps the specified key to the specified + * value in this hashtable. The key cannot be + * null.

+ * + *

The value can be retrieved by calling the get method + * with a key that is equal to the original key.

+ * + * @param key the hashtable key. + * @param value the value. + * @return the previous value of the specified key in this hashtable, + * or null if it did not have one. + * @throws NullPointerException if the key is null. + * @see #get(int) + */ + public T put(int key, T value) { + // Makes sure the key is not already in the hashtable. + Entry tab[] = table; + int hash = key; + int index = (hash & 0x7FFFFFFF) % tab.length; + for (Entry e = tab[index]; e != null; e = e.next) { + if (e.hash == hash) { + T old = e.value; + e.value = value; + return old; + } + } + + if (count >= threshold) { + // Rehash the table if the threshold is exceeded + rehash(); + + tab = table; + index = (hash & 0x7FFFFFFF) % tab.length; + } + + // Creates the new entry. + Entry e = new Entry(hash, key, value, tab[index]); + tab[index] = e; + count++; + return null; + } + + + +} + diff --git a/src/main/java/com/nhn/pinpoint/common/JvmVersion.java b/src/main/java/com/nhn/pinpoint/common/JvmVersion.java new file mode 100644 index 000000000..8873f4b3e --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/JvmVersion.java @@ -0,0 +1,54 @@ +package com.nhn.pinpoint.common; + +/** + * @author hyungil.jeong + */ +public enum JvmVersion { + JAVA_5(1.5, 49), + JAVA_6(1.6, 50), + JAVA_7(1.7, 51), + JAVA_8(1.8, 52), + UNSUPPORTED(-1, -1); + + private final double version; + private final int classVersion; + + private JvmVersion(double version, int classVersion) { + this.version = version; + this.classVersion = classVersion; + } + + public boolean onOrAfter(JvmVersion other) { + if (this == UNSUPPORTED || other == UNSUPPORTED) { + return false; + } + return this == other || this.version > other.version; + } + + public static JvmVersion getFromVersion(String javaVersion) { + try { + double version = Double.parseDouble(javaVersion); + return getFromVersion(version); + } catch (NumberFormatException e) { + return UNSUPPORTED; + } + } + + public static JvmVersion getFromVersion(double javaVersion) { + for (JvmVersion version : JvmVersion.values()) { + if (version.version == javaVersion) { + return version; + } + } + return JvmVersion.UNSUPPORTED; + } + + public static JvmVersion getFromClassVersion(int classVersion) { + for (JvmVersion version : JvmVersion.values()) { + if (version.classVersion == classVersion) { + return version; + } + } + return JvmVersion.UNSUPPORTED; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/PinpointConstants.java b/src/main/java/com/nhn/pinpoint/common/PinpointConstants.java new file mode 100644 index 000000000..638e66406 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/PinpointConstants.java @@ -0,0 +1,12 @@ +package com.nhn.pinpoint.common; + +/** + * @author emeroad + */ +public final class PinpointConstants { + + public static final int APPLICATION_NAME_MAX_LEN = 24; + + public static final int AGENT_NAME_MAX_LEN = 24; + +} diff --git a/src/main/java/com/nhn/pinpoint/common/ServiceType.java b/src/main/java/com/nhn/pinpoint/common/ServiceType.java new file mode 100644 index 000000000..3dc39c20e --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/ServiceType.java @@ -0,0 +1,266 @@ +package com.nhn.pinpoint.common; + +import static com.nhn.pinpoint.common.HistogramSchema.FAST_SCHEMA; +import static com.nhn.pinpoint.common.HistogramSchema.NORMAL_SCHEMA; +import static com.nhn.pinpoint.common.ServiceTypeConstants.INCLUDE_DESTINATION; +import static com.nhn.pinpoint.common.ServiceTypeConstants.RECORD_STATISTICS; +import static com.nhn.pinpoint.common.ServiceTypeConstants.TERMINAL; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.nhn.pinpoint.common.util.RpcCodeRange; + +/** + * @author emeroad + * @author netspider + */ +public enum ServiceType { + + /** + * 정의되지 않은 서비스 코드, + */ + UNDEFINED((short) -1, "UNDEFINED", TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * agent가 설치되지 않은 피호출자. + */ + UNKNOWN((short) 1, "UNKNOWN", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * 사용자 + */ + USER((short) 2, "USER", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * UNKNOWN의 그룹, UI에서만 사용함. + */ + UNKNOWN_GROUP((short) 3, "UNKNOWN_GROUP", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * TEST의 그룹 - 테스트 실행 시 사용 + */ + TEST((short) 5, "TEST", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * Java applications, WAS + */ + STAND_ALONE((short) 1000, "STAND_ALONE", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + TEST_STAND_ALONE((short) 1005, "TEST_STAND_ALONE", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + TOMCAT((short) 1010, "TOMCAT", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + BLOC((short) 1020, "BLOC", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + // BLOC4((short) 1030, "BLOC4", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * Database + * xxx_EXECUTE_QUERY만 server map통계정보에 집계된다. + */ + // DB 2000 + UNKNOWN_DB((short) 2050, "UNKNOWN_DB", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + UNKNOWN_DB_EXECUTE_QUERY((short) 2051, "UNKNOWN_DB", TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + + MYSQL((short) 2100, "MYSQL", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + MYSQL_EXECUTE_QUERY((short) 2101, "MYSQL", TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + + MSSQL((short) 2200, "MSSQL", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + MSSQL_EXECUTE_QUERY((short) 2201, "MSSQL", TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + + ORACLE((short) 2300, "ORACLE", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + ORACLE_EXECUTE_QUERY((short) 2301, "ORACLE", TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + + CUBRID((short) 2400, "CUBRID", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, NORMAL_SCHEMA), + CUBRID_EXECUTE_QUERY((short) 2401, "CUBRID", TERMINAL, RECORD_STATISTICS, true, NORMAL_SCHEMA), + + /** + * Internal method + */ + // FIXME internal method를 여기에 넣기 애매하긴 하나.. 일단 그대로 둠. + INTERNAL_METHOD((short) 5000, "INTERNAL_METHOD", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * Spring framework + */ + SPRING((short) 5050, "SPRING", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + SPRING_MVC((short) 5051, "SPRING", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + // FIXME 스프링 관련 코드들 어떻게 가져갈지 정리 필요 + SPRING_ORM_IBATIS((short) 5061, "SPRING", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * xBatis + */ + IBATIS((short) 5500, "IBATIS", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + MYBATIS((short) 5510, "MYBATIS", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * DBCP + */ + DBCP((short) 6050, "DBCP", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + + /** + * Memory cache + */ + MEMCACHED((short) 8050, "MEMCACHED", TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, FAST_SCHEMA), + MEMCACHED_FUTURE_GET((short) 8051, "MEMCACHED", TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, FAST_SCHEMA), + ARCUS((short) 8100, "ARCUS", TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION, FAST_SCHEMA), + ARCUS_FUTURE_GET((short) 8101, "ARCUS", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, FAST_SCHEMA), + ARCUS_EHCACHE_FUTURE_GET((short) 8102, "ARCUS-EHCACHE", TERMINAL, !RECORD_STATISTICS, INCLUDE_DESTINATION, FAST_SCHEMA), + + /** + * Connector, Client + */ + HTTP_CLIENT((short) 9050, "HTTP_CLIENT", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + HTTP_CLIENT_INTERNAL((short) 9051, "HTTP_CLIENT", !TERMINAL, !RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + JDK_HTTPURLCONNECTOR((short) 9055, "JDK_HTTPCONNECTOR", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + NPC_CLIENT((short) 9060, "NPC_CLIENT", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA), + NIMM_CLIENT((short) 9070, "NIMM_CLIENT", !TERMINAL, RECORD_STATISTICS, !INCLUDE_DESTINATION, NORMAL_SCHEMA); + + public static final short WAS_START_INDEX = 1000; + public static final short WAS_END_INDEX = 2000; + + private final short code; + private final String desc; + private final boolean terminal; + + // FIXME rpc 호출에 대해서만 통계정보를 남길 것이니, isRecordRpc()로 바꾸는건 어떨지??? + private final boolean recordStatistics; + + // DetinationId를 포함시켜 api를 출력하지 여부 + private final boolean includeDestinationId; + private final HistogramSchema histogramSchema; + + ServiceType(short code, String desc, boolean terminal, boolean recordStatistics, boolean includeDestinationId, HistogramSchema histogramSchema) { + this.code = code; + this.desc = desc; + this.terminal = terminal; + this.recordStatistics = recordStatistics; + this.includeDestinationId = includeDestinationId; + this.histogramSchema = histogramSchema; + } + + // FIXME 이 메소드를 사용해서 ServiceType을 찾는건 좋지 않을 듯. + public static List findDesc(String desc) { + if (desc == null) { + throw new NullPointerException("desc must not be null"); + } + return STATISTICS_LOOKUP_TABLE.get(desc); + } + + public boolean isInternalMethod() { + return this == INTERNAL_METHOD; + } + + public boolean isRpcClient() { + return RpcCodeRange.isRpcRange(code); + } + + public boolean isIndexable() { + return !terminal && !isRpcClient() && code > 1000; + } + + // FIXME rpc 호출에 대해서만 통계정보를 남길 것이니, isRecordRpc()로 바꾸는건 어떨지??? + public boolean isRecordStatistics() { + return recordStatistics; + } + + /** + * agent가 설치되어있지 않은 피호출자인가? + * + * @return + */ + public boolean isUnknown() { + return this == ServiceType.UNKNOWN; // || this == ServiceType.UNKNOWN_CLOUD; + } + + /** + * 사용자 또는 알 수 없는 호출자인가? + * + * @return + */ + public boolean isUser() { + return this == ServiceType.USER; + } + + public short getCode() { + return code; + } + + public String getDesc() { + return desc; + } + + public boolean isTerminal() { + return terminal; + } + + public boolean isIncludeDestinationId() { + return includeDestinationId; + } + + public HistogramSchema getHistogramSchema() { + return histogramSchema; + } + + public boolean isWas() { + return isWas(this.code); + } + + public static boolean isWas(final short code) { + return code >= WAS_START_INDEX && code < WAS_END_INDEX; + } + + @Override + public String toString() { + return desc; + } + + public static ServiceType findServiceType(short code) { + ServiceType serviceType = CODE_LOOKUP_TABLE.get(code); + if (serviceType == null) { + return UNDEFINED; + //return UNKNOWN; + } + return serviceType; + } + + private static final IntHashMap CODE_LOOKUP_TABLE = new IntHashMap(256); + private static final Map> STATISTICS_LOOKUP_TABLE = new HashMap>(64); + + static { + initializeLookupTable(); + initializeStatisticsLookupTable(); + } + + private static void initializeStatisticsLookupTable() { + ServiceType[] values = ServiceType.values(); + final Map> temp = new HashMap>(); + for (ServiceType serviceType : values) { + if(serviceType.isRecordStatistics()) { + List serviceTypeList = STATISTICS_LOOKUP_TABLE.get(serviceType.getDesc()); + if (serviceTypeList == null) { + serviceTypeList = new ArrayList(); + temp.put(serviceType.getDesc(), serviceTypeList); + } + serviceTypeList.add(serviceType); + } + } + // 수정하지 못하도록 한다. + for (Map.Entry> entry : temp.entrySet()) { + List serviceTypes = Collections.unmodifiableList(entry.getValue()); + STATISTICS_LOOKUP_TABLE.put(entry.getKey(), serviceTypes); + } + + } + + private static void initializeLookupTable() { + ServiceType[] values = ServiceType.values(); + for (ServiceType serviceType : values) { + ServiceType check = CODE_LOOKUP_TABLE.put(serviceType.code, serviceType); + if (check != null) { + throw new IllegalStateException("duplicated code found. code:" + serviceType.code); + } + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/ServiceTypeConstants.java b/src/main/java/com/nhn/pinpoint/common/ServiceTypeConstants.java new file mode 100644 index 000000000..f3f908aab --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/ServiceTypeConstants.java @@ -0,0 +1,12 @@ +package com.nhn.pinpoint.common; + +/** + * + * @author netspider + * + */ +public class ServiceTypeConstants { + public static final boolean TERMINAL = true; + public static final boolean RECORD_STATISTICS = true; + public static final boolean INCLUDE_DESTINATION = true; +} diff --git a/src/main/java/com/nhn/pinpoint/common/SlotType.java b/src/main/java/com/nhn/pinpoint/common/SlotType.java new file mode 100644 index 000000000..2b6ecc9dc --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/SlotType.java @@ -0,0 +1,6 @@ +package com.nhn.pinpoint.common; + + +public enum SlotType { + FAST, NORMAL, SLOW, VERY_SLOW, ERROR +} diff --git a/src/main/java/com/nhn/pinpoint/common/SystemPropertyKey.java b/src/main/java/com/nhn/pinpoint/common/SystemPropertyKey.java new file mode 100644 index 000000000..9c07db3ef --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/SystemPropertyKey.java @@ -0,0 +1,27 @@ +package com.nhn.pinpoint.common; + +/** + * @author hyungil.jeong + */ +public enum SystemPropertyKey { + + JAVA_VERSION("java.version"), + JAVA_RUNTIME_VERSION("java.runtime.version"), + JAVA_RUNTIME_NAME("java.runtime.name"), + JAVA_SPECIFICATION_VERSION("java.specification.version"), + JAVA_CLASS_VERSION("java.class.version"), + JAVA_VM_NAME("java.vm.name"), + JAVA_VM_VERSION("java.vm.version"), + JAVA_VM_INFO("java.vm.info"), + JAVA_VM_SPECIFICATION_VERSION("java.vm.specification.version"); + + private final String key; + + private SystemPropertyKey(String key) { + this.key = key; + } + + public String getKey() { + return this.key; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/Version.java b/src/main/java/com/nhn/pinpoint/common/Version.java new file mode 100644 index 000000000..a6ad2d1f1 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/Version.java @@ -0,0 +1,4 @@ +package com.nhn.pinpoint.common; +public final class Version { + public static final String VERSION = "1.0.2-SNAPSHOT"; +} \ No newline at end of file diff --git a/src/main/java/com/nhn/pinpoint/common/bo/AgentInfoBo.java b/src/main/java/com/nhn/pinpoint/common/bo/AgentInfoBo.java new file mode 100644 index 000000000..00be5a012 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/AgentInfoBo.java @@ -0,0 +1,222 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.ServiceType; +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.buffer.FixedBuffer; +import com.nhn.pinpoint.thrift.dto.TAgentInfo; +import org.apache.commons.lang.StringUtils; + +import java.util.Comparator; + +/** + * @author emeroad + */ +public class AgentInfoBo { + + public static final Comparator AGENT_NAME_ASC_COMPARATOR = new Comparator() { + @Override + public int compare(AgentInfoBo that, AgentInfoBo other) { + // null 일때 상황이 애매할수 있어서 그냥 ""으로 처리함. + final String thatAgentId = StringUtils.defaultString(that.agentId); + final String otherAgentId = StringUtils.defaultString(other.agentId); + return thatAgentId.compareTo(otherAgentId); + } + }; + + + private String hostname; + private String ip; + private String ports; + private String agentId; + private String applicationName; + private ServiceType serviceType; + private int pid; + private String version; + + private long startTime; + + private long endTimeStamp; + private int endStatus; + + public AgentInfoBo(TAgentInfo agentInfo) { + if (agentInfo == null) { + throw new NullPointerException("agentInfo must not be null"); + } + this.hostname = agentInfo.getHostname(); + this.ip = agentInfo.getIp(); + this.ports = agentInfo.getPorts(); + this.agentId = agentInfo.getAgentId(); + this.applicationName = agentInfo.getApplicationName(); + this.serviceType = ServiceType.findServiceType(agentInfo.getServiceType()); + this.pid = agentInfo.getPid(); + this.version = agentInfo.getVersion(); + + this.startTime = agentInfo.getStartTimestamp(); + + this.endTimeStamp = agentInfo.getEndTimestamp(); + this.endStatus = agentInfo.getEndStatus(); + } + + public AgentInfoBo() { + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public String getPorts() { + return ports; + } + + public void setPorts(String ports) { + this.ports = ports; + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTimeStamp() { + return endTimeStamp; + } + + public int getEndStatus() { + return endStatus; + } + + public int getPid() { + return pid; + } + + public void setPid(int pid) { + this.pid = pid; + } + + public ServiceType getServiceType() { + return serviceType; + } + + public void setServiceType(ServiceType serviceType) { + this.serviceType = serviceType; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public byte[] writeValue() { + final Buffer buffer = new AutomaticBuffer(); + buffer.putPrefixedString(this.getHostname()); + buffer.putPrefixedString(this.getIp()); + buffer.putPrefixedString(this.getPorts()); + buffer.putPrefixedString(this.getApplicationName()); + buffer.put(this.serviceType.getCode()); + buffer.put(this.getPid()); + buffer.putPrefixedString(this.getVersion());; + + buffer.put(this.getStartTime()); + buffer.put(this.getEndTimeStamp()); + buffer.put(this.getEndStatus()); + + return buffer.getBuffer(); + } + + public int readValue(byte[] value) { + final Buffer buffer = new FixedBuffer(value); + this.hostname = buffer.readPrefixedString(); + this.ip = buffer.readPrefixedString(); + this.ports = buffer.readPrefixedString(); + this.applicationName = buffer.readPrefixedString(); + this.serviceType = ServiceType.findServiceType(buffer.readShort()); + this.pid = buffer.readInt(); + this.version = buffer.readPrefixedString(); + + this.startTime = buffer.readLong(); + this.endTimeStamp = buffer.readLong(); + this.endStatus = buffer.readInt(); + + return buffer.getOffset(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((agentId == null) ? 0 : agentId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AgentInfoBo other = (AgentInfoBo) obj; + if (agentId == null) { + if (other.agentId != null) + return false; + } else if (!agentId.equals(other.agentId)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("AgentInfoBo{"); + sb.append("hostname='").append(hostname).append('\''); + sb.append(", ip='").append(ip).append('\''); + sb.append(", ports='").append(ports).append('\''); + sb.append(", agentId='").append(agentId).append('\''); + sb.append(", applicationName='").append(applicationName).append('\''); + sb.append(", serviceType=").append(serviceType); + sb.append(", pid=").append(pid); + sb.append(", version='").append(version).append('\''); + sb.append(", startTime=").append(startTime); + sb.append(", endTimeStamp=").append(endTimeStamp); + sb.append(", endStatus=").append(endStatus); + sb.append('}'); + return sb.toString(); + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/AgentKeyBo.java b/src/main/java/com/nhn/pinpoint/common/bo/AgentKeyBo.java new file mode 100644 index 000000000..4409150e5 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/AgentKeyBo.java @@ -0,0 +1,34 @@ +package com.nhn.pinpoint.common.bo; + +/** + * @author emeroad + */ +public class AgentKeyBo { + private String agentId; + private String applicationName; + private long agentStartTime; + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public long getAgentStartTime() { + return agentStartTime; + } + + public void setAgentStartTime(long agentStartTime) { + this.agentStartTime = agentStartTime; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/AgentStatCpuLoadBo.java b/src/main/java/com/nhn/pinpoint/common/bo/AgentStatCpuLoadBo.java new file mode 100644 index 000000000..b84c4ae92 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/AgentStatCpuLoadBo.java @@ -0,0 +1,136 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.buffer.FixedBuffer; + +/** + * @author hyungil.jeong + */ +public class AgentStatCpuLoadBo { + + private final String agentId; + private final long startTimestamp; + private final long timestamp; + private final double jvmCpuLoad; + private final double systemCpuLoad; + + private AgentStatCpuLoadBo(Builder builder) { + this.agentId = builder.agentId; + this.startTimestamp = builder.startTimestamp; + this.timestamp = builder.timestamp; + this.jvmCpuLoad = builder.jvmCpuLoad; + this.systemCpuLoad = builder.systemCpuLoad; + } + + public String getAgentId() { + return agentId; + } + + public long getStartTimestamp() { + return startTimestamp; + } + + public long getTimestamp() { + return timestamp; + } + + public double getJvmCpuLoad() { + return jvmCpuLoad; + } + + public double getSystemCpuLoad() { + return systemCpuLoad; + } + + public byte[] writeValue() { + final Buffer buffer = new AutomaticBuffer(); + buffer.putPrefixedString(this.agentId); + buffer.put(this.startTimestamp); + buffer.put(this.timestamp); + buffer.put(this.jvmCpuLoad); + buffer.put(this.systemCpuLoad); + return buffer.getBuffer(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("AgentStatCpuLoadBo{"); + sb.append("agentId='").append(this.agentId).append('\''); + sb.append(", startTimestamp=").append(this.startTimestamp); + sb.append(", timestamp=").append(this.timestamp); + sb.append(", jvmCpuLoad=").append(this.jvmCpuLoad); + sb.append(", systemCpuLoad=").append(this.systemCpuLoad); + sb.append('}'); + return sb.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((agentId == null) ? 0 : agentId.hashCode()); + result = prime * result + (int)(startTimestamp ^ (startTimestamp >>> 32)); + result = prime * result + (int)(timestamp ^ (timestamp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AgentStatCpuLoadBo other = (AgentStatCpuLoadBo)obj; + if (agentId == null) { + if (other.agentId != null) + return false; + } else if (!agentId.equals(other.agentId)) + return false; + if (startTimestamp != other.startTimestamp) + return false; + if (timestamp != other.timestamp) + return false; + return true; + } + + public static class Builder { + private static final double UNSUPPORTED = -1.0D; + private final String agentId; + private final long startTimestamp; + private final long timestamp; + private double jvmCpuLoad = UNSUPPORTED; + private double systemCpuLoad = UNSUPPORTED; + + public Builder(final byte[] value) { + final Buffer buffer = new FixedBuffer(value); + this.agentId = buffer.readPrefixedString(); + this.startTimestamp = buffer.readLong(); + this.timestamp = buffer.readLong(); + this.jvmCpuLoad = buffer.readDouble(); + this.systemCpuLoad = buffer.readDouble(); + } + + public Builder(String agentId, long startTimestamp, long timestamp) { + this.agentId = agentId; + this.startTimestamp = startTimestamp; + this.timestamp = timestamp; + } + + public Builder jvmCpuLoad(double jvmCpuLoad) { + this.jvmCpuLoad = jvmCpuLoad; + return this; + } + + public Builder systemCpuLoad(double systemCpuLoad) { + this.systemCpuLoad = systemCpuLoad; + return this; + } + + public AgentStatCpuLoadBo build() { + return new AgentStatCpuLoadBo(this); + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/AgentStatMemoryGcBo.java b/src/main/java/com/nhn/pinpoint/common/bo/AgentStatMemoryGcBo.java new file mode 100644 index 000000000..1fd3be4c0 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/AgentStatMemoryGcBo.java @@ -0,0 +1,210 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.buffer.FixedBuffer; + +/** + * @author hyungil.jeong + */ +public class AgentStatMemoryGcBo { + + private final String agentId; + private final long startTimestamp; + private final long timestamp; + private final String gcType; + private final long jvmMemoryHeapUsed; + private final long jvmMemoryHeapMax; + private final long jvmMemoryNonHeapUsed; + private final long jvmMemoryNonHeapMax; + private final long jvmGcOldCount; + private final long jvmGcOldTime; + + private AgentStatMemoryGcBo(Builder builder) { + this.agentId = builder.agentId; + this.startTimestamp = builder.startTimestamp; + this.timestamp = builder.timestamp; + this.gcType = builder.gcType; + this.jvmMemoryHeapUsed = builder.jvmMemoryHeapUsed; + this.jvmMemoryHeapMax = builder.jvmMemoryHeapMax; + this.jvmMemoryNonHeapUsed = builder.jvmMemoryNonHeapUsed; + this.jvmMemoryNonHeapMax = builder.jvmMemoryNonHeapMax; + this.jvmGcOldCount = builder.jvmGcOldCount; + this.jvmGcOldTime = builder.jvmGcOldTime; + } + + public String getAgentId() { + return agentId; + } + + public long getStartTimestamp() { + return startTimestamp; + } + + public long getTimestamp() { + return timestamp; + } + + public String getGcType() { + return gcType; + } + + public long getJvmMemoryHeapUsed() { + return jvmMemoryHeapUsed; + } + + public long getJvmMemoryHeapMax() { + return jvmMemoryHeapMax; + } + + public long getJvmMemoryNonHeapUsed() { + return jvmMemoryNonHeapUsed; + } + + public long getJvmMemoryNonHeapMax() { + return jvmMemoryNonHeapMax; + } + + public long getJvmGcOldCount() { + return jvmGcOldCount; + } + + public long getJvmGcOldTime() { + return jvmGcOldTime; + } + + public byte[] writeValue() { + final Buffer buffer = new AutomaticBuffer(); + buffer.putPrefixedString(this.agentId); + buffer.put(this.startTimestamp); + buffer.put(this.timestamp); + buffer.putPrefixedString(this.gcType); + buffer.put(this.jvmMemoryHeapUsed); + buffer.put(this.jvmMemoryHeapMax); + buffer.put(this.jvmMemoryNonHeapUsed); + buffer.put(this.jvmMemoryNonHeapMax); + buffer.put(this.jvmGcOldCount); + buffer.put(this.jvmGcOldTime); + return buffer.getBuffer(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((agentId == null) ? 0 : agentId.hashCode()); + result = prime * result + (int)(startTimestamp ^ (startTimestamp >>> 32)); + result = prime * result + (int)(timestamp ^ (timestamp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AgentStatMemoryGcBo other = (AgentStatMemoryGcBo)obj; + if (agentId == null) { + if (other.agentId != null) + return false; + } else if (!agentId.equals(other.agentId)) + return false; + if (startTimestamp != other.startTimestamp) + return false; + if (timestamp != other.timestamp) + return false; + return true; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("AgentStatMemoryGcBo{"); + sb.append("agentId='").append(this.agentId).append('\''); + sb.append(", startTimestamp=").append(this.startTimestamp); + sb.append(", timestamp=").append(this.timestamp); + sb.append(", gcType='").append(this.gcType).append('\''); + sb.append(", jvmMemoryHeapUsed=").append(this.jvmMemoryHeapUsed); + sb.append(", jvmMemoryHeapMax=").append(this.jvmMemoryHeapMax); + sb.append(", jvmMemoryNonHeapUsed=").append(this.jvmMemoryNonHeapUsed); + sb.append(", jvmMemoryNonHeapMax=").append(this.jvmMemoryNonHeapMax); + sb.append(", jvmGcOldCount=").append(this.jvmGcOldCount); + sb.append(", jvmGcOldTime=").append(this.jvmGcOldTime); + sb.append('}'); + return sb.toString(); + } + + public static class Builder { + private final String agentId; + private final long startTimestamp; + private final long timestamp; + private String gcType; + private long jvmMemoryHeapUsed; + private long jvmMemoryHeapMax; + private long jvmMemoryNonHeapUsed; + private long jvmMemoryNonHeapMax; + private long jvmGcOldCount; + private long jvmGcOldTime; + + public Builder(final byte[] value) { + final Buffer buffer = new FixedBuffer(value); + this.agentId = buffer.readPrefixedString(); + this.startTimestamp = buffer.readLong(); + this.timestamp = buffer.readLong(); + this.gcType = buffer.readPrefixedString(); + this.jvmMemoryHeapUsed = buffer.readLong(); + this.jvmMemoryHeapMax = buffer.readLong(); + this.jvmMemoryNonHeapUsed = buffer.readLong(); + this.jvmMemoryNonHeapMax = buffer.readLong(); + this.jvmGcOldCount = buffer.readLong(); + this.jvmGcOldTime = buffer.readLong(); + } + + public Builder(String agentId, long startTimestamp, long timestamp) { + this.agentId = agentId; + this.startTimestamp = startTimestamp; + this.timestamp = timestamp; + } + + public Builder gcType(String gcType) { + this.gcType = gcType; + return this; + } + + public Builder jvmMemoryHeapUsed(long jvmMemoryHeapUsed) { + this.jvmMemoryHeapUsed = jvmMemoryHeapUsed; + return this; + } + + public Builder jvmMemoryHeapMax(long jvmMemoryHeapMax) { + this.jvmMemoryHeapMax = jvmMemoryHeapMax; + return this; + } + + public Builder jvmMemoryNonHeapUsed(long jvmMemoryNonHeapUsed) { + this.jvmMemoryNonHeapUsed = jvmMemoryNonHeapUsed; + return this; + } + + public Builder jvmMemoryNonHeapMax(long jvmMemoryNonHeapMax) { + this.jvmMemoryNonHeapMax = jvmMemoryNonHeapMax; + return this; + } + + public Builder jvmGcOldCount(long jvmGcOldCount) { + this.jvmGcOldCount = jvmGcOldCount; + return this; + } + + public Builder jvmGcOldTime(long jvmGcOldTime) { + this.jvmGcOldTime = jvmGcOldTime; + return this; + } + + public AgentStatMemoryGcBo build() { + return new AgentStatMemoryGcBo(this); + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/AnnotationBo.java b/src/main/java/com/nhn/pinpoint/common/bo/AnnotationBo.java new file mode 100644 index 000000000..148b90416 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/AnnotationBo.java @@ -0,0 +1,138 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.AnnotationKey; +import com.nhn.pinpoint.thrift.dto.TAnnotation; +import com.nhn.pinpoint.common.util.AnnotationTranscoder; +import com.nhn.pinpoint.common.buffer.Buffer; + +/** + * @author emeroad + */ +public class AnnotationBo { + + private static final AnnotationTranscoder transcoder = new AnnotationTranscoder(); + + private static final int VERSION_SIZE = 1; + + private byte version = 0; + private long spanId; + + private int key; + + private byte valueType; + private byte[] byteValue; + private Object value; + + public AnnotationBo() { + } + + public AnnotationBo(TAnnotation annotation) { + if (annotation == null) { + throw new NullPointerException("annotation must not be null"); + } + this.key = annotation.getKey(); + Object value = transcoder.getMappingValue(annotation); + this.valueType = transcoder.getTypeCode(value); + this.byteValue = transcoder.encode(value, this.valueType); + } + + public long getSpanId() { + return spanId; + } + + public void setSpanId(long spanId) { + this.spanId = spanId; + } + + public int getVersion() { + return version & 0xFF; + } + + public void setVersion(int version) { + if (version < 0 || version > 255) { + throw new IllegalArgumentException("out of range (0~255) " + version); + } + // range 체크 + this.version = (byte) (version & 0xFF); + } + + public int getKey() { + return key; + } + + public String getKeyName() { + return AnnotationKey.findAnnotationKey(this.key).getValue(); + } + + public void setKey(int key) { + this.key = key; + } + + + public int getValueType() { + return valueType; + } + + public void setValueType(byte valueType) { + this.valueType = valueType; + } + + public byte[] getByteValue() { + return byteValue; + } + + public void setByteValue(byte[] byteValue) { + this.byteValue = byteValue; + } + + public Object getValue() { + return value; + } + + public void setValue(Object value) { + this.value = value; + } + + public void writeValue(Buffer buffer) { + // long timestamp; // required 8 + // long duration; // optional 8 + // int key; // required 4 + // int valueTypeCode; // required 4 + // ByteBuffer value; // optional 4 + buf.length + buffer.put(this.version); + buffer.putSVar(this.key); + buffer.put(this.valueType); + buffer.putPrefixedBytes(this.byteValue); + } + +// public int getBufferSize() { +// // int key; // required 4+string.length +// // int valueTypeCode; // required 4 +// // ByteBuffer value; // optional 4 + buf.length +// int size = 0; +// size += 1 + 4 + 4 + 4; +// size += 4; +// if (this.getByteValue() != null) { +// size += this.getByteValue().length; +// } +// return size; +// } + + + public void readValue(Buffer buffer) { + this.version = buffer.readByte(); + this.key = buffer.readSVarInt(); + this.valueType = buffer.readByte(); + this.byteValue = buffer.readPrefixedBytes(); + this.value = transcoder.decode(valueType, byteValue); + } + + @Override + public String toString() { + if (value == null) { + return "AnnotationBo{" + "version=" + version + ", spanId=" + spanId + ", key='" + key + '\'' + ", valueType=" + valueType + '}'; + } + return "AnnotationBo{" + "version=" + version + ", spanId=" + spanId + ", key='" + key + '\'' + ", value=" + value + '}'; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/AnnotationBoList.java b/src/main/java/com/nhn/pinpoint/common/bo/AnnotationBoList.java new file mode 100644 index 000000000..540f2643c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/AnnotationBoList.java @@ -0,0 +1,72 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.buffer.Buffer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author emeroad + */ +public class AnnotationBoList { + private List annotationBoList; + + public AnnotationBoList() { + this.annotationBoList = new ArrayList(); + } + + + public AnnotationBoList(int annotationBoListSize) { + this.annotationBoList = new ArrayList(annotationBoListSize); + } + + public AnnotationBoList(List annotationBoList) { + if (annotationBoList == null) { + this.annotationBoList = Collections.emptyList(); + return; + } + this.annotationBoList = annotationBoList; + } + + public List getAnnotationBoList() { + return annotationBoList; + } + + public void addAnnotationBo(AnnotationBo annotationBo) { + this.annotationBoList.add(annotationBo); + } + + public void writeValue(Buffer writer){ + + int size = this.annotationBoList.size(); + writer.putVar(size); + for (AnnotationBo annotationBo : this.annotationBoList) { + annotationBo.writeValue(writer); + } + } + + public void readValue(Buffer reader) { + int size = reader.readVarInt(); + if (size == 0) { + return; + } + this.annotationBoList = new ArrayList(size); + for (int i = 0; i < size; i++) { + AnnotationBo bo = new AnnotationBo(); + bo.readValue(reader); + this.annotationBoList.add(bo); + } + } + + public int size() { + return this.annotationBoList.size(); + } + + + public void setSpanId(long spanId) { + for (AnnotationBo annotationBo : this.annotationBoList) { + annotationBo.setSpanId(spanId); + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/ApiMetaDataBo.java b/src/main/java/com/nhn/pinpoint/common/bo/ApiMetaDataBo.java new file mode 100644 index 000000000..83a4d5a33 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/ApiMetaDataBo.java @@ -0,0 +1,106 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.util.BytesUtils; +import com.nhn.pinpoint.common.util.RowKeyUtils; +import com.nhn.pinpoint.common.util.TimeUtils; +import org.apache.hadoop.hbase.util.Bytes; + +import static com.nhn.pinpoint.common.PinpointConstants.AGENT_NAME_MAX_LEN; +import static com.nhn.pinpoint.common.util.BytesUtils.LONG_BYTE_LENGTH; + +/** + * @author emeroad + */ +public class ApiMetaDataBo { + private String agentId; + private long startTime; + + private int apiId; + + private String apiInfo; + private int lineNumber; + + public ApiMetaDataBo() { + } + + public ApiMetaDataBo(String agentId, long startTime, int apiId) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + + this.agentId = agentId; + this.startTime = startTime; + this.apiId = apiId; + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public int getApiId() { + return apiId; + } + + public void setApiId(int apiId) { + this.apiId = apiId; + } + + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public String getApiInfo() { + return apiInfo; + } + + public void setApiInfo(String apiInfo) { + this.apiInfo = apiInfo; + } + + public int getLineNumber() { + return lineNumber; + } + + public void setLineNumber(int lineNumber) { + this.lineNumber = lineNumber; + } + + public void readRowKey(byte[] bytes) { + this.agentId = Bytes.toString(bytes, 0, AGENT_NAME_MAX_LEN).trim(); + this.startTime = TimeUtils.recoveryTimeMillis(readTime(bytes)); + this.apiId = readKeyCode(bytes); + } + + private static long readTime(byte[] rowKey) { + return BytesUtils.bytesToLong(rowKey, AGENT_NAME_MAX_LEN); + } + + private static int readKeyCode(byte[] rowKey) { + return BytesUtils.bytesToInt(rowKey, AGENT_NAME_MAX_LEN + LONG_BYTE_LENGTH); + } + + public byte[] toRowKey() { + return RowKeyUtils.getMetaInfoRowKey(this.agentId, this.startTime, this.apiId); + } + + @Override + public String toString() { + return "ApiMetaDataBo{" + + "agentId='" + agentId + '\'' + + ", apiId=" + apiId + + ", startTime=" + startTime + + ", apiInfo='" + apiInfo + '\'' + + ", lineNumber=" + lineNumber + + '}'; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/IntStringStringValue.java b/src/main/java/com/nhn/pinpoint/common/bo/IntStringStringValue.java new file mode 100644 index 000000000..9f4febe55 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/IntStringStringValue.java @@ -0,0 +1,28 @@ +package com.nhn.pinpoint.common.bo; + +/** + * @author emeroad + */ +public class IntStringStringValue { + private final int intValue; + private final String stringValue1; + private final String stringValue2; + + public IntStringStringValue(int intValue, String stringValue1, String stringValue2) { + this.intValue = intValue; + this.stringValue1 = stringValue1; + this.stringValue2 = stringValue2; + } + + public int getIntValue() { + return intValue; + } + + public String getStringValue1() { + return stringValue1; + } + + public String getStringValue2() { + return stringValue2; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/IntStringValue.java b/src/main/java/com/nhn/pinpoint/common/bo/IntStringValue.java new file mode 100644 index 000000000..2fc3e68f4 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/IntStringValue.java @@ -0,0 +1,22 @@ +package com.nhn.pinpoint.common.bo; + +/** + * @author emeroad + */ +public class IntStringValue { + private final int intValue; + private final String stringValue; + + public IntStringValue(int intValue, String stringValue) { + this.intValue = intValue; + this.stringValue = stringValue; + } + + public String getStringValue() { + return stringValue; + } + + public int getIntValue() { + return intValue; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/Span.java b/src/main/java/com/nhn/pinpoint/common/bo/Span.java new file mode 100644 index 000000000..a7b0d3386 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/Span.java @@ -0,0 +1,18 @@ +package com.nhn.pinpoint.common.bo; + +import java.util.List; + +import com.nhn.pinpoint.common.ServiceType; + +/** + * @author emeroad + */ +public interface Span { + ServiceType getServiceType(); + + String getRpc(); + + String getEndPoint(); + + List getAnnotationBoList(); +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/SpanBo.java b/src/main/java/com/nhn/pinpoint/common/bo/SpanBo.java new file mode 100644 index 000000000..cc994ac1f --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/SpanBo.java @@ -0,0 +1,463 @@ +package com.nhn.pinpoint.common.bo; + +import java.util.ArrayList; +import java.util.List; + +import com.nhn.pinpoint.common.ServiceType; +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.OffsetFixedBuffer; +import com.nhn.pinpoint.common.util.TransactionId; +import com.nhn.pinpoint.common.util.TransactionIdUtils; +import com.nhn.pinpoint.thrift.dto.TAnnotation; +import com.nhn.pinpoint.thrift.dto.TIntStringValue; +import com.nhn.pinpoint.thrift.dto.TSpan; +import com.nhn.pinpoint.common.buffer.Buffer; + +/** + * @author emeroad + */ +public class SpanBo implements com.nhn.pinpoint.common.bo.Span { + + private static final int VERSION_SIZE = 1; + // version 0 = prefix의 사이즈를 int로 + + private byte version = 0; + + +// private AgentKeyBo agentKeyBo; + private String agentId; + private String applicationId; + private long agentStartTime; + + private String traceAgentId; + private long traceAgentStartTime; + private long traceTransactionSequence; + private long spanId; + private long parentSpanId; + + private long startTime; + private int elapsed; + + private String rpc; + private ServiceType serviceType; + private String endPoint; + private int apiId; + + private List annotationBoList; + private short flag; // optional + private int errCode; + + private List spanEventBoList; + + private long collectorAcceptTime; + + private boolean hasException = false; + private int exceptionId; + private String exceptionMessage; + private String exceptionClass; + + + private String remoteAddr; // optional + + public SpanBo(TSpan span) { + if (span == null) { + throw new NullPointerException("span must not be null"); + } + this.agentId = span.getAgentId(); + this.applicationId = span.getApplicationName(); + this.agentStartTime = span.getAgentStartTime(); + + final TransactionId transactionId = TransactionIdUtils.parseTransactionId(span.getTransactionId()); + this.traceAgentId = transactionId.getAgentId(); + if (traceAgentId == null) { + traceAgentId = this.agentId; + } + this.traceAgentStartTime = transactionId.getAgentStartTime(); + this.traceTransactionSequence = transactionId.getTransactionSequence(); + + this.spanId = span.getSpanId(); + this.parentSpanId = span.getParentSpanId(); + + this.startTime = span.getStartTime(); + this.elapsed = span.getElapsed(); + + this.rpc = span.getRpc(); + + this.serviceType = ServiceType.findServiceType(span.getServiceType()); + this.endPoint = span.getEndPoint(); + this.flag = span.getFlag(); + this.apiId = span.getApiId(); + + this.errCode = span.getErr(); + + this.remoteAddr = span.getRemoteAddr(); + + + // FIXME span.errCode는 span과 spanEvent의 에러를 모두 포함한 값. + // exceptionInfo는 span자체의 에러정보이기 때문에 errCode가 0이 아니더라도 exceptionInfo는 null일 수 있음. + final TIntStringValue exceptionInfo = span.getExceptionInfo(); + if (exceptionInfo != null) { + this.hasException = true; + this.exceptionId = exceptionInfo.getIntValue(); + this.exceptionMessage = exceptionInfo.getStringValue(); + } + + setAnnotationList(span.getAnnotations()); + } + + public SpanBo(String traceAgentId, long traceAgentStartTime, long traceTransactionSequence, long startTime, int elapsed, long spanId) { + if (traceAgentId == null) { + throw new NullPointerException("traceAgentId must not be null"); + } + this.traceAgentId = traceAgentId; + this.traceAgentStartTime = traceAgentStartTime; + this.traceTransactionSequence = traceTransactionSequence; + + this.startTime = startTime; + this.elapsed = elapsed; + + this.spanId = spanId; + } + + public SpanBo() { + } + + public int getVersion() { + return version & 0xFF; + } + + public void setVersion(int version) { + if (version < 0 || version > 255) { + throw new IllegalArgumentException("out of range (0~255)"); + } + // range 체크 + this.version = (byte) (version & 0xFF); + } + + public String getTransactionId() { + return TransactionIdUtils.formatString(traceAgentId, traceAgentStartTime, traceTransactionSequence); + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public String getApplicationId() { + return applicationId; + } + + public void setApplicationId(String applicationId) { + this.applicationId = applicationId; + } + + public long getAgentStartTime() { + return agentStartTime; + } + + public void setAgentStartTime(long agentStartTime) { + this.agentStartTime = agentStartTime; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + + public int getElapsed() { + return elapsed; + } + + public void setElapsed(int elapsed) { + this.elapsed = elapsed; + } + + + public String getTraceAgentId() { + return traceAgentId; + } + + public void setTraceAgentId(String traceAgentId) { + this.traceAgentId = traceAgentId; + } + + public long getTraceAgentStartTime() { + return traceAgentStartTime; + } + + public void setTraceAgentStartTime(long traceAgentStartTime) { + this.traceAgentStartTime = traceAgentStartTime; + } + + + public long getTraceTransactionSequence() { + return traceTransactionSequence; + } + + public void setTraceTransactionSequence(long traceTransactionSequence) { + this.traceTransactionSequence = traceTransactionSequence; + } + + + public String getRpc() { + return rpc; + } + + public void setRpc(String rpc) { + this.rpc = rpc; + } + + + public long getSpanId() { + return spanId; + } + + public void setSpanID(long spanId) { + this.spanId = spanId; + } + + public long getParentSpanId() { + return parentSpanId; + } + + public void setParentSpanId(long parentSpanId) { + this.parentSpanId = parentSpanId; + } + + public int getFlag() { + return flag; + } + + public void setFlag(short flag) { + this.flag = flag; + } + + public String getEndPoint() { + return endPoint; + } + + public void setEndPoint(String endPoint) { + this.endPoint = endPoint; + } + + public int getApiId() { + return apiId; + } + + public void setApiId(int apiId) { + this.apiId = apiId; + } + + public List getAnnotationBoList() { + return annotationBoList; + } + + public void setAnnotationList(List anoList) { + if (anoList == null) { + return; + } + List boList = new ArrayList(anoList.size()); + for (TAnnotation ano : anoList) { + boList.add(new AnnotationBo(ano)); + } + this.annotationBoList = boList; + } + + public void setAnnotationBoList(List anoList) { + if (anoList == null) { + return; + } + this.annotationBoList = anoList; + } + + public void addSpanEvent(SpanEventBo spanEventBo) { + if (spanEventBoList == null) { + spanEventBoList = new ArrayList(); + } + spanEventBoList.add(spanEventBo); + } + + public List getSpanEventBoList() { + return spanEventBoList; + } + + public ServiceType getServiceType() { + return serviceType; + } + + public void setServiceType(ServiceType serviceType) { + this.serviceType = serviceType; + } + + public int getErrCode() { + return errCode; + } + + public void setErrCode(int errCode) { + this.errCode = errCode; + } + + public String getRemoteAddr() { + return remoteAddr; + } + + public void setRemoteAddr(String remoteAddr) { + this.remoteAddr = remoteAddr; + } + + public long getCollectorAcceptTime() { + return collectorAcceptTime; + } + + public void setCollectorAcceptTime(long collectorAcceptTime) { + this.collectorAcceptTime = collectorAcceptTime; + } + + public boolean isRoot() { + return -1L == parentSpanId; + } + + public boolean hasException() { + return hasException; + } + + public int getExceptionId() { + return exceptionId; + } + + public String getExceptionMessage() { + return exceptionMessage; + } + + public String getExceptionClass() { + return exceptionClass; + } + + public void setExceptionClass(String exceptionClass) { + this.exceptionClass = exceptionClass; + } + + + // io wirte시 variable encoding을 추가함. + // 약 10%정도 byte 사이즈가 줄어드는 효과가 있음. + public byte[] writeValue() { + // var encoding 사용시 사이즈를 측정하기 어려움. 안되는것음 아님 편의상 그냥 자동 증가 buffer를 사용한다. + // 향후 더 효율적으로 메모리를 사용하게 한다면 getBufferLength를 다시 부활 시키는것을 고려한다. + final Buffer buffer = new AutomaticBuffer(256); + + buffer.put(version); + + // buffer.put(mostTraceID); + // buffer.put(leastTraceID); + + buffer.putPrefixedString(agentId); + // time의 경우도 현재 시간을 기준으로 var를 사용하는게 사이즈가 더 작음 6byte를 먹음. + buffer.putVar(agentStartTime); + + // rowkey에 들어감. + // buffer.put(spanID); + buffer.put(parentSpanId); + + // 현재 시간이 기준이므로 var encoding + buffer.putVar(startTime); + buffer.putVar(elapsed); + + buffer.putPrefixedString(rpc); + buffer.putPrefixedString(applicationId); + buffer.put(serviceType.getCode()); + buffer.putPrefixedString(endPoint); + buffer.putPrefixedString(remoteAddr); + buffer.putSVar(apiId); + + // errCode code는 음수가 될수 있음. + buffer.putSVar(errCode); + + if (hasException){ + buffer.put(true); + buffer.putSVar(exceptionId); + buffer.putPrefixedString(exceptionMessage); + } else { + buffer.put(false); + } + + buffer.put(flag); + + return buffer.getBuffer(); + } + + public int readValue(byte[] bytes, int offset) { + final Buffer buffer = new OffsetFixedBuffer(bytes, offset); + + this.version = buffer.readByte(); + + // this.mostTraceID = buffer.readLong(); + // this.leastTraceID = buffer.readLong(); + + this.agentId = buffer.readPrefixedString(); + this.agentStartTime = buffer.readVarLong(); + + // this.spanID = buffer.readLong(); + this.parentSpanId = buffer.readLong(); + + this.startTime = buffer.readVarLong(); + this.elapsed = buffer.readVarInt(); + + this.rpc = buffer.readPrefixedString(); + this.applicationId = buffer.readPrefixedString(); + this.serviceType = ServiceType.findServiceType(buffer.readShort()); + this.endPoint = buffer.readPrefixedString(); + this.remoteAddr = buffer.readPrefixedString(); + this.apiId = buffer.readSVarInt(); + + this.errCode = buffer.readSVarInt(); + + this.hasException = buffer.readBoolean(); + if (hasException) { + this.exceptionId = buffer.readSVarInt(); + this.exceptionMessage = buffer.readPrefixedString(); + } + + this.flag = buffer.readShort(); + + return buffer.getOffset(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(256); + sb.append("SpanBo{"); + sb.append("version=").append(version); + sb.append(", agentId='").append(agentId).append('\''); + sb.append(", applicationId='").append(applicationId).append('\''); + sb.append(", agentStartTime=").append(agentStartTime); + sb.append(", traceAgentId='").append(traceAgentId).append('\''); + sb.append(", traceAgentStartTime=").append(traceAgentStartTime); + sb.append(", traceTransactionSequence=").append(traceTransactionSequence); + sb.append(", spanId=").append(spanId); + sb.append(", parentSpanId=").append(parentSpanId); + sb.append(", startTime=").append(startTime); + sb.append(", elapsed=").append(elapsed); + sb.append(", rpc='").append(rpc).append('\''); + sb.append(", serviceType=").append(serviceType); + sb.append(", endPoint='").append(endPoint).append('\''); + sb.append(", apiId=").append(apiId); + sb.append(", annotationBoList=").append(annotationBoList); + sb.append(", flag=").append(flag); + sb.append(", errCode=").append(errCode); + sb.append(", spanEventBoList=").append(spanEventBoList); + sb.append(", collectorAcceptTime=").append(collectorAcceptTime); + sb.append(", hasException=").append(hasException); + sb.append(", exceptionId=").append(exceptionId); + sb.append(", exceptionMessage='").append(exceptionMessage).append('\''); + sb.append(", remoteAddr='").append(remoteAddr).append('\''); + sb.append('}'); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/com/nhn/pinpoint/common/bo/SpanEventBo.java b/src/main/java/com/nhn/pinpoint/common/bo/SpanEventBo.java new file mode 100644 index 000000000..f5b2b76e0 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/SpanEventBo.java @@ -0,0 +1,460 @@ +package com.nhn.pinpoint.common.bo; + +import java.util.ArrayList; +import java.util.List; + +import com.nhn.pinpoint.common.ServiceType; +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.OffsetFixedBuffer; +import com.nhn.pinpoint.common.util.TransactionId; +import com.nhn.pinpoint.common.util.TransactionIdUtils; +import com.nhn.pinpoint.thrift.dto.*; +import com.nhn.pinpoint.common.buffer.Buffer; + +/** + * @author emeroad + */ +public class SpanEventBo implements Span { + private static final int VERSION_SIZE = 1; + // version 0 = prefix의 사이즈를 int로 + + private byte version = 0; + + private String agentId; + private String applicationId; + private long agentStartTime; + + private String traceAgentId; + private long traceAgentStartTime; + private long traceTransactionSequence; + + private long spanId; + private short sequence; + + private int startElapsed; + private int endElapsed; + + private String rpc; + private ServiceType serviceType; + + private String destinationId; + private String endPoint; + private int apiId; + + private List annotationBoList; + + private int depth = -1; + private long nextSpanId = -1; + + private boolean hasException; + private int exceptionId; + private String exceptionMessage; + // dao에서 찾아야 함. + private String exceptionClass; + + + public SpanEventBo() { + } + + public SpanEventBo(TSpan tSpan, TSpanEvent tSpanEvent) { + if (tSpan == null) { + throw new NullPointerException("tSpan must not be null"); + } + if (tSpanEvent == null) { + throw new NullPointerException("tSpanEvent must not be null"); + } + + this.agentId = tSpan.getAgentId(); + this.applicationId = tSpan.getApplicationName(); + this.agentStartTime = tSpan.getAgentStartTime(); + + final TransactionId transactionId = TransactionIdUtils.parseTransactionId(tSpan.getTransactionId()); + this.traceAgentId = transactionId.getAgentId(); + if (traceAgentId == null) { + traceAgentId = this.agentId; + } + this.traceAgentStartTime = transactionId.getAgentStartTime(); + this.traceTransactionSequence = transactionId.getTransactionSequence(); + + this.spanId = tSpan.getSpanId(); + this.sequence = tSpanEvent.getSequence(); + + this.startElapsed = tSpanEvent.getStartElapsed(); + this.endElapsed = tSpanEvent.getEndElapsed(); + + this.rpc = tSpanEvent.getRpc(); + this.serviceType = ServiceType.findServiceType(tSpanEvent.getServiceType()); + + + this.destinationId = tSpanEvent.getDestinationId(); + + this.endPoint = tSpanEvent.getEndPoint(); + this.apiId = tSpanEvent.getApiId(); + + if (tSpanEvent.isSetDepth()) { + this.depth = tSpanEvent.getDepth(); + } + + if (tSpanEvent.isSetNextSpanId()) { + this.nextSpanId = tSpanEvent.getNextSpanId(); + } + + setAnnotationBoList(tSpanEvent.getAnnotations()); + + final TIntStringValue exceptionInfo = tSpanEvent.getExceptionInfo(); + if (exceptionInfo != null) { + this.hasException = true; + this.exceptionId = exceptionInfo.getIntValue(); + this.exceptionMessage = exceptionInfo.getStringValue(); + } + } + + public SpanEventBo(TSpanChunk spanChunk, TSpanEvent spanEvent) { + if (spanChunk == null) { + throw new NullPointerException("spanChunk must not be null"); + } + if (spanEvent == null) { + throw new NullPointerException("spanEvent must not be null"); + } + + this.agentId = spanChunk.getAgentId(); + this.applicationId = spanChunk.getApplicationName(); + this.agentStartTime = spanChunk.getAgentStartTime(); + + final TransactionId transactionId = TransactionIdUtils.parseTransactionId(spanChunk.getTransactionId()); + this.traceAgentId = transactionId.getAgentId(); + if (traceAgentId == null) { + traceAgentId = this.agentId; + } + this.traceAgentStartTime = transactionId.getAgentStartTime(); + this.traceTransactionSequence = transactionId.getTransactionSequence(); + + this.spanId = spanChunk.getSpanId(); + this.sequence = spanEvent.getSequence(); + + this.startElapsed = spanEvent.getStartElapsed(); + this.endElapsed = spanEvent.getEndElapsed(); + + this.rpc = spanEvent.getRpc(); + this.serviceType = ServiceType.findServiceType(spanEvent.getServiceType()); + + this.destinationId = spanEvent.getDestinationId(); + + this.endPoint = spanEvent.getEndPoint(); + this.apiId = spanEvent.getApiId(); + + if (spanEvent.isSetDepth()) { + this.depth = spanEvent.getDepth(); + } + + if (spanEvent.isSetNextSpanId()) { + this.nextSpanId = spanEvent.getNextSpanId(); + } + + setAnnotationBoList(spanEvent.getAnnotations()); + + final TIntStringValue exceptionInfo = spanEvent.getExceptionInfo(); + if (exceptionInfo != null) { + this.hasException = true; + this.exceptionId = exceptionInfo.getIntValue(); + this.exceptionMessage = exceptionInfo.getStringValue(); + } + } + + + + public byte getVersion() { + return version; + } + + public void setVersion(byte version) { + this.version = version; + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + public long getAgentStartTime() { + return this.agentStartTime; + } + + public void setAgentStartTime(long agentStartTime) { + this.agentStartTime = agentStartTime; + } + + public String getTraceAgentId() { + return traceAgentId; + } + + public void setTraceAgentId(String traceAgentId) { + this.traceAgentId = traceAgentId; + } + + public long getTraceAgentStartTime() { + return traceAgentStartTime; + } + + public void setTraceAgentStartTime(long traceAgentStartTime) { + this.traceAgentStartTime = traceAgentStartTime; + } + + public long getTraceTransactionSequence() { + return traceTransactionSequence; + } + + public void setTraceTransactionSequence(long traceTransactionSequence) { + this.traceTransactionSequence = traceTransactionSequence; + } + + public void setSpanId(long spanId) { + this.spanId = spanId; + } + + public long getSpanId() { + return this.spanId; + } + + public short getSequence() { + return sequence; + } + + public void setSequence(short sequence) { + this.sequence = sequence; + } + + public int getStartElapsed() { + return startElapsed; + } + + public void setStartElapsed(int startElapsed) { + this.startElapsed = startElapsed; + } + + public int getEndElapsed() { + return endElapsed; + } + + public void setEndElapsed(int endElapsed) { + this.endElapsed = endElapsed; + } + + public String getRpc() { + return rpc; + } + + public void setRpc(String rpc) { + this.rpc = rpc; + } + + public ServiceType getServiceType() { + return serviceType; + } + + public void setServiceType(ServiceType serviceType) { + this.serviceType = serviceType; + } + + public String getEndPoint() { + return endPoint; + } + + public void setEndPoint(String endPoint) { + this.endPoint = endPoint; + } + + public int getApiId() { + return apiId; + } + + public void setApiId(int apiId) { + this.apiId = apiId; + } + + public String getDestinationId() { + return destinationId; + } + + public void setDestinationId(String destinationId) { + this.destinationId = destinationId; + } + + + public List getAnnotationBoList() { + return annotationBoList; + } + + public int getDepth() { + return depth; + } + + public void setDepth(int depth) { + this.depth = depth; + } + + public long getNextSpanId() { + return nextSpanId; + } + + public void setNextSpanId(long nextSpanId) { + this.nextSpanId = nextSpanId; + } + + private void setAnnotationBoList(List annotations) { + if (annotations == null) { + return; + } + List boList = new ArrayList(annotations.size()); + for (TAnnotation ano : annotations) { + boList.add(new AnnotationBo(ano)); + } + this.annotationBoList = boList; + } + + public boolean hasException() { + return hasException; + } + + public int getExceptionId() { + return exceptionId; + } + + public String getExceptionMessage() { + return exceptionMessage; + } + + public String getExceptionClass() { + return exceptionClass; + } + + public void setExceptionClass(String exceptionClass) { + this.exceptionClass = exceptionClass; + } + + + + public byte[] writeValue() { + final Buffer buffer = new AutomaticBuffer(512); + + buffer.put(version); + + // buffer.put(mostTraceID); + // buffer.put(leastTraceID); + + buffer.putPrefixedString(agentId); + buffer.putPrefixedString(applicationId); + buffer.putVar(agentStartTime); + + buffer.putVar(startElapsed); + buffer.putVar(endElapsed); + // Qualifier에서 읽어서 set하므로 필요 없음. + // buffer.put(sequence); + + buffer.putPrefixedString(rpc); + buffer.put(serviceType.getCode()); + buffer.putPrefixedString(endPoint); + buffer.putPrefixedString(destinationId); + buffer.putSVar(apiId); + + buffer.putSVar(depth); + buffer.put(nextSpanId); + + if (hasException) { + buffer.put(true); + buffer.putSVar(exceptionId); + buffer.putPrefixedString(exceptionMessage); + } else { + buffer.put(false); + } + + writeAnnotation(buffer); + + + return buffer.getBuffer(); + } + + + + private void writeAnnotation(Buffer buffer) { + AnnotationBoList annotationBo = new AnnotationBoList(this.annotationBoList); + annotationBo.writeValue(buffer); + } + + + public int readValue(byte[] bytes, int offset) { + final Buffer buffer = new OffsetFixedBuffer(bytes, offset); + + this.version = buffer.readByte(); + + // this.mostTraceID = buffer.readLong(); + // this.leastTraceID = buffer.readLong(); + + this.agentId = buffer.readPrefixedString(); + this.applicationId = buffer.readPrefixedString(); + this.agentStartTime = buffer.readVarLong(); + + this.startElapsed = buffer.readVarInt(); + this.endElapsed = buffer.readVarInt(); + // Qualifier에서 읽어서 가져오므로 하지 않아도 됨. + // this.sequence = buffer.readShort(); + + + this.rpc = buffer.readPrefixedString(); + this.serviceType = ServiceType.findServiceType(buffer.readShort()); + this.endPoint = buffer.readPrefixedString(); + this.destinationId = buffer.readPrefixedString(); + this.apiId = buffer.readSVarInt(); + + this.depth = buffer.readSVarInt(); + this.nextSpanId = buffer.readLong(); + + this.hasException = buffer.readBoolean(); + if (hasException) { + this.exceptionId = buffer.readSVarInt(); + this.exceptionMessage = buffer.readPrefixedString(); + } + + this.annotationBoList = readAnnotation(buffer); + return buffer.getOffset(); + } + + private List readAnnotation(Buffer buffer) { + AnnotationBoList annotationBoList = new AnnotationBoList(); + annotationBoList.readValue(buffer); + return annotationBoList.getAnnotationBoList(); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(256); + sb.append("SpanEventBo{"); + sb.append("version=").append(version); + sb.append(", agentId='").append(agentId).append('\''); + sb.append(", applicationId='").append(applicationId).append('\''); + sb.append(", agentStartTime=").append(agentStartTime); + sb.append(", traceAgentId='").append(traceAgentId).append('\''); + sb.append(", traceAgentStartTime=").append(traceAgentStartTime); + sb.append(", traceTransactionSequence=").append(traceTransactionSequence); + sb.append(", spanId=").append(spanId); + sb.append(", sequence=").append(sequence); + sb.append(", startElapsed=").append(startElapsed); + sb.append(", endElapsed=").append(endElapsed); + sb.append(", rpc='").append(rpc).append('\''); + sb.append(", serviceType=").append(serviceType); + sb.append(", destinationId='").append(destinationId).append('\''); + sb.append(", endPoint='").append(endPoint).append('\''); + sb.append(", apiId=").append(apiId); + sb.append(", annotationBoList=").append(annotationBoList); + sb.append(", depth=").append(depth); + sb.append(", nextSpanId=").append(nextSpanId); + sb.append(", hasException=").append(hasException); + sb.append(", exceptionId=").append(exceptionId); + sb.append(", exceptionMessage='").append(exceptionMessage).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/SqlMetaDataBo.java b/src/main/java/com/nhn/pinpoint/common/bo/SqlMetaDataBo.java new file mode 100644 index 000000000..ad7968e57 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/SqlMetaDataBo.java @@ -0,0 +1,97 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.util.BytesUtils; +import com.nhn.pinpoint.common.util.RowKeyUtils; +import com.nhn.pinpoint.common.util.TimeUtils; +import org.apache.hadoop.hbase.util.Bytes; + +import static com.nhn.pinpoint.common.PinpointConstants.AGENT_NAME_MAX_LEN; +import static com.nhn.pinpoint.common.util.BytesUtils.LONG_BYTE_LENGTH; + +/** + * @author emeroad + */ +public class SqlMetaDataBo { + private String agentId; + private long startTime; + + private int hashCode; + + private String sql; + + public SqlMetaDataBo() { + } + + + public SqlMetaDataBo(String agentId, long startTime, int hashCode) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + this.agentId = agentId; + this.hashCode = hashCode; + this.startTime = startTime; + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + + public int getHashCode() { + return hashCode; + } + + public void setHashCode(int hashCode) { + this.hashCode = hashCode; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public void readRowKey(byte[] rowKey) { + this.agentId = Bytes.toString(rowKey, 0, AGENT_NAME_MAX_LEN).trim(); + this.startTime = TimeUtils.recoveryTimeMillis(readTime(rowKey)); + this.hashCode = readKeyCode(rowKey); + } + + + private static long readTime(byte[] rowKey) { + return BytesUtils.bytesToLong(rowKey, AGENT_NAME_MAX_LEN); + } + + private static int readKeyCode(byte[] rowKey) { + return BytesUtils.bytesToInt(rowKey, AGENT_NAME_MAX_LEN + LONG_BYTE_LENGTH); + } + + public byte[] toRowKey() { + return RowKeyUtils.getMetaInfoRowKey(this.agentId, this.startTime, this.hashCode); + } + + @Override + public String toString() { + return "SqlMetaDataBo{" + + "agentId='" + agentId + '\'' + + ", startTime=" + startTime + + ", hashCode=" + hashCode + + ", sql='" + sql + '\'' + + '}'; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/bo/StringMetaDataBo.java b/src/main/java/com/nhn/pinpoint/common/bo/StringMetaDataBo.java new file mode 100644 index 000000000..90fe4dbba --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/bo/StringMetaDataBo.java @@ -0,0 +1,97 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.util.BytesUtils; +import com.nhn.pinpoint.common.util.RowKeyUtils; +import com.nhn.pinpoint.common.util.TimeUtils; +import org.apache.hadoop.hbase.util.Bytes; + +import static com.nhn.pinpoint.common.PinpointConstants.AGENT_NAME_MAX_LEN; +import static com.nhn.pinpoint.common.util.BytesUtils.LONG_BYTE_LENGTH; + +/** + * @author emeroad + */ +public class StringMetaDataBo { + private String agentId; + private long startTime; + + private int stringId; + + private String stringValue; + + public StringMetaDataBo() { + } + + + public StringMetaDataBo(String agentId, long startTime, int stringId) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + this.agentId = agentId; + this.stringId = stringId; + this.startTime = startTime; + } + + public String getAgentId() { + return agentId; + } + + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + + public int getStringId() { + return stringId; + } + + public void setStringId(int stringId) { + this.stringId = stringId; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public String getStringValue() { + return stringValue; + } + + public void setStringValue(String stringValue) { + this.stringValue = stringValue; + } + + public void readRowKey(byte[] rowKey) { + this.agentId = Bytes.toString(rowKey, 0, AGENT_NAME_MAX_LEN).trim(); + this.startTime = TimeUtils.recoveryTimeMillis(readTime(rowKey)); + this.stringId = readKeyCode(rowKey); + } + + + private static long readTime(byte[] rowKey) { + return BytesUtils.bytesToLong(rowKey, AGENT_NAME_MAX_LEN); + } + + private static int readKeyCode(byte[] rowKey) { + return BytesUtils.bytesToInt(rowKey, AGENT_NAME_MAX_LEN + LONG_BYTE_LENGTH); + } + + public byte[] toRowKey() { + return RowKeyUtils.getMetaInfoRowKey(this.agentId, this.startTime, this.stringId); + } + + @Override + public String toString() { + return "StringMetaDataBo{" + + "agentId='" + agentId + '\'' + + ", startTime=" + startTime + + ", stringId=" + stringId + + ", stringValue='" + stringValue + '\'' + + '}'; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/buffer/AutomaticBuffer.java b/src/main/java/com/nhn/pinpoint/common/buffer/AutomaticBuffer.java new file mode 100644 index 000000000..de004a314 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/buffer/AutomaticBuffer.java @@ -0,0 +1,182 @@ +package com.nhn.pinpoint.common.buffer; + +import com.nhn.pinpoint.common.util.BytesUtils; + +/** + * 버퍼사이즈가 자동으로 확장되는 buffer + * @author emeroad + */ +public class AutomaticBuffer extends FixedBuffer { + + public AutomaticBuffer() { + super(32); + } + + public AutomaticBuffer(final int size) { + super(size); + } + + public AutomaticBuffer(final byte[] buffer) { + super(buffer); + } + + + private void checkExpend(final int size) { + int length = buffer.length; + final int remain = length - offset; + if (remain >= size) { + return; + } + + if (length == 0) { + length = 1; + } + + // 사이즈 계산을 먼저한 후에 buffer를 한번만 할당하도록 변경. + final int expendBufferSize = computeExpendBufferSize(size, length, remain); + // allocate buffer + final byte[] expendBuffer = new byte[expendBufferSize]; + System.arraycopy(buffer, 0, expendBuffer, 0, buffer.length); + buffer = expendBuffer; + } + + private int computeExpendBufferSize(final int size, int length, int remain) { + int expendBufferSize = 0; + while (remain < size) { + length <<= 2; + expendBufferSize = length; + remain = expendBufferSize - offset; + } + return expendBufferSize; + } + + @Override + public void putPadBytes(byte[] bytes, int totalLength) { + checkExpend(totalLength); + super.putPadBytes(bytes, totalLength); + } + + + @Override + public void putPrefixedBytes(final byte[] bytes) { + if (bytes == null) { + checkExpend(1); + super.putSVar(NULL); + } else { + checkExpend(bytes.length + BytesUtils.VINT_MAX_SIZE); + super.putSVar(bytes.length); + super.put(bytes); + } + } + + @Override + public void put2PrefixedBytes(final byte[] bytes) { + if (bytes == null) { + checkExpend(BytesUtils.SHORT_BYTE_LENGTH); + super.put((short)NULL); + } else { + if (bytes.length > Short.MAX_VALUE) { + throw new IllegalArgumentException("too large bytes length:" + bytes.length); + } + checkExpend(bytes.length + BytesUtils.SHORT_BYTE_LENGTH); + super.put((short)bytes.length); + super.put(bytes); + } + } + + @Override + public void put4PrefixedBytes(final byte[] bytes) { + if (bytes == null) { + checkExpend(BytesUtils.INT_BYTE_LENGTH); + super.put(NULL); + } else { + checkExpend(bytes.length + BytesUtils.INT_BYTE_LENGTH); + super.put(bytes.length); + super.put(bytes); + } + } + + @Override + public void putPadString(String string, int totalLength) { + checkExpend(totalLength); + super.putPadString(string, totalLength); + } + + + @Override + public void putPrefixedString(final String string) { + byte[] bytes = BytesUtils.toBytes(string); + this.putPrefixedBytes(bytes); + } + + @Override + public void put2PrefixedString(final String string) { + byte[] bytes = BytesUtils.toBytes(string); + this.put2PrefixedBytes(bytes); + } + + @Override + public void put4PrefixedString(final String string) { + byte[] bytes = BytesUtils.toBytes(string); + this.put4PrefixedBytes(bytes); + } + + @Override + public void put(final byte v) { + checkExpend(1); + super.put(v); + } + + @Override + public void put(final boolean v) { + checkExpend(1); + super.put(v); + } + + @Override + public void put(final short v) { + checkExpend(2); + super.put(v); + } + + @Override + public void put(final int v) { + checkExpend(4); + super.put(v); + } + + public void putVar(final int v) { + checkExpend(BytesUtils.VLONG_MAX_SIZE); + super.putVar(v); + } + + public void putSVar(final int v) { + checkExpend(BytesUtils.VINT_MAX_SIZE); + super.putSVar(v); + } + + public void putVar(final long v) { + checkExpend(BytesUtils.VLONG_MAX_SIZE); + super.putVar(v); + } + + public void putSVar(final long v) { + checkExpend(BytesUtils.VLONG_MAX_SIZE); + super.putSVar(v); + } + + @Override + public void put(final long v) { + checkExpend(8); + super.put(v); + } + + @Override + public void put(final byte[] v) { + if (v == null) { + throw new NullPointerException("v must not be null"); + } + checkExpend(v.length); + super.put(v); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/buffer/Buffer.java b/src/main/java/com/nhn/pinpoint/common/buffer/Buffer.java new file mode 100644 index 000000000..9a7e2115b --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/buffer/Buffer.java @@ -0,0 +1,154 @@ +package com.nhn.pinpoint.common.buffer; + +/** + * @author emeroad + */ +public interface Buffer { + + public static final int BOOLEAN_FALSE = 0; + public static final int BOOLEAN_TRUE = 1; + + public static final byte[] EMPTY = new byte[0]; + + public static final String UTF8 = "UTF-8"; + + void putPadBytes(byte[] bytes, int totalLength); + + void putPrefixedBytes(byte[] bytes); + + void put2PrefixedBytes(byte[] bytes); + + void put4PrefixedBytes(byte[] bytes); + + void putPadString(String string, int totalLength); + + void putPrefixedString(String string); + + void put2PrefixedString(String string); + + void put4PrefixedString(String string); + + void put(byte v); + + void put(boolean v); + + void put(int v); + + /** + * 가변인코딩을 사용하여 저장한다. + * 상수값에 강한 인코딩을 한다. + * 음수값이 들어갈 경우 사이즈가 fixint 인코딩 보다 더 커짐, 음수값의 분포가 많을 경우 매우 비효율적임. + * 이 경우 putSVar를 사용한다. putSVar에 비해서 zigzag연산이 없어 cpu를 약간 덜사용하는 이점 뿐이 없음. + * 음수가 조금이라도 들어갈 가능성이 있다면 putSVar를 사용하는 것이 이득이다.. + * 1~10 byte사용 + * max : 5, min 10 + * @param v + */ + void putVar(int v); + + /** + * 가변인코딩을 사용하여 저장한다. + * 상수, 음수의 분포가 동일한 데이터 일 경우 사용한다. + * 1~5 사용 + * max : 5, min :5 + * @param v + */ + void putSVar(int v); + + void put(short v); + + void put(long v); + + /** + * 가변인코딩을 사용하여 저장한다. + * 상수값에 강한 인코딩을 한다. + * 음수값이 들어갈 경우 사이즈가 fixint 인코딩 보다 더 커짐 + * 이경우 putSVar를 사용한다. + * @param v + */ + void putVar(long v); + + /** + * 가변인코딩을 사용하여 저장한다. + * 상수, 음수의 분포가 동일한 데이터 일 경우 사용한다. + * @param v + */ + void putSVar(long v); + + void put(double v); + + /** + * 가변인코딩을 사용하여 저장한다. + * 상수값에 강한 인코딩을 한다. + * 음수값이 들어갈 경우 사이즈가 fixint 인코딩 보다 더 커짐 + * 이경우 putSVar를 사용한다. + * @param v + */ + void putVar(double v); + + /** + * 가변인코딩을 사용하여 저장한다. + * 상수, 음수의 분포가 동일한 데이터 일 경우 사용한다. + * @param v + */ + void putSVar(double v); + + void put(byte[] v); + + byte readByte(); + + int readUnsignedByte(); + + boolean readBoolean(); + + int readInt(); + + int readVarInt(); + + int readSVarInt(); + + + short readShort(); + + long readLong(); + + long readVarLong(); + + long readSVarLong(); + + double readDouble(); + + double readVarDouble(); + + double readSVarDouble(); + + byte[] readPadBytes(int totalLength); + + String readPadString(int totalLength); + + String readPadStringAndRightTrim(int totalLength); + + byte[] readPrefixedBytes(); + + byte[] read2PrefixedBytes(); + + byte[] read4PrefixedBytes(); + + String readPrefixedString(); + + String read2PrefixedString(); + + String read4PrefixedString(); + + byte[] getBuffer(); + + byte[] copyBuffer(); + + byte[] getInternalBuffer(); + + void setOffset(int offset); + + int getOffset(); + + int limit(); +} diff --git a/src/main/java/com/nhn/pinpoint/common/buffer/FixedBuffer.java b/src/main/java/com/nhn/pinpoint/common/buffer/FixedBuffer.java new file mode 100644 index 000000000..804f37e3f --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/buffer/FixedBuffer.java @@ -0,0 +1,479 @@ +package com.nhn.pinpoint.common.buffer; + +import com.nhn.pinpoint.common.util.BytesUtils; + +import java.io.UnsupportedEncodingException; + +/** + * @author emeroad + */ +public class FixedBuffer implements Buffer { + protected static final int NULL = -1; + protected byte[] buffer; + protected int offset; + + public FixedBuffer() { + this(32); + } + + public FixedBuffer(final int bufferSize) { + if (bufferSize < 0) { + throw new IllegalArgumentException("negative bufferSize:" + bufferSize); + } + this.buffer = new byte[bufferSize]; + this.offset = 0; + } + + public FixedBuffer(final byte[] buffer) { + if (buffer == null) { + throw new NullPointerException("buffer must not be null"); + } + this.buffer = buffer; + this.offset = 0; + } + + @Override + public void putPadBytes(byte[] bytes, int totalLength) { + if (bytes == null) { + bytes = EMPTY; + } + if (bytes.length > totalLength) { + throw new IllegalArgumentException("bytes too big:" + bytes.length + " totalLength:" + totalLength); + } + put(bytes); + final int padSize = totalLength - bytes.length; + if (padSize > 0) { + putPad(padSize); + } + } + + private void putPad(int padSize) { + for (int i = 0; i < padSize; i++) { + put((byte)0); + } + } + + + @Override + public void putPrefixedBytes(final byte[] bytes) { + if (bytes == null) { + putSVar(NULL); + } else { + putSVar(bytes.length); + put(bytes); + } + } + + @Override + public void put2PrefixedBytes(final byte[] bytes) { + if (bytes == null) { + put((short)NULL); + } else { + if (bytes.length > Short.MAX_VALUE) { + throw new IllegalArgumentException("too large bytes length:" + bytes.length); + } + put((short)bytes.length); + put(bytes); + } + } + + @Override + public void put4PrefixedBytes(final byte[] bytes) { + if (bytes == null) { + put(NULL); + } else { + put(bytes.length); + put(bytes); + } + } + + @Override + public void putPadString(String string, int totalLength) { + final byte[] bytes = BytesUtils.toBytes(string); + putPadBytes(bytes, totalLength); + } + + @Override + public void putPrefixedString(final String string) { + final byte[] bytes = BytesUtils.toBytes(string); + putPrefixedBytes(bytes); + } + + @Override + public void put2PrefixedString(final String string) { + final byte[] bytes = BytesUtils.toBytes(string); + if (bytes == null) { + put((short)NULL); + return; + } + if (bytes.length > Short.MAX_VALUE) { + throw new IllegalArgumentException("too large String size:" + bytes.length); + } + put2PrefixedBytes(bytes); + } + + @Override + public void put4PrefixedString(final String string) { + final byte[] bytes = BytesUtils.toBytes(string); + if (bytes == null) { + put(NULL); + return; + } + put4PrefixedBytes(bytes); + } + + @Override + public void put(final byte v) { + this.buffer[offset++] = v; + } + + @Override + public void put(final boolean v) { + if (v) { + this.buffer[offset++] = BOOLEAN_TRUE; + } else { + this.buffer[offset++] = BOOLEAN_FALSE; + } + } + + @Override + public void put(final int v) { + this.offset = BytesUtils.writeInt(v, buffer, offset); + } + + public void putVar(int v) { + if (v >= 0) { + putVar32(v); + } else { + putVar64((long) v); + } + } + + public void putSVar(int v) { + this.offset = BytesUtils.writeSVar32(v, buffer, offset); + } + + private void putVar32(int v) { + this.offset = BytesUtils.writeVar32(v, buffer, offset); + } + + @Override + public void put(final short v) { + this.offset = BytesUtils.writeShort(v, buffer, offset); + } + + @Override + public void put(final long v) { + this.offset = BytesUtils.writeLong(v, buffer, offset); + } + + @Override + public void putVar(long v) { + putVar64(v); + } + + @Override + public void putSVar(long v) { + putVar64(BytesUtils.longToZigZag(v)); + } + + private void putVar64(long v) { + this.offset = BytesUtils.writeVar64(v, buffer, offset); + } + + @Override + public void put(double v) { + put(Double.doubleToRawLongBits(v)); + } + + @Override + public void putVar(double v) { + putVar(Double.doubleToRawLongBits(v)); + } + + @Override + public void putSVar(double v) { + putSVar(Double.doubleToRawLongBits(v)); + } + + @Override + public void put(final byte[] v) { + if (v == null) { + throw new NullPointerException("v must not be null"); + } + System.arraycopy(v, 0, buffer, offset, v.length); + this.offset = offset + v.length; + } + + @Override + public byte readByte() { + return this.buffer[offset++]; + } + + @Override + public int readUnsignedByte() { + return readByte() & 0xff; + } + + @Override + public boolean readBoolean() { + final byte b = readByte(); + return b == BOOLEAN_TRUE; + } + + @Override + public int readInt() { + final int i = BytesUtils.bytesToInt(buffer, offset); + this.offset = this.offset + 4; + return i; + } + + @Override + public int readVarInt() { + // protocol buffer의 var encoding 차용. + byte v = readByte(); + if (v >= 0) { + return v; + } + int result = v & 0x7f; + if ((v = readByte()) >= 0) { + result |= v << 7; + } else { + result |= (v & 0x7f) << 7; + if ((v = readByte()) >= 0) { + result |= v << 14; + } else { + result |= (v & 0x7f) << 14; + if ((v = readByte()) >= 0) { + result |= v << 21; + } else { + result |= (v & 0x7f) << 21; + result |= (v = readByte()) << 28; + if (v < 0) { + for (int i = 0; i < 5; i++) { + if (readByte() >= 0) { + return result; + } + } + throw new IllegalArgumentException("invalid varInt"); + } + } + } + } + return result; + } + + public int readSVarInt() { + return BytesUtils.zigzagToInt(readVarInt()); + } + + @Override + public short readShort() { + final short i = BytesUtils.bytesToShort(buffer, offset); + this.offset = this.offset + 2; + return i; + } + + public int readUnsignedShort() { + return readShort() & 0xFFFF; + } + + @Override + public long readLong() { + final long l = BytesUtils.bytesToLong(buffer, offset); + this.offset = this.offset + 8; + return l; + } + + @Override + public long readVarLong() { + int shift = 0; + long result = 0; + while (shift < 64) { + final byte v = readByte(); + result |= (long)(v & 0x7F) << shift; + if ((v & 0x80) == 0) { + return result; + } + shift += 7; + } + throw new IllegalArgumentException("invalid varLong"); + } + + @Override + public long readSVarLong() { + return BytesUtils.zigzagToLong(readVarLong()); + } + + @Override + public double readDouble() { + return Double.longBitsToDouble(this.readLong()); + } + + @Override + public double readVarDouble() { + return Double.longBitsToDouble(this.readVarLong()); + } + + @Override + public double readSVarDouble() { + return Double.longBitsToDouble(this.readSVarLong()); + } + + @Override + public byte[] readPadBytes(int totalLength) { + return readBytes(totalLength); + } + + @Override + public String readPadString(int totalLength) { + return readString(totalLength); + } + + @Override + public String readPadStringAndRightTrim(int totalLength) { + String string = BytesUtils.toStringAndRightTrim(buffer, offset, totalLength); + this.offset = offset + totalLength; + return string ; + } + + + @Override + public byte[] readPrefixedBytes() { + final int size = readSVarInt(); + if (size == NULL) { + return null; + } + if (size == 0) { + return EMPTY; + } + return readBytes(size); + } + + @Override + public byte[] read2PrefixedBytes() { + final int size = readShort(); + if (size == NULL) { + return null; + } + if (size == 0) { + return EMPTY; + } + return readBytes(size); + } + + @Override + public byte[] read4PrefixedBytes() { + final int size = readInt(); + if (size == NULL) { + return null; + } + if (size == 0) { + return EMPTY; + } + return readBytes(size); + } + + + private byte[] readBytes(int size) { + final byte[] b = new byte[size]; + System.arraycopy(buffer, offset, b, 0, size); + this.offset = offset + size; + return b; + } + + @Override + public String readPrefixedString() { + final int size = readSVarInt(); + if (size == NULL) { + return null; + } + if (size == 0) { + return ""; + } + return readString(size); + } + + @Override + public String read2PrefixedString() { + final int size = readShort(); + if (size == NULL) { + return null; + } + if (size == 0) { + return ""; + } + return readString(size); + } + + @Override + public String read4PrefixedString() { + final int size = readInt(); + if (size == NULL) { + return null; + } + if (size == 0) { + return ""; + } + return readString(size); + } + + + private String readString(final int size) { + final String s = newString(size); + this.offset = offset + size; + return s; + } + + private String newString(final int size) { + try { + return new String(buffer, offset, size, UTF8); + } catch (UnsupportedEncodingException ue) { + throw new RuntimeException(ue.getMessage(), ue); + } + } + + /** + * 암묵적으로 성능을 내부 buffe length와 offset의 사이즈가 같으면 메모리 copy를 하지 않고 그냥 internal buffer를 리턴하므로 주의해야 한다. + * @return + */ + @Override + public byte[] getBuffer() { + if (offset == buffer.length) { + return this.buffer; + } else { + return copyBuffer(); + } + } + + @Override + public byte[] copyBuffer() { + final byte[] copy = new byte[offset]; + System.arraycopy(buffer, 0, copy, 0, offset); + return copy; + } + + /** + * 내부 buffer를 리턴한다. + * @return + */ + @Override + public byte[] getInternalBuffer() { + return this.buffer; + } + + @Override + public void setOffset(int offset) { + this.offset = offset; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public int limit() { + return buffer.length - offset; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/buffer/OffsetAutomaticBuffer.java b/src/main/java/com/nhn/pinpoint/common/buffer/OffsetAutomaticBuffer.java new file mode 100644 index 000000000..4c2b9ba33 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/buffer/OffsetAutomaticBuffer.java @@ -0,0 +1,32 @@ +package com.nhn.pinpoint.common.buffer; + +/** + * @author emeroad + */ +public class OffsetAutomaticBuffer extends AutomaticBuffer { + + protected final int startOffset; + + public OffsetAutomaticBuffer(final byte[] buffer, final int offset) { + if (buffer == null) { + throw new NullPointerException("buffer must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (offset > buffer.length) { + throw new IllegalArgumentException("offset:" + offset + " > buffer.length:" + buffer.length); + } + this.buffer = buffer; + this.offset = offset; + this.startOffset = offset; + } + + @Override + public byte[] getBuffer() { + final int bufferSize = offset - startOffset; + final byte[] copy = new byte[bufferSize]; + System.arraycopy(buffer, startOffset, copy, 0, bufferSize); + return copy; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/buffer/OffsetFixedBuffer.java b/src/main/java/com/nhn/pinpoint/common/buffer/OffsetFixedBuffer.java new file mode 100644 index 000000000..ee3f6c60c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/buffer/OffsetFixedBuffer.java @@ -0,0 +1,32 @@ +package com.nhn.pinpoint.common.buffer; + +/** + * @author emeroad + */ +public class OffsetFixedBuffer extends FixedBuffer { + + protected final int startOffset; + + public OffsetFixedBuffer(final byte[] buffer, final int offset) { + if (buffer == null) { + throw new NullPointerException("buffer must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (offset > buffer.length) { + throw new IllegalArgumentException("offset:" + offset + " > buffer.length:" + buffer.length); + } + this.buffer = buffer; + this.offset = offset; + this.startOffset = offset; + } + + @Override + public byte[] getBuffer() { + final int bufferSize = offset - startOffset; + final byte[] copy = new byte[bufferSize]; + System.arraycopy(buffer, startOffset, copy, 0, bufferSize); + return copy; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/EmptyLimitEventHandler.java b/src/main/java/com/nhn/pinpoint/common/hbase/EmptyLimitEventHandler.java new file mode 100644 index 000000000..f05b771cc --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/EmptyLimitEventHandler.java @@ -0,0 +1,13 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.hbase.client.Result; + +/** + * @author emeroad + */ +public class EmptyLimitEventHandler implements LimitEventHandler{ + + @Override + public void handleLastResult(Result lastResult) { + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/HBaseAdminTemplate.java b/src/main/java/com/nhn/pinpoint/common/hbase/HBaseAdminTemplate.java new file mode 100644 index 000000000..784f14d8a --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/HBaseAdminTemplate.java @@ -0,0 +1,78 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.MasterNotRunningException; +import org.apache.hadoop.hbase.ZooKeeperConnectionException; +import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.springframework.data.hadoop.hbase.HbaseSystemException; + +import java.io.IOException; + +/** + * @author emeroad + */ +public class HBaseAdminTemplate { + + private final HBaseAdmin hBaseAdmin; + + public HBaseAdminTemplate(Configuration configuration) { + try { + this.hBaseAdmin = new HBaseAdmin(configuration); + } catch (MasterNotRunningException e) { + throw new HbaseSystemException(e); + } catch (ZooKeeperConnectionException e) { + throw new HbaseSystemException(e); + } + } + + public boolean createTableIfNotExist(HTableDescriptor htd) { + try { + if (!hBaseAdmin.tableExists(htd.getName())) { + this.hBaseAdmin.createTable(htd); + return true; + } + return false; + } catch (IOException e) { + throw new HbaseSystemException(e); + } + } + + public boolean tableExists(String tableName) { + try { + return hBaseAdmin.tableExists(tableName); + } catch (IOException e) { + throw new HbaseSystemException(e); + } + } + + public boolean dropTableIfExist(String tableName) { + try { + if (hBaseAdmin.tableExists(tableName)) { + this.hBaseAdmin.disableTable(tableName); + this.hBaseAdmin.deleteTable(tableName); + return true; + } + return false; + } catch (IOException e) { + throw new HbaseSystemException(e); + } + } + + public void dropTable(String tableName) { + try { + this.hBaseAdmin.disableTable(tableName); + this.hBaseAdmin.deleteTable(tableName); + } catch (IOException e) { + throw new HbaseSystemException(e); + } + } + + public void close() { + try { + this.hBaseAdmin.close(); + } catch (IOException e) { + throw new HbaseSystemException(e); + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/HBaseTables.java b/src/main/java/com/nhn/pinpoint/common/hbase/HBaseTables.java new file mode 100644 index 000000000..5b9765101 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/HBaseTables.java @@ -0,0 +1,74 @@ +package com.nhn.pinpoint.common.hbase; + +import com.nhn.pinpoint.common.PinpointConstants; +import org.apache.hadoop.hbase.util.Bytes; + +/** + * @author emeroad + */ +public final class HBaseTables { + + public static final int APPLICATION_NAME_MAX_LEN = PinpointConstants.APPLICATION_NAME_MAX_LEN; + public static final int AGENT_NAME_MAX_LEN = PinpointConstants.AGENT_NAME_MAX_LEN; + + + public static final String APPLICATION_TRACE_INDEX = "ApplicationTraceIndex"; + public static final byte[] APPLICATION_TRACE_INDEX_CF_TRACE = Bytes.toBytes("I"); // applicationIndex + public static final int APPLICATION_TRACE_INDEX_ROW_DISTRIBUTE_SIZE = 1; // applicationIndex hash size + + public static final String AGENT_STAT = "AgentStat"; + public static final byte[] AGENT_STAT_CF_STATISTICS = Bytes.toBytes("S"); // agent statistics column family + public static final byte[] AGENT_STAT_CF_STATISTICS_V1 = Bytes.toBytes("V1"); // qualifier + public static final byte[] AGENT_STAT_CF_STATISTICS_MEMORY_GC = Bytes.toBytes("Gc"); // qualifier for Heap Memory/Gc statistics + public static final byte[] AGENT_STAT_CF_STATISTICS_CPU_LOAD = Bytes.toBytes("Cpu"); // qualifier for CPU load statistics + public static final int AGENT_STAT_ROW_DISTRIBUTE_SIZE = 1; // agent statistics hash size + + public static final String TRACES = "Traces"; + public static final byte[] TRACES_CF_SPAN = Bytes.toBytes("S"); //Span + public static final byte[] TRACES_CF_ANNOTATION = Bytes.toBytes("A"); //Annotation + public static final byte[] TRACES_CF_TERMINALSPAN = Bytes.toBytes("T"); //TerminalSpan + + public static final String APPLICATION_INDEX = "ApplicationIndex"; + public static final byte[] APPLICATION_INDEX_CF_AGENTS = Bytes.toBytes("Agents"); + + public static final String AGENTINFO = "AgentInfo"; + public static final byte[] AGENTINFO_CF_INFO = Bytes.toBytes("Info"); + public static final byte[] AGENTINFO_CF_INFO_IDENTIFIER = Bytes.toBytes("i"); + + @Deprecated + public static final String AGENTID_APPLICATION_INDEX = "AgentIdApplicationIndex"; + @Deprecated + public static final byte[] AGENTID_APPLICATION_INDEX_CF_APPLICATION = Bytes.toBytes("Application"); + + + public static final String SQL_METADATA = "SqlMetaData"; + public static final byte[] SQL_METADATA_CF_SQL = Bytes.toBytes("Sql"); + + public static final String STRING_METADATA = "StringMetaData"; + public static final byte[] STRING_METADATA_CF_STR = Bytes.toBytes("Str"); + + public static final String API_METADATA = "ApiMetaData"; + public static final byte[] API_METADATA_CF_API = Bytes.toBytes("Api"); + + public static final String MAP_STATISTICS_CALLER = "ApplicationMapStatisticsCaller"; + public static final byte[] MAP_STATISTICS_CALLER_CF_COUNTER = Bytes.toBytes("C"); + + public static final String MAP_STATISTICS_CALLEE = "ApplicationMapStatisticsCallee"; + // 나중에 삭제할것. 관련 코드도같이 제거해도 됨. + public static final byte[] MAP_STATISTICS_CALLEE_CF_COUNTER = Bytes.toBytes("C"); + // 신버전의 column Name저장용. + public static final byte[] MAP_STATISTICS_CALLEE_CF_VER2_COUNTER = Bytes.toBytes("D"); + + public static final String MAP_STATISTICS_SELF = "ApplicationMapStatisticsSelf"; + public static final byte[] MAP_STATISTICS_SELF_CF_COUNTER = Bytes.toBytes("C"); + + public static final String HOST_APPLICATION_MAP = "HostApplicationMap"; + public static final byte[] HOST_APPLICATION_MAP_CF_MAP = Bytes.toBytes("M"); + + public static final String HOST_APPLICATION_MAP_VER2 = "HostApplicationMap_Ver2"; + public static final byte[] HOST_APPLICATION_MAP_VER2_CF_MAP = Bytes.toBytes("M"); + + + public static final short STATISTICS_CQ_ERROR_SLOT_NUMBER = -1; + public static final byte[] STATISTICS_CQ_ERROR_SLOT = Bytes.toBytes(STATISTICS_CQ_ERROR_SLOT_NUMBER); +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/HTableCallBack.java b/src/main/java/com/nhn/pinpoint/common/hbase/HTableCallBack.java new file mode 100644 index 000000000..83b213720 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/HTableCallBack.java @@ -0,0 +1,14 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.hbase.client.HTable; + +import java.io.IOException; + +/** + * @author emeroad + */ +public interface HTableCallBack { + void doExecute(HTable hTable) throws IOException; + +// void doMultiExecute(HTable... tables) throws IOException; +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/HbaseOperations2.java b/src/main/java/com/nhn/pinpoint/common/hbase/HbaseOperations2.java new file mode 100644 index 000000000..a330bc5f8 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/HbaseOperations2.java @@ -0,0 +1,96 @@ +package com.nhn.pinpoint.common.hbase; + +import java.util.List; + +import com.sematext.hbase.wd.AbstractRowKeyDistributor; +import org.apache.hadoop.hbase.client.*; +import org.springframework.data.hadoop.hbase.HbaseOperations; +import org.springframework.data.hadoop.hbase.ResultsExtractor; +import org.springframework.data.hadoop.hbase.RowMapper; + +/** + * @author emeroad + */ +public interface HbaseOperations2 extends HbaseOperations { + /** + * Gets an individual row from the given table. The content is mapped by the given action. + * + * @param tableName target table + * @param rowName row name + * @param mapper row mapper + * @return object mapping the target row + */ + T get(String tableName, byte[] rowName, final RowMapper mapper); + + /** + * Gets an individual row from the given table. The content is mapped by the given action. + * + * @param tableName target table + * @param rowName row name + * @param familyName column family + * @param mapper row mapper + * @return object mapping the target row + */ + T get(String tableName, byte[] rowName, byte[] familyName, final RowMapper mapper); + + /** + * Gets an individual row from the given table. The content is mapped by the given action. + * + * @param tableName target table + * @param rowName row name + * @param familyName family + * @param qualifier column qualifier + * @param mapper row mapper + * @return object mapping the target row + */ + T get(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final RowMapper mapper); + + T get(String tableName, final Get get, final RowMapper mapper); + + List get(String tableName, final List get, final RowMapper mapper); + + + void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final byte[] value); + + void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final Long timestamp, final byte[] value); + + void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final T value, final ValueMapper mapper); + + void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final Long timestamp, final T value, final ValueMapper mapper); + + void put(String tableName, final Put put); + + void put(String tableName, final List puts); + + void delete(String tableName, final Delete delete); + + void delete(String tableName, final List deletes); + + List find(String tableName, final List scans, final ResultsExtractor action); + + List> find(String tableName, final List scans, final RowMapper action); + + List find(String tableName, final Scan scan, AbstractRowKeyDistributor rowKeyDistributor, final RowMapper action); + + List find(String tableName, final Scan scan, AbstractRowKeyDistributor rowKeyDistributor, int limit, final RowMapper action); + + List find(String tableName, final Scan scan, final AbstractRowKeyDistributor rowKeyDistributor, int limit, final RowMapper action, final LimitEventHandler limitEventHandler); + + T find(String tableName, final Scan scan, final AbstractRowKeyDistributor rowKeyDistributor, final ResultsExtractor action); + + Result increment(String tableName, final Increment increment); + + /** + * increment list는 부분적으로 exception이 throw될수 있다. 이 경우 lastException이 사용에게 던져진다. + * 특정 increment에서 오류를 감지 해서 재시도 한다하는 로직의 경우 lastException던지는 문제 인해 어느게 실패 했는지 알수 없는 한계가 있다. + * @param tableName + * @param incrementList + * @return + */ + List increment(String tableName, final List incrementList); + + long incrementColumnValue(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final long amount); + + long incrementColumnValue(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final long amount, final boolean writeToWAL); + +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/HbaseTemplate2.java b/src/main/java/com/nhn/pinpoint/common/hbase/HbaseTemplate2.java new file mode 100644 index 000000000..fdfd4f80e --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/HbaseTemplate2.java @@ -0,0 +1,560 @@ +package com.nhn.pinpoint.common.hbase; + +import com.nhn.pinpoint.common.util.StopWatch; +import com.sematext.hbase.wd.AbstractRowKeyDistributor; +import com.sematext.hbase.wd.DistributedScanner; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.data.hadoop.hbase.*; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +/** + * @author emeroad + */ +public class HbaseTemplate2 extends HbaseTemplate implements HbaseOperations2, InitializingBean, DisposableBean { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private PooledHTableFactory pooledHTableFactory; + private int poolSize = PooledHTableFactory.DEFAULT_POOL_SIZE; + + private ExecutorService executor = newCachedThreadPool(); + + public HbaseTemplate2() { + } + + public ExecutorService newCachedThreadPool() { + return new ThreadPoolExecutor(0, 128, + 60L, TimeUnit.SECONDS, + new LinkedBlockingQueue()); + } + +// public Executor getExecutor() { +// return executor; +// } + +// public void setExecutor(Executor executor) { +// this.executor = executor; +// } + + public HbaseTemplate2(Configuration configuration) { + Assert.notNull(configuration); + } + + public HbaseTemplate2(Configuration configuration, int poolSize) { + Assert.notNull(configuration); + this.poolSize = poolSize; + } + + public int getPoolSize() { + return poolSize; + } + + public void setPoolSize(int hTablePoolSize) { + this.poolSize = hTablePoolSize; + } + + @Override + public void afterPropertiesSet() { + Configuration configuration = getConfiguration(); + Assert.notNull(configuration, "configuration is required"); + this.pooledHTableFactory = new PooledHTableFactory(configuration, poolSize); + this.setTableFactory(pooledHTableFactory); + } + + @Override + public void destroy() throws Exception { + if (pooledHTableFactory != null) { + this.pooledHTableFactory.destroy(); + } + + final ExecutorService executor = this.executor; + if (executor != null) { + executor.shutdown(); + try { + executor.awaitTermination(2000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + @Override + public T find(String tableName, String family, final ResultsExtractor action) { + Scan scan = new Scan(); + scan.addFamily(family.getBytes(getCharset())); + return find(tableName, scan, action); + } + + @Override + public T find(String tableName, String family, String qualifier, final ResultsExtractor action) { + Scan scan = new Scan(); + scan.addColumn(family.getBytes(getCharset()), qualifier.getBytes(getCharset())); + return find(tableName, scan, action); + } + + @Override + public T find(String tableName, final Scan scan, final ResultsExtractor action) { + return execute(tableName, new TableCallback() { + @Override + public T doInTable(HTableInterface htable) throws Throwable { + final ResultScanner scanner = htable.getScanner(scan); + try { + return action.extractData(scanner); + } finally { + scanner.close(); + } + } + }); + } + + @Override + public List find(String tableName, String family, final RowMapper action) { + Scan scan = new Scan(); + scan.addFamily(family.getBytes(getCharset())); + return find(tableName, scan, action); + } + + @Override + public List find(String tableName, String family, String qualifier, final RowMapper action) { + Scan scan = new Scan(); + scan.addColumn(family.getBytes(getCharset()), qualifier.getBytes(getCharset())); + return find(tableName, scan, action); + } + + @Override + public List find(String tableName, final Scan scan, final RowMapper action) { + return find(tableName, scan, new RowMapperResultsExtractor(action)); + } + +// public class ParallelScan { +// private String tableName; +// private Scan scan; +// private RowMapper mapper; +// +// public String getTableName() { +// return tableName; +// } +// +// public void setTableName(String tableName) { +// this.tableName = tableName; +// } +// +// public Scan getScan() { +// return scan; +// } +// +// public void setScan(Scan scan) { +// this.scan = scan; +// } +// +// public RowMapper getMapper() { +// return mapper; +// } +// +// public void setMapper(RowMapper action) { +// this.mapper = action; +// } +// } +// +// /** +// * sanner를 병렬로 돌리기 위한 api +// * scanner 구현 자체가 얼마나 병렬인지 애매해서 무조껀 만들기도 그러니 일단 주석처리. +// * @return +// */ +// public List>> findParallel(final ParallelScan parallelScans) { +// Callable> tCallable = new Callable>() { +// @Override +// public List call() throws Exception { +// return find(parallelScans.getTableName(), parallelScans.getScan(), parallelScans.getMapper()); +// } +// }; +// ArrayList>> callables = new ArrayList>>(); +// callables.add(tCallable); +// +// List>> futures = null; +// try { +// futures = this.executor.invokeAll(callables); +// } catch (InterruptedException e) { +// Thread.currentThread().interrupt(); +// } +// return futures; +// } + + @Override + public T get(String tableName, String rowName, final RowMapper mapper) { + return get(tableName, rowName, null, null, mapper); + } + + @Override + public T get(String tableName, String rowName, String familyName, final RowMapper mapper) { + return get(tableName, rowName, familyName, null, mapper); + } + + @Override + public T get(String tableName, final String rowName, final String familyName, final String qualifier, final RowMapper mapper) { + return execute(tableName, new TableCallback() { + @Override + public T doInTable(HTableInterface htable) throws Throwable { + Get get = new Get(rowName.getBytes(getCharset())); + if (familyName != null) { + byte[] family = familyName.getBytes(getCharset()); + + if (qualifier != null) { + get.addColumn(family, qualifier.getBytes(getCharset())); + } else { + get.addFamily(family); + } + } + Result result = htable.get(get); + return mapper.mapRow(result, 0); + } + }); + } + + + @Override + public T get(String tableName, byte[] rowName, RowMapper mapper) { + return get(tableName, rowName, null, null, mapper); + } + + @Override + public T get(String tableName, byte[] rowName, byte[] familyName, RowMapper mapper) { + return get(tableName, rowName, familyName, null, mapper); + } + + @Override + public T get(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final RowMapper mapper) { + return execute(tableName, new TableCallback() { + @Override + public T doInTable(HTableInterface htable) throws Throwable { + Get get = new Get(rowName); + if (familyName != null) { + if (qualifier != null) { + get.addColumn(familyName, qualifier); + } else { + get.addFamily(familyName); + } + } + Result result = htable.get(get); + return mapper.mapRow(result, 0); + } + }); + } + + @Override + public T get(String tableName, final Get get, final RowMapper mapper) { + return execute(tableName, new TableCallback() { + @Override + public T doInTable(HTableInterface htable) throws Throwable { + Result result = htable.get(get); + return mapper.mapRow(result, 0); + } + }); + } + + @Override + public List get(String tableName, final List getList, final RowMapper mapper) { + return execute(tableName, new TableCallback>() { + @Override + public List doInTable(HTableInterface htable) throws Throwable { + Result[] result = htable.get(getList); + List list = new ArrayList(result.length); + for (int i = 0; i < result.length; i++) { + T t = mapper.mapRow(result[i], i); + list.add(t); + } + return list; + } + }); + } + + + public void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final byte[] value) { + put(tableName, rowName, familyName, qualifier, null, value); + } + + public void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final Long timestamp, final byte[] value) { + execute(tableName, new TableCallback() { + @Override + public Object doInTable(HTableInterface htable) throws Throwable { + Put put = new Put(rowName); + if (familyName != null) { + if (timestamp == null) { + put.add(familyName, qualifier, value); + } else { + put.add(familyName, qualifier, timestamp, value); + } + } + htable.put(put); + return null; + } + }); + } + + public void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final T value, final ValueMapper mapper) { + put(tableName, rowName, familyName, qualifier, null, value, mapper); + } + + public void put(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final Long timestamp, final T value, final ValueMapper mapper) { + execute(tableName, new TableCallback() { + @Override + public T doInTable(HTableInterface htable) throws Throwable { + Put put = new Put(rowName); + byte[] bytes = mapper.mapValue(value); + if (familyName != null) { + if (timestamp == null) { + put.add(familyName, qualifier, bytes); + } else { + put.add(familyName, qualifier, timestamp, bytes); + } + } + htable.put(put); + return null; + } + }); + } + + public void put(String tableName, final Put put) { + execute(tableName, new TableCallback() { + @Override + public Object doInTable(HTableInterface htable) throws Throwable { + htable.put(put); + return null; + } + }); + } + + public void put(String tableName, final List puts) { + execute(tableName, new TableCallback() { + @Override + public Object doInTable(HTableInterface htable) throws Throwable { + htable.put(puts); + return null; + } + }); + } + + public void delete(String tableName, final Delete delete) { + execute(tableName, new TableCallback() { + @Override + public Object doInTable(HTableInterface htable) throws Throwable { + htable.delete(delete); + return null; + } + }); + } + + public void delete(String tableName, final List deletes) { + execute(tableName, new TableCallback() { + @Override + public Object doInTable(HTableInterface htable) throws Throwable { + htable.delete(deletes); + return null; + } + }); + } + + @Override + public List find(String tableName, final List scanList, final ResultsExtractor action) { + return execute(tableName, new TableCallback>() { + @Override + public List doInTable(HTableInterface htable) throws Throwable { + List result = new ArrayList(scanList.size()); + for (Scan scan : scanList) { + final ResultScanner scanner = htable.getScanner(scan); + try { + T t = action.extractData(scanner); + result.add(t); + } finally { + scanner.close(); + } + } + return result; + } + }); + } + + @Override + public List> find(String tableName, List scanList, RowMapper action) { + return find(tableName, scanList, new RowMapperResultsExtractor(action)); + } + + public List find(String tableName, final Scan scan, final AbstractRowKeyDistributor rowKeyDistributor, final RowMapper action) { + final ResultsExtractor> resultsExtractor = new RowMapperResultsExtractor(action); + return execute(tableName, new TableCallback>() { + @Override + public List doInTable(HTableInterface htable) throws Throwable { + final ResultScanner scanner = createDistributeScanner(htable, scan, rowKeyDistributor); + try { + return resultsExtractor.extractData(scanner); + } finally { + scanner.close(); + } + } + }); + } + + public List find(String tableName, final Scan scan, final AbstractRowKeyDistributor rowKeyDistributor, int limit, final RowMapper action) { + final ResultsExtractor> resultsExtractor = new LimitRowMapperResultsExtractor(action, limit); + return execute(tableName, new TableCallback>() { + @Override + public List doInTable(HTableInterface htable) throws Throwable { + final ResultScanner scanner = createDistributeScanner(htable, scan, rowKeyDistributor); + try { + return resultsExtractor.extractData(scanner); + } finally { + scanner.close(); + } + } + }); + } + + public List find(String tableName, final Scan scan, final AbstractRowKeyDistributor rowKeyDistributor, int limit, final RowMapper action, final LimitEventHandler limitEventHandler) { + final LimitRowMapperResultsExtractor resultsExtractor = new LimitRowMapperResultsExtractor(action, limit, limitEventHandler); + return execute(tableName, new TableCallback>() { + @Override + public List doInTable(HTableInterface htable) throws Throwable { + final ResultScanner scanner = createDistributeScanner(htable, scan, rowKeyDistributor); + try { + return resultsExtractor.extractData(scanner); + } finally { + scanner.close(); + } + } + }); + } + + + @Override + public T find(String tableName, final Scan scan, final AbstractRowKeyDistributor rowKeyDistributor, final ResultsExtractor action) { + + return execute(tableName, new TableCallback() { + @Override + public T doInTable(HTableInterface htable) throws Throwable { + final boolean debugEnabled = logger.isDebugEnabled(); + StopWatch watch = null; + if (debugEnabled) { + watch = new StopWatch(); + watch.start(); + } + final ResultScanner scanner = createDistributeScanner(htable, scan, rowKeyDistributor); + if (debugEnabled) { + logger.debug("DistributeScanner createTime:{}", watch.stop()); + } + if (debugEnabled) { + watch.start(); + } + try { + return action.extractData(scanner); + } finally { + scanner.close(); + if (debugEnabled) { + logger.debug("DistributeScanner scanTime:{}", watch.stop()); + } + } + } + }); + } + + public ResultScanner createDistributeScanner(HTableInterface htable, Scan originalScan, AbstractRowKeyDistributor rowKeyDistributor) throws IOException { + + Scan[] scans = rowKeyDistributor.getDistributedScans(originalScan); + final int length = scans.length; + for(int i = 0; i < length; i++) { + Scan scan = scans[i]; + scan.setId(originalScan.getId() + "-" + i); + // caching만 넣으면 되나? + scan.setCaching(originalScan.getCaching()); + } + + ResultScanner[] scanner = new ResultScanner[length]; + boolean success = false; + try { + for (int i = 0; i < length; i++) { + scanner[i] = htable.getScanner(scans[i]); + } + success = true; + } finally { + if (!success) { + closeScanner(scanner); + } + } + + return new DistributedScanner(rowKeyDistributor, scanner); + } + + private void closeScanner(ResultScanner[] scannerList ) { + for (ResultScanner scanner : scannerList) { + if (scanner != null) { + try { + scanner.close(); + } catch (Exception e) { + logger.warn("Scanner.close() error Caused:{}", e.getMessage(), e); + } + } + } + } + + public Result increment(String tableName, final Increment increment) { + return execute(tableName, new TableCallback() { + @Override + public Result doInTable(HTableInterface htable) throws Throwable { + return htable.increment(increment); + } + }); + } + + public List increment(final String tableName, final List incrementList) { + return execute(tableName, new TableCallback>() { + @Override + public List doInTable(HTableInterface htable) throws Throwable { + final List resultList = new ArrayList(incrementList.size()); + + Exception lastException = null; + for (Increment increment : incrementList) { + try { + Result result = htable.increment(increment); + resultList.add(result); + } catch (IOException e) { + logger.warn("{} increment error Caused:{}", tableName, e.getMessage(), e); + lastException = e; + } + } + if (lastException != null) { + throw lastException; + } + return resultList; + } + }); + } + + public long incrementColumnValue(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final long amount) { + return execute(tableName, new TableCallback() { + @Override + public Long doInTable(HTableInterface htable) throws Throwable { + return htable.incrementColumnValue(rowName, familyName, qualifier, amount); + } + }); + } + + public long incrementColumnValue(String tableName, final byte[] rowName, final byte[] familyName, final byte[] qualifier, final long amount, final boolean writeToWAL) { + return execute(tableName, new TableCallback() { + @Override + public Long doInTable(HTableInterface htable) throws Throwable { + return htable.incrementColumnValue(rowName, familyName, qualifier, amount, writeToWAL); + } + }); + } + + +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/LimitEventHandler.java b/src/main/java/com/nhn/pinpoint/common/hbase/LimitEventHandler.java new file mode 100644 index 000000000..cd95e4573 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/LimitEventHandler.java @@ -0,0 +1,10 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.hbase.client.Result; + +/** + * @author emeroad + */ +public interface LimitEventHandler { + void handleLastResult(Result lastResult); +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/LimitRowMapperResultsExtractor.java b/src/main/java/com/nhn/pinpoint/common/hbase/LimitRowMapperResultsExtractor.java new file mode 100644 index 000000000..df3f60ca1 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/LimitRowMapperResultsExtractor.java @@ -0,0 +1,84 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.springframework.data.hadoop.hbase.ResultsExtractor; +import org.springframework.data.hadoop.hbase.RowMapper; +import org.springframework.util.Assert; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * @author emeroad + */ +public class LimitRowMapperResultsExtractor implements ResultsExtractor> { + + private static final LimitEventHandler EMPTY = new EmptyLimitEventHandler(); + + private int limit = Integer.MAX_VALUE; + private final RowMapper rowMapper; + private LimitEventHandler eventHandler; + + public int getLimit() { + return limit; + } + + public void setLimit(int limit) { + this.limit = limit; + } + + /** + * Create a new RowMapperResultSetExtractor. + * + * @param rowMapper the RowMapper which creates an object for each row + */ + public LimitRowMapperResultsExtractor(RowMapper rowMapper, int limit) { + this(rowMapper, limit, EMPTY); + } + + /** + * Create a new RowMapperResultSetExtractor. + * + * @param rowMapper the RowMapper which creates an object for each row + */ + public LimitRowMapperResultsExtractor(RowMapper rowMapper, int limit, LimitEventHandler eventHandler) { + Assert.notNull(rowMapper, "RowMapper is required"); + Assert.notNull(eventHandler, "LimitEventHandler is required"); + this.rowMapper = rowMapper; + this.limit = limit; + this.eventHandler = eventHandler; + } + + public List extractData(ResultScanner results) throws Exception { + final List rs = new ArrayList(); + int rowNum = 0; + Result lastResult = null; + + for (Result result : results) { + final T t = this.rowMapper.mapRow(result, rowNum); + lastResult = result; + if (t instanceof Collection) { + rowNum += ((Collection) t).size(); + } else if (t instanceof Map) { + rowNum += ((Map) t).size(); + } else if (t == null) { + // empty + } else if (t.getClass().isArray()) { + rowNum += Array.getLength(t); + } else { + rowNum++; + } + rs.add(t); + if (rowNum >= limit) { + break; + } + } + + eventHandler.handleLastResult(lastResult); + return rs; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/PooledHTableFactory.java b/src/main/java/com/nhn/pinpoint/common/hbase/PooledHTableFactory.java new file mode 100644 index 000000000..dd3ab4f2c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/PooledHTableFactory.java @@ -0,0 +1,48 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.HTableInterface; +import org.apache.hadoop.hbase.client.HTableInterfaceFactory; +import org.apache.hadoop.hbase.client.HTablePool; +import org.springframework.beans.factory.DisposableBean; + +import java.io.IOException; + +/** + * HTablePool 기반의 HTableInterfaceFactory. + * @author emeroad + */ +public class PooledHTableFactory implements HTableInterfaceFactory, DisposableBean { + + private HTablePool hTablePool; + public static final int DEFAULT_POOL_SIZE = 256; + + public PooledHTableFactory(Configuration config) { + this.hTablePool = new HTablePool(config, DEFAULT_POOL_SIZE); + } + + public PooledHTableFactory(Configuration config, int poolSize) { + this.hTablePool = new HTablePool(config, poolSize); + } + + + @Override + public HTableInterface createHTableInterface(Configuration config, byte[] tableName) { + return hTablePool.getTable(tableName); + } + + @Override + public void releaseHTableInterface(HTableInterface table) throws IOException { + if (table != null) { + table.close(); + } + } + + + @Override + public void destroy() throws Exception { + if (hTablePool != null) { + this.hTablePool.close(); + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/RowMapperResultsExtractor.java b/src/main/java/com/nhn/pinpoint/common/hbase/RowMapperResultsExtractor.java new file mode 100644 index 000000000..960fc82b9 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/RowMapperResultsExtractor.java @@ -0,0 +1,41 @@ +package com.nhn.pinpoint.common.hbase; + +import org.apache.hadoop.hbase.client.Result; +import org.apache.hadoop.hbase.client.ResultScanner; +import org.springframework.data.hadoop.hbase.ResultsExtractor; +import org.springframework.data.hadoop.hbase.RowMapper; +import org.springframework.util.Assert; + +import java.util.ArrayList; +import java.util.List; + +/** + * Spring꺼가 package라서 그냥 복사해옴. + * copy->Spring + * Adapter encapsulating the RowMapper callback. + * + * @author Costin Leau + */ +class RowMapperResultsExtractor implements ResultsExtractor> { + + private final RowMapper rowMapper; + + /** + * Create a new RowMapperResultSetExtractor. + * + * @param rowMapper the RowMapper which creates an object for each row + */ + public RowMapperResultsExtractor(RowMapper rowMapper) { + Assert.notNull(rowMapper, "RowMapper is required"); + this.rowMapper = rowMapper; + } + + public List extractData(ResultScanner results) throws Exception { + List rs = new ArrayList(); + int rowNum = 0; + for (Result result : results) { + rs.add(this.rowMapper.mapRow(result, rowNum++)); + } + return rs; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/ValueMapper.java b/src/main/java/com/nhn/pinpoint/common/hbase/ValueMapper.java new file mode 100644 index 000000000..e41551d69 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/ValueMapper.java @@ -0,0 +1,8 @@ +package com.nhn.pinpoint.common.hbase; + +/** + * @author emeroad + */ +public interface ValueMapper { + byte[] mapValue(T value); +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/distributor/RangeOneByteSimpleHash.java b/src/main/java/com/nhn/pinpoint/common/hbase/distributor/RangeOneByteSimpleHash.java new file mode 100644 index 000000000..cf2b453b2 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/distributor/RangeOneByteSimpleHash.java @@ -0,0 +1,74 @@ +package com.nhn.pinpoint.common.hbase.distributor; + + +import com.nhn.pinpoint.common.util.MathUtils; +import com.sematext.hbase.wd.RowKeyDistributorByHashPrefix; + +import java.util.Arrays; + +/** + * @author emeroad + */ +public class RangeOneByteSimpleHash implements RowKeyDistributorByHashPrefix.Hasher { + private final int start; + private final int end; + private int mod; + + // Used to minimize # of created object instances + // Should not be changed. TODO: secure that + private static final byte[][] PREFIXES; + + static { + PREFIXES = new byte[256][]; + for (int i = 0; i < 256; i++) { + PREFIXES[i] = new byte[] {(byte) i}; + } + } + + + public RangeOneByteSimpleHash(int start, int end, int maxBuckets) { + if (maxBuckets < 1 || maxBuckets > 256) { + throw new IllegalArgumentException("maxBuckets should be in 1..256 range"); + } + this.start = start; + this.end = end; + // i.e. "real" maxBuckets value = maxBuckets or maxBuckets-1 + this.mod = maxBuckets; + } + + @Override + public byte[] getHashPrefix(byte[] originalKey) { + long hash = MathUtils.fastAbs(hashBytes(originalKey)); + return new byte[] {(byte) (hash % mod)}; + } + + /** Compute hash for binary data. */ + private int hashBytes(byte[] bytes) { + int min = Math.min(bytes.length, end); + int hash = 1; + for (int i = start; i < min; i++) + hash = (31 * hash) + (int) bytes[i]; + return hash; + } + + @Override + public byte[][] getAllPossiblePrefixes() { + return Arrays.copyOfRange(PREFIXES, 0, mod); + } + + @Override + public int getPrefixLength(byte[] adjustedKey) { + return 1; + } + + @Override + public String getParamsToStore() { + return String.valueOf(mod); + } + + @Override + public void init(String storedParams) { + this.mod = Integer.valueOf(storedParams); + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/hbase/filter/ApplicationTraceIndexResponseTimeFilter.java b/src/main/java/com/nhn/pinpoint/common/hbase/filter/ApplicationTraceIndexResponseTimeFilter.java new file mode 100644 index 000000000..798e75de7 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/hbase/filter/ApplicationTraceIndexResponseTimeFilter.java @@ -0,0 +1,73 @@ +package com.nhn.pinpoint.common.hbase.filter; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +import org.apache.hadoop.hbase.KeyValue; +import org.apache.hadoop.hbase.filter.FilterBase; +import org.apache.hadoop.hbase.util.Bytes; + +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.buffer.OffsetFixedBuffer; + +/** + * value filter보다 column name에 prefix 붙여 filter하는것이 나을 듯하여 일단 deprecated 처리 함. + * + * @author netspider + * + */ +@Deprecated +public class ApplicationTraceIndexResponseTimeFilter extends FilterBase { + + private byte[] value = null; + private boolean filterRow = true; + + private final int responseTimeFrom; + private final int responseTimeTo; + + public ApplicationTraceIndexResponseTimeFilter(int responseTimeFrom, int responseTimeTo) { + super(); + this.responseTimeFrom = responseTimeFrom; + this.responseTimeTo = responseTimeTo; + } + + @Override + public void reset() { + // 새로운 값을 비교할 때마다 플래그 재설정. + this.filterRow = true; + } + + @Override + public ReturnCode filterKeyValue(KeyValue kv) { + final byte[] buffer = kv.getBuffer(); + + final int valueOffset = kv.getValueOffset(); + final Buffer valueBuffer = new OffsetFixedBuffer(buffer, valueOffset); + int elapsed = valueBuffer.readVarInt(); + + if (elapsed < responseTimeFrom || elapsed > responseTimeTo) { + // 조건에 맞지 않으면 row를 통과 + filterRow = false; + } + + // 실제 결정은 나중에 하기 때문에 항상 이 값을 반환 + return ReturnCode.INCLUDE; + } + + @Override + public boolean filterRow() { + // 실제 결정은 플래그 상태에 따라 이곳에서 이루어진다. + return filterRow; + } + + @Override + public void readFields(DataInput dataInput) throws IOException { + this.value = Bytes.readByteArray(dataInput); + } + + @Override + public void write(DataOutput dataOutput) throws IOException { + Bytes.writeByteArray(dataOutput, this.value); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/AnnotationTranscoder.java b/src/main/java/com/nhn/pinpoint/common/util/AnnotationTranscoder.java new file mode 100644 index 000000000..94f61a4c2 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/AnnotationTranscoder.java @@ -0,0 +1,252 @@ +package com.nhn.pinpoint.common.util; + + +import com.nhn.pinpoint.common.bo.IntStringStringValue; +import com.nhn.pinpoint.common.bo.IntStringValue; +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.buffer.FixedBuffer; +import com.nhn.pinpoint.thrift.dto.TAnnotation; +import com.nhn.pinpoint.thrift.dto.TAnnotationValue; +import com.nhn.pinpoint.thrift.dto.TIntStringStringValue; +import com.nhn.pinpoint.thrift.dto.TIntStringValue; + +/** + * @author emeroad + */ +public class AnnotationTranscoder { + + static final byte CODE_STRING = 0; + static final byte CODE_NULL = 1; + static final byte CODE_INT = 2; + static final byte CODE_LONG = 3; + + static final byte CODE_BOOLEAN_TRUE = 4; + static final byte CODE_BOOLEAN_FALSE = 5; + + static final byte CODE_BYTEARRAY = 6; + static final byte CODE_BYTE = 7; + + static final byte CODE_SHORT = 8; + static final byte CODE_FLOAT = 9; + static final byte CODE_DOUBLE = 10; + static final byte CODE_TOSTRING = 11; + // multivalue + static final byte CODE_INT_STRING = 20; + static final byte CODE_INT_STRING_STRING = 21; + + + public Object getMappingValue(TAnnotation annotation) { + final TAnnotationValue value = annotation.getValue(); + if (value == null) { + return null; + } + return value.getFieldValue(); + } + + + public Object decode(final byte dataType, final byte[] data) { + switch (dataType) { + case CODE_STRING: + return decodeString(data); + case CODE_BOOLEAN_TRUE: + return Boolean.TRUE; + case CODE_BOOLEAN_FALSE: + return Boolean.FALSE; + case CODE_INT: { + final Buffer buffer = new FixedBuffer(data); + return buffer.readSVarInt(); + } + case CODE_LONG: { + final Buffer buffer = new FixedBuffer(data); + return buffer.readSVarLong(); + } + case CODE_BYTE: + return data[0]; + case CODE_SHORT: + final Buffer buffer = new FixedBuffer(data); + return (short)buffer.readSVarInt(); + case CODE_FLOAT: + return Float.intBitsToFloat(BytesUtils.bytesToInt(data, 0)); + case CODE_DOUBLE: + return Double.longBitsToDouble(BytesUtils.bytesToLong(data, 0)); + case CODE_BYTEARRAY: + return data; + case CODE_NULL: + return null; + case CODE_TOSTRING: + return decodeString(data); + case CODE_INT_STRING: + return decodeIntStringValue(data); + case CODE_INT_STRING_STRING: + return decodeIntStringStringValue(data); + } + throw new IllegalArgumentException("unsupported DataType:" + dataType); + } + + public byte getTypeCode(Object o) { + if (o == null) { + return CODE_NULL; + } + if (o instanceof String) { + return CODE_STRING; + } else if (o instanceof Long) { + return CODE_LONG; + } else if (o instanceof Integer) { + return CODE_INT; + } else if (o instanceof Boolean) { + if (Boolean.TRUE.equals(o)) { + return CODE_BOOLEAN_TRUE; + } + return CODE_BOOLEAN_FALSE; + } else if (o instanceof Byte) { + return CODE_BYTE; + } else if (o instanceof Short) { + return CODE_SHORT; + } else if (o instanceof Float) { + // thrift에서 지원안함. + return CODE_FLOAT; + } else if (o instanceof Double) { + return CODE_DOUBLE; + } else if (o instanceof byte[]) { + return CODE_BYTEARRAY; + } else if(o instanceof TIntStringValue) { + return CODE_INT_STRING; + } else if(o instanceof TIntStringStringValue) { + return CODE_INT_STRING_STRING; + } + return CODE_TOSTRING; + } + + public byte[] encode(Object o, int typeCode) { + switch (typeCode) { + case CODE_STRING: + return encodeString((String) o); + case CODE_INT: { + final Buffer buffer = new FixedBuffer(BytesUtils.VINT_MAX_SIZE); + buffer.putSVar((Integer)o); + return buffer.getBuffer(); + } + case CODE_BOOLEAN_TRUE: { + return new byte[0]; + } + case CODE_BOOLEAN_FALSE: { + return new byte[0]; + } + case CODE_LONG: { + final Buffer buffer = new FixedBuffer(BytesUtils.VLONG_MAX_SIZE); + buffer.putSVar((Long)o); + return buffer.getBuffer(); + } + case CODE_BYTE: { + final byte[] bytes = new byte[1]; + bytes[0] = (Byte)o; + return bytes; + } + case CODE_SHORT: { + final Buffer buffer = new FixedBuffer(BytesUtils.VINT_MAX_SIZE); + buffer.putSVar((Short) o); + return buffer.getBuffer(); + } + case CODE_FLOAT: { + final byte[] buffer = new byte[4]; + BytesUtils.writeInt(Float.floatToRawIntBits((Float) o), buffer, 0); + return buffer; + } + case CODE_DOUBLE: { + final byte[] buffer = new byte[8]; + BytesUtils.writeLong(Double.doubleToRawLongBits((Double) o), buffer, 0); + return buffer; + } + case CODE_BYTEARRAY: + return (byte[]) o; + case CODE_NULL: + return null; + case CODE_TOSTRING: + final String str = o.toString(); + return encodeString(str); + case CODE_INT_STRING: + return encodeIntStringValue(o); + case CODE_INT_STRING_STRING: + return encodeIntStringStringValue(o); + } + throw new IllegalArgumentException("unsupported DataType:" + typeCode + " data:" + o); + } + + + private Object decodeIntStringValue(byte[] data) { + final Buffer buffer = new FixedBuffer(data); + final int intValue = buffer.readSVarInt(); + final String stringValue = BytesUtils.toString(buffer.readPrefixedBytes()); + return new IntStringValue(intValue, stringValue); + } + + private byte[] encodeIntStringValue(Object value) { + final TIntStringValue tIntStringValue = (TIntStringValue) value; + final int intValue = tIntStringValue.getIntValue(); + final byte[] stringValue = BytesUtils.toBytes(tIntStringValue.getStringValue()); + // 대충 크기 더함. 나중에 좀더 정교하게 계산하자. + final int bufferSize = getBufferSize(stringValue, 4 + 8); + final Buffer buffer = new AutomaticBuffer(bufferSize); + buffer.putSVar(intValue); + buffer.putPrefixedBytes(stringValue); + return buffer.getBuffer(); + } + + private int getBufferSize(byte[] stringValue, int reserve) { + if (stringValue == null) { + return reserve; + } else { + return stringValue.length + reserve; + } + } + + private Object decodeIntStringStringValue(byte[] data) { + final Buffer buffer = new FixedBuffer(data); + final int intValue = buffer.readSVarInt(); + final String stringValue1 = BytesUtils.toString(buffer.readPrefixedBytes()); + final String stringValue2 = BytesUtils.toString(buffer.readPrefixedBytes()); + return new IntStringStringValue(intValue, stringValue1, stringValue2); + } + + private byte[] encodeIntStringStringValue(Object o) { + final TIntStringStringValue tIntStringStringValue = (TIntStringStringValue) o; + final int intValue = tIntStringStringValue.getIntValue(); + final byte[] stringValue1 = BytesUtils.toBytes(tIntStringStringValue.getStringValue1()); + final byte[] stringValue2 = BytesUtils.toBytes(tIntStringStringValue.getStringValue2()); + // 대충 크기 더함. 나중에 좀더 정교하게 계산하자. + final int bufferSize = getBufferSize(stringValue1, stringValue2, 4 + 8); + final Buffer buffer = new AutomaticBuffer(bufferSize); + buffer.putSVar(intValue); + buffer.putPrefixedBytes(stringValue1); + buffer.putPrefixedBytes(stringValue2); + return buffer.getBuffer(); + } + + private int getBufferSize(byte[] stringValue1, byte[] stringValue2, int reserve) { + int length = 0; + if (stringValue1 != null) { + length += stringValue1.length; + } + if (stringValue2 != null) { + length += stringValue2.length; + + } + return length + reserve; + } + + + /** + * Decode the string with the current character set. + */ + protected String decodeString(byte[] data) { + return BytesUtils.toString(data); + } + + /** + * Encode a string into the current character set. + */ + protected byte[] encodeString(String in) { + return BytesUtils.toBytes(in); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/AnnotationUtils.java b/src/main/java/com/nhn/pinpoint/common/util/AnnotationUtils.java new file mode 100644 index 000000000..eb2295c5a --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/AnnotationUtils.java @@ -0,0 +1,125 @@ +package com.nhn.pinpoint.common.util; + +import java.util.*; + +import com.nhn.pinpoint.common.AnnotationKey; +import com.nhn.pinpoint.common.ServiceType; +import com.nhn.pinpoint.common.bo.AnnotationBo; +import com.nhn.pinpoint.common.bo.Span; + +/** + * @author emeroad + */ +public class AnnotationUtils { + + public static String findApiAnnotation(List list) { + if (list == null) { + return null; + } + AnnotationBo annotationBo = findAnnotationBo(list, AnnotationKey.API); + if (annotationBo != null) { + return (String) annotationBo.getValue(); + } + return null; + } + + public static AnnotationBo findAnnotationBo(List annotationBoList, AnnotationKey annotationKey) { + for (AnnotationBo annotation : annotationBoList) { + int key = annotation.getKey(); + if (annotationKey.getCode() == key) { + return annotation; + } + } + return null; + } + + public static AnnotationBo findArgsAnnotationBo(List annotationBoList) { + for (AnnotationBo annotation : annotationBoList) { + if (AnnotationKey.isArgsKey(annotation.getKey())) { + return annotation; + } + } + return null; + } + + public static AnnotationBo getDisplayArgument(Span span) { + // arcus 관련 일반화 필요. + List list = span.getAnnotationBoList(); + if (list == null) { + return null; + } + final ServiceType serviceType = span.getServiceType(); + if (serviceType == ServiceType.ARCUS || serviceType == ServiceType.MEMCACHED) { + // 첫번째 args아무거나 하나를 디스플레이에 뿌린다. + // TODO 2개 이상일 경우의 케이스 일때 비기는 하나, 현재 arucs쪽 파라미터 덤프키는 일단 1개뿐이라 괜찮을듯하다. + return findArgsAnnotationBo(list); + } + + // rpc connector의 경우 보여주는 code일반화 필요. + if (serviceType == ServiceType.HTTP_CLIENT || serviceType == ServiceType.JDK_HTTPURLCONNECTOR) { + return findAnnotationBo(list, AnnotationKey.HTTP_URL); + } + + +// span에 해당하는 Tomcat의 경우 Span에 포함된 rpc 필드를 사용하므로 annotation에서 찾을필요가 없음. +// if (span.getServiceType() == ServiceType.TOMCAT) { +// return findAnnotationBo(list, AnnotationKey.HTTP_URL); +// } +// + // TODO 먼가 고쳐야 함. + if (serviceType == ServiceType.MYSQL || serviceType == ServiceType.MYSQL_EXECUTE_QUERY + || serviceType == ServiceType.ORACLE || serviceType == ServiceType.ORACLE_EXECUTE_QUERY + || serviceType == ServiceType.MSSQL || serviceType == ServiceType.MSSQL_EXECUTE_QUERY + || serviceType == ServiceType.CUBRID || serviceType == ServiceType.CUBRID_EXECUTE_QUERY) { + // args 0의 경우 연결string이다 + // 구현 방법이 매우 구림 좀더 개선 필요. + return findAnnotationBo(list, AnnotationKey.ARGS0); + } + + if (serviceType == ServiceType.IBATIS || serviceType == ServiceType.MYBATIS) { + return findAnnotationBo(list, AnnotationKey.ARGS0); + } + + if (serviceType == ServiceType.SPRING_ORM_IBATIS) { + return findAnnotationBo(list, AnnotationKey.ARGS0); + } + + return null; + } + + private static List API_META_DATA_ERROR; + static { + API_META_DATA_ERROR = loadApiMetaDataError(); + } + + static List loadApiMetaDataError() { + List apiMetaData = new ArrayList(); + for (AnnotationKey annotationKey : AnnotationKey.values()) { + if (annotationKey.name().startsWith("ERROR_API_METADATA_")) { + apiMetaData.add(annotationKey); + } + } + return apiMetaData; + } + + public static AnnotationKey getApiMetaDataError(List annotationBoList) { + for (AnnotationBo bo : annotationBoList) { + AnnotationKey apiErrorCode = findApiErrorCode(bo); + if (apiErrorCode != null) { + return apiErrorCode; + } + } + // 정확한 에러 코드를 못찾음. 퉁쳐서 에러 처리 + return AnnotationKey.ERROR_API_METADATA_ERROR; + } + + private static AnnotationKey findApiErrorCode(AnnotationBo bo) { + for (AnnotationKey annotationKey : API_META_DATA_ERROR) { + if (bo.getKey() == annotationKey.getCode()) { + return annotationKey; + } + } + return null; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/ApiDescription.java b/src/main/java/com/nhn/pinpoint/common/util/ApiDescription.java new file mode 100644 index 000000000..3e84fa32c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/ApiDescription.java @@ -0,0 +1,80 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public class ApiDescription { + + private String className; + + private String methodName; + + private String[] simpleParameter; + + private int line = -1; + + public void setClassName(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } + + public String getSimpleClassName() { + int classNameStartIndex = className.lastIndexOf('.') + 1; + return className.substring(classNameStartIndex, className.length()); + } + + public String getPackageNameName() { + int packageNameIndex = className.lastIndexOf('.'); + if (packageNameIndex == -1) { + return ""; + } + return className.substring(0, packageNameIndex); + } + + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getMethodName() { + return this.methodName; + } + + public void setSimpleParameter(String[] simpleParameter) { + this.simpleParameter = simpleParameter; + } + + public String[] getSimpleParameter() { + return simpleParameter; + } + + public void setLine(int line) { + this.line = line; + } + + public String getSimpleMethodDescription() { + String simpleParameterDescription = concateLine(simpleParameter, ", "); + return methodName + simpleParameterDescription; + } + + public String concateLine(String[] stringList, String separator) { + if (stringList == null || stringList.length == 0) { + return "()"; + } + + StringBuilder sb = new StringBuilder(); + if (stringList.length > 0) { + sb.append('('); + sb.append(stringList[0]); + for (int i = 1; i < stringList.length; i++) { + sb.append(separator); + sb.append(stringList[i]); + } + sb.append(')'); + } + return sb.toString(); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/ApiDescriptionParser.java b/src/main/java/com/nhn/pinpoint/common/util/ApiDescriptionParser.java new file mode 100644 index 000000000..9da123105 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/ApiDescriptionParser.java @@ -0,0 +1,109 @@ +package com.nhn.pinpoint.common.util; + +import org.slf4j.LoggerFactory; + +import java.util.regex.Pattern; + +/** + * MethodDescriptor 과 비슷한데. 문자열을 기반으로 parsing하여 생성하므로 따로 만들었음. + * @author emeroad + */ +public class ApiDescriptionParser { + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final char DOT = '.'; + private static final char METHOD_PARAM_START = '('; + private static final char METHOD_PARAM_END = ')'; + private static final char PARAMETER_SP = ','; + private static Pattern PARAMETER_REGEX = Pattern.compile(", |,"); + // org.springframework.web.servlet.FrameworkServlet.doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) +// com.mysql.jdbc.ConnectionImpl.setAutoCommit(boolean autoCommitFlag) +// com.mysql.jdbc.ConnectionImpl.commit() + + // org.apache.catalina.core.StandardHostValve.invoke(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response):110 + public ApiDescription parse(String apiDescriptionString) { + if (apiDescriptionString == null) { + throw new NullPointerException("apiDescriptionString must not be null"); + } + + final int methodStart = apiDescriptionString.lastIndexOf(METHOD_PARAM_START); + if (methodStart == -1) { + throw new IllegalArgumentException("'(' not found. invalid apiDescriptionString:" + apiDescriptionString); + } + + final int methodEnd = apiDescriptionString.lastIndexOf(METHOD_PARAM_END); + if (methodEnd == -1) { + throw new IllegalArgumentException("')' not found. invalid apiDescriptionString:" + apiDescriptionString); + } + + final int classIndex = apiDescriptionString.lastIndexOf(DOT, methodStart); + if (classIndex == -1) { + throw new IllegalArgumentException("'.' not found. invalid apiDescriptionString:" + apiDescriptionString); + } + + String className = parseClassName(apiDescriptionString, classIndex); + ApiDescription api = new ApiDescription(); + api.setClassName(className); + + String methodName = parseMethodName(apiDescriptionString, methodStart, classIndex); + api.setMethodName(methodName); + + String parameterDescriptor = apiDescriptionString.substring(methodStart + 1, methodEnd); + String[] parameterList = parseParameter(parameterDescriptor); + String[] simpleParameterList = parseSimpleParameter(parameterList); + api.setSimpleParameter(simpleParameterList); + + int lineIndex = apiDescriptionString.lastIndexOf(':'); + // 일단 땜방으로 lineNumber체크해서 lineNumber를 뿌려주도록 하자. + if (lineIndex != -1) { + try { + int line = Integer.parseInt(apiDescriptionString.substring(lineIndex + 1, apiDescriptionString.length())); + api.setLine(line); + } catch (NumberFormatException e) { + LoggerFactory.getLogger(this.getClass()).warn("line number parse error {}", e); + } + } + + return api; + } + + private String[] parseSimpleParameter(String[] parameterList) { + if (parameterList == null || parameterList.length == 0) { + return EMPTY_STRING_ARRAY; + } + String[] simple = new String[parameterList.length]; + for (int i = 0; i < parameterList.length; i++) { + simple[i] = simepleParameter(parameterList[i]); + } + return simple; + } + + private String simepleParameter(String parameter) { + int packageIndex = parameter.lastIndexOf(DOT); + if (packageIndex == -1) { + // 없을 경우 아래 로직가 동일하나 추후 뭔가 변경사항이 생길수 있어 명시적으로 체크하는 로직으로 구현. + packageIndex = 0; + } else { + packageIndex += 1; + } + + + return parameter.substring(packageIndex, parameter.length()); + } + + private String[] parseParameter(String parameterDescriptor) { + if (parameterDescriptor == null || parameterDescriptor.length() == 0) { + return EMPTY_STRING_ARRAY; + } + return PARAMETER_REGEX.split(parameterDescriptor); + + } + + private String parseClassName(String apiDescriptionString, int classIndex) { + return apiDescriptionString.substring(0, classIndex); + } + + private String parseMethodName(String apiDescriptionString, int methodStart, int classIndex) { + return apiDescriptionString.substring(classIndex + 1, methodStart); + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/ApplicationMapStatisticsUtils.java b/src/main/java/com/nhn/pinpoint/common/util/ApplicationMapStatisticsUtils.java new file mode 100644 index 000000000..7e3f48147 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/ApplicationMapStatisticsUtils.java @@ -0,0 +1,151 @@ +package com.nhn.pinpoint.common.util; + +import com.nhn.pinpoint.common.HistogramSchema; +import com.nhn.pinpoint.common.HistogramSlot; +import com.nhn.pinpoint.common.ServiceType; +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.hbase.HBaseTables; +import org.apache.hadoop.hbase.util.Bytes; + + +/** + *
+ * columnName format = SERVICETYPE(2bytes) + SLOT(2bytes) + APPNAMELEN(2bytes) + APPLICATIONNAME(str) + HOST(str)
+ * 
+ * + * @author netspider + * @author emeroad + */ +public class ApplicationMapStatisticsUtils { + + public static byte[] makeColumnName(short serviceType, String applicationName, String destHost, short slotNumber) { + if (applicationName == null) { + throw new NullPointerException("applicationName must not be null"); + } + if (destHost == null) { + // throw new NullPointerException("destHost must not be null"); + destHost = ""; + } + byte[] serviceTypeBytes = Bytes.toBytes(serviceType); + byte[] slotNumberBytes = Bytes.toBytes(slotNumber); + byte[] applicationNameBytes = Bytes.toBytes(applicationName); + byte[] applicationNameLenBytes = Bytes.toBytes((short) applicationNameBytes.length); + byte[] destHostBytes = Bytes.toBytes(destHost); + + return BytesUtils.concat(serviceTypeBytes, slotNumberBytes, applicationNameLenBytes, applicationNameBytes, destHostBytes); + } + + public static short getSlotNumber(short serviceType, int elapsed, boolean isError) { + if (isError) { + return HBaseTables.STATISTICS_CQ_ERROR_SLOT_NUMBER; + } else { + return findResponseHistogramSlotNo(serviceType, elapsed); + } + } + + + public static byte[] makeColumnName(String agentId, short columnSlotNumber) { + if (agentId == null) { + agentId = ""; + } + final byte[] slotNumber = Bytes.toBytes(columnSlotNumber); + final byte[] agentIdBytes = Bytes.toBytes(agentId); + + return BytesUtils.concat(slotNumber, agentIdBytes); + } + + + private static short findResponseHistogramSlotNo(short serviceType, int elapsed) { + final HistogramSchema histogramSchema = ServiceType.findServiceType(serviceType).getHistogramSchema(); + final HistogramSlot histogramSlot = histogramSchema.findHistogramSlot(elapsed); + return histogramSlot.getSlotTime(); + } + + public static short getDestServiceTypeFromColumnName(byte[] bytes) { + return BytesUtils.bytesToShort(bytes, 0); + } + + /** + * @param bytes + * @return
+     *         0 > : ms
+     *         0 : slow
+     *         -1 : error
+     *         
+ */ + public static short getHistogramSlotFromColumnName(byte[] bytes) { + return BytesUtils.bytesToShort(bytes, 2); + } + + public static String getDestApplicationNameFromColumnName(byte[] bytes) { + final short length = BytesUtils.bytesToShort(bytes, 4); + return BytesUtils.toStringAndRightTrim(bytes, 6, length); + } + + public static String getHost(byte[] bytes) { + int offset = 6 + BytesUtils.bytesToShort(bytes, 4); + + if (offset == bytes.length) { + return null; + } + return BytesUtils.toStringAndRightTrim(bytes, offset, bytes.length - offset); + } + + /** + *
+     * rowkey format = "APPLICATIONNAME(max 24bytes)" + apptype(2byte) + "TIMESTAMP(8byte)"
+     * 
+ * + * @param applicationName + * @param timestamp + * @return + */ + public static byte[] makeRowKey(String applicationName, short applicationType, long timestamp) { + if (applicationName == null) { + throw new NullPointerException("applicationName must not be null"); + } + final byte[] applicationNameBytes= BytesUtils.toBytes(applicationName); + + final Buffer buffer = new AutomaticBuffer(2 + applicationNameBytes.length + 2 + 8); +// buffer.put2PrefixedString(applicationName); + buffer.put((short)applicationNameBytes.length); + buffer.put(applicationNameBytes); + buffer.put(applicationType); + long reverseTimeMillis = TimeUtils.reverseTimeMillis(timestamp); + buffer.put(reverseTimeMillis); + return buffer.getBuffer(); + } + + public static String getApplicationNameFromRowKey(byte[] bytes, int offset) { + if (bytes == null) { + throw new NullPointerException("bytes must not be null"); + } + short applicationNameLength = BytesUtils.bytesToShort(bytes, offset); + return BytesUtils.toString(bytes, offset + 2, applicationNameLength); //.trim(); + } + + public static String getApplicationNameFromRowKey(byte[] bytes) { + return getApplicationNameFromRowKey(bytes, 0); + } + + public static short getApplicationTypeFromRowKey(byte[] bytes) { + return getApplicationTypeFromRowKey(bytes, 0); + } + + public static short getApplicationTypeFromRowKey(byte[] bytes, int offset) { + if (bytes == null) { + throw new NullPointerException("bytes must not be null"); + } + short applicationNameLength = BytesUtils.bytesToShort(bytes, offset); + return BytesUtils.bytesToShort(bytes, offset + applicationNameLength + 2); + } + + public static long getTimestampFromRowKey(byte[] bytes) { + if (bytes == null) { + throw new NullPointerException("bytes must not be null"); + } + short applicationNameLength = BytesUtils.bytesToShort(bytes, 0); + return TimeUtils.recoveryTimeMillis(BytesUtils.bytesToLong(bytes, applicationNameLength + 4)); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/BytesUtils.java b/src/main/java/com/nhn/pinpoint/common/util/BytesUtils.java new file mode 100644 index 000000000..e2b0f986f --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/BytesUtils.java @@ -0,0 +1,530 @@ +package com.nhn.pinpoint.common.util; + + +import java.io.UnsupportedEncodingException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author emeroad + */ +public final class BytesUtils { + public static final int SHORT_BYTE_LENGTH = 2; + public static final int INT_BYTE_LENGTH = 4; + public static final int LONG_BYTE_LENGTH = 8; + public static final int LONG_LONG_BYTE_LENGTH = 16; + + public static final int VLONG_MAX_SIZE = 10; + public static final int VINT_MAX_SIZE = 5; + + private static final byte[] EMPTY_BYTES = new byte[0]; + private static final String UTF8 = "UTF-8"; + private static final Logger LOGGER = Logger.getLogger(BytesUtils.class.getName()); + + @Deprecated + public static byte[] longLongToBytes(final long value1, final long value2) { + final byte[] buffer = new byte[LONG_LONG_BYTE_LENGTH]; + writeFirstLong0(value1, buffer); + writeSecondLong0(value2, buffer); + return buffer; + } + + public static byte[] stringLongLongToBytes(final String string, final int maxStringSize, final long value1, final long value2) { + if (string == null) { + throw new NullPointerException("string must not be null"); + } + if (maxStringSize < 0) { + throw new IllegalArgumentException("maxStringSize"); + } + final byte[] stringBytes = toBytes(string); + if (stringBytes.length > maxStringSize) { + throw new IllegalArgumentException("string is max " + stringBytes.length + ", string='" + string + "'"); + } + final byte[] buffer = new byte[LONG_LONG_BYTE_LENGTH + maxStringSize]; + writeBytes(buffer, 0, stringBytes); + writeFirstLong0(value1, buffer, maxStringSize); + writeSecondLong0(value2, buffer, maxStringSize); + return buffer; + } + + public static void writeBytes(final byte[] buffer, int offset, final byte[] stringBytes) { + if (buffer == null) { + throw new NullPointerException("buffer must not be null"); + } + if (stringBytes == null) { + throw new NullPointerException("stringBytes must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + System.arraycopy(stringBytes, 0, buffer, offset, stringBytes.length); + } + + @Deprecated + public static long[] bytesToLongLong(final byte[] buf) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (buf.length < LONG_LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("Illegal buf size."); + } + final long[] result = new long[2]; + + result[0] = bytesToFirstLong0(buf); + result[1] = bytesToSecondLong0(buf); + + return result; + } + + public static long bytesToLong(final byte[] buf, final int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (buf.length < offset + LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small. buf.length:" + buf.length + " offset:" + (offset + 8)); + } + + final long rv = (((long) buf[offset] & 0xff) << 56) + | (((long) buf[offset + 1] & 0xff) << 48) + | (((long) buf[offset + 2] & 0xff) << 40) + | (((long) buf[offset + 3] & 0xff) << 32) + | (((long) buf[offset + 4] & 0xff) << 24) + | (((long) buf[offset + 5] & 0xff) << 16) + | (((long) buf[offset + 6] & 0xff) << 8) + | (((long) buf[offset + 7] & 0xff)); + return rv; + } + + public static int bytesToInt(final byte[] buf, final int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (buf.length < offset + INT_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small. buf.length:" + buf.length + " offset:" + (offset + 4)); + } + + final int v = ((buf[offset] & 0xff) << 24) + | ((buf[offset + 1] & 0xff) << 16) + | ((buf[offset + 2] & 0xff) << 8) + | ((buf[offset + 3] & 0xff)); + + return v; + } + + public static short bytesToShort(final byte[] buf, final int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (buf.length < offset + SHORT_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small. buf.length:" + buf.length + " offset:" + (offset + 2)); + } + + final short v = (short) (((buf[offset] & 0xff) << 8) | ((buf[offset + 1] & 0xff))); + + return v; + } + + public static short bytesToShort(final byte byte1, final byte byte2) { + return (short) (((byte1 & 0xff) << 8) | ((byte2 & 0xff))); + } + + public static long bytesToFirstLong(final byte[] buf) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (buf.length < LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small(8). buf.length:" + buf.length); + } + + return bytesToFirstLong0(buf); + } + + private static long bytesToFirstLong0(byte[] buf) { + final long rv = (((long) buf[0] & 0xff) << 56) + | (((long) buf[1] & 0xff) << 48) + | (((long) buf[2] & 0xff) << 40) + | (((long) buf[3] & 0xff) << 32) + | (((long) buf[4] & 0xff) << 24) + | (((long) buf[5] & 0xff) << 16) + | (((long) buf[6] & 0xff) << 8) + | (((long) buf[7] & 0xff)); + return rv; + } + + public static long bytesToSecondLong(final byte[] buf) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (buf.length < LONG_LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small(16). buf.length:" + buf.length); + } + + return bytesToSecondLong0(buf); + } + + private static long bytesToSecondLong0(final byte[] buf) { + final long rv = (((long) buf[8] & 0xff) << 56) + | (((long) buf[9] & 0xff) << 48) + | (((long) buf[10] & 0xff) << 40) + | (((long) buf[11] & 0xff) << 32) + | (((long) buf[12] & 0xff) << 24) + | (((long) buf[13] & 0xff) << 16) + | (((long) buf[14] & 0xff) << 8) + | (((long) buf[15] & 0xff)); + return rv; + } + + public static int writeLong(final long value, final byte[] buf, int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (buf.length < offset + LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small. buf.length:" + buf.length + " offset:" + (offset + 8)); + } + buf[offset++] = (byte) (value >> 56); + buf[offset++] = (byte) (value >> 48); + buf[offset++] = (byte) (value >> 40); + buf[offset++] = (byte) (value >> 32); + buf[offset++] = (byte) (value >> 24); + buf[offset++] = (byte) (value >> 16); + buf[offset++] = (byte) (value >> 8); + buf[offset++] = (byte) (value); + return offset; + } + + public static byte writeShort1(final short value) { + return (byte) (value >> 8); + } + + public static byte writeShort2(final short value) { + return (byte) (value); + } + + public static int writeShort(final short value, final byte[] buf, int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (buf.length < offset + SHORT_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small. buf.length:" + buf.length + " offset:" + (offset + 2)); + } + buf[offset++] = (byte) (value >> 8); + buf[offset++] = (byte) (value); + return offset; + } + + public static int writeInt(final int value, final byte[] buf, int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (buf.length < offset + INT_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small. buf.length:" + buf.length + " offset:" + (offset + 4)); + } + buf[offset++] = (byte) (value >> 24); + buf[offset++] = (byte) (value >> 16); + buf[offset++] = (byte) (value >> 8); + buf[offset++] = (byte) (value); + return offset; + } + + public static int writeSVar32(final int value, final byte[] buf, final int offset) { + return writeVar32(intToZigZag(value), buf, offset); + } + + public static int writeVar32(int value, final byte[] buf, int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + while (true) { + if ((value & ~0x7F) == 0) { + buf[offset++] = (byte)value; + return offset; + } else { + buf[offset++] = (byte)((value & 0x7F) | 0x80); + value >>>= 7; + } + } + } + + public static int writeVar64(long value, final byte[] buf, int offset) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + while (true) { + if ((value & ~0x7FL) == 0) { + buf[offset++] = (byte)value; + return offset; + } else { + buf[offset++] = (byte)(((int)value & 0x7F) | 0x80); + value >>>= 7; + } + } + } + + @Deprecated + public static void writeFirstLong(final long value, final byte[] buf) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (buf.length < LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small(8). buf.length:" + buf.length); + } + writeFirstLong0(value, buf); + } + + private static void writeFirstLong0(final long value, final byte[] buf) { + buf[0] = (byte) (value >> 56); + buf[1] = (byte) (value >> 48); + buf[2] = (byte) (value >> 40); + buf[3] = (byte) (value >> 32); + buf[4] = (byte) (value >> 24); + buf[5] = (byte) (value >> 16); + buf[6] = (byte) (value >> 8); + buf[7] = (byte) (value); + } + + private static void writeFirstLong0(final long value, final byte[] buf, int offset) { + buf[0 + offset] = (byte) (value >> 56); + buf[1 + offset] = (byte) (value >> 48); + buf[2 + offset] = (byte) (value >> 40); + buf[3 + offset] = (byte) (value >> 32); + buf[4 + offset] = (byte) (value >> 24); + buf[5 + offset] = (byte) (value >> 16); + buf[6 + offset] = (byte) (value >> 8); + buf[7 + offset] = (byte) (value); + } + + @Deprecated + public static void writeSecondLong(final long value, final byte[] buf) { + if (buf == null) { + throw new NullPointerException("buf must not be null"); + } + if (buf.length < LONG_LONG_BYTE_LENGTH) { + throw new IllegalArgumentException("buf.length is too small(16). buf.length:" + buf.length); + } + writeSecondLong0(value, buf); + } + + + private static Logger getLogger() { + return Logger.getLogger(BytesUtils.class.getName()); + } + + private static void writeSecondLong0(final long value, final byte[] buf) { + buf[8] = (byte) (value >> 56); + buf[9] = (byte) (value >> 48); + buf[10] = (byte) (value >> 40); + buf[11] = (byte) (value >> 32); + buf[12] = (byte) (value >> 24); + buf[13] = (byte) (value >> 16); + buf[14] = (byte) (value >> 8); + buf[15] = (byte) (value); + } + + private static void writeSecondLong0(final long value, final byte[] buf, int offset) { + buf[8 + offset] = (byte) (value >> 56); + buf[9 + offset] = (byte) (value >> 48); + buf[10 + offset] = (byte) (value >> 40); + buf[11 + offset] = (byte) (value >> 32); + buf[12 + offset] = (byte) (value >> 24); + buf[13 + offset] = (byte) (value >> 16); + buf[14 + offset] = (byte) (value >> 8); + buf[15 + offset] = (byte) (value); + } + + public static byte[] add(final String prefix, final long postfix) { + if (prefix == null) { + throw new NullPointerException("prefix must not be null"); + } + byte[] agentByte = toBytes(prefix); + return add(agentByte, postfix); + } + + public static byte[] add(final byte[] preFix, final long postfix) { + byte[] buf = new byte[preFix.length + LONG_BYTE_LENGTH]; + System.arraycopy(preFix, 0, buf, 0, preFix.length); + writeLong(postfix, buf, preFix.length); + return buf; + } + + public static byte[] add(final byte[] preFix, final short postfix) { + byte[] buf = new byte[preFix.length + SHORT_BYTE_LENGTH]; + System.arraycopy(preFix, 0, buf, 0, preFix.length); + writeShort(postfix, buf, preFix.length); + return buf; + } + + public static byte[] add(final int preFix, final short postFix) { + byte[] buf = new byte[INT_BYTE_LENGTH + SHORT_BYTE_LENGTH]; + writeInt(preFix, buf, 0); + writeShort(postFix, buf, 4); + return buf; + } + + + public static byte[] add(final long preFix, final short postFix) { + byte[] buf = new byte[LONG_BYTE_LENGTH + SHORT_BYTE_LENGTH]; + writeLong(preFix, buf, 0); + writeShort(postFix, buf, 8); + return buf; + } + + public static byte[] toBytes(final String value) { + if (value == null) { + return null; + } + try { + return value.getBytes(UTF8); + } catch (UnsupportedEncodingException e) { + final Logger logger = getLogger(); + logger.log(Level.SEVERE, "String encoding fail. value:" + value + " Caused:" + e.getMessage(), e); + return EMPTY_BYTES; + } + } + + public static byte[] merge(final byte[] b1, final byte[] b2) { + if (b1 == null) { + throw new NullPointerException("b1 must not be null"); + } + if (b2 == null) { + throw new NullPointerException("b2 must not be null"); + } + final byte[] result = new byte[b1.length + b2.length]; + + System.arraycopy(b1, 0, result, 0, b1.length); + System.arraycopy(b2, 0, result, b1.length, b2.length); + + return result; + } + + public static byte[] toFixedLengthBytes(final String str, final int length) { + if (length < 0) { + throw new IllegalArgumentException("negative length:" + length); + } + final byte[] b1 = toBytes(str); + if (b1 == null) { + return new byte[length]; + } + + if (b1.length > length) { + throw new IllegalArgumentException("String is longer then target length of bytes."); + } + byte[] b = new byte[length]; + System.arraycopy(b1, 0, b, 0, b1.length); + + return b; + } + + + public static int intToZigZag(final int n) { + return (n << 1) ^ (n >> 31); + } + + public static int zigzagToInt(final int n) { + return (n >>> 1) ^ -(n & 1); + } + + + public static long longToZigZag(final long n) { + return (n << 1) ^ (n >> 63); + } + + public static long zigzagToLong(final long n) { + return (n >>> 1) ^ -(n & 1); + } + + public static byte[] concat(final byte[]... arrays) { + int totalLength = 0; + + for (int i = 0; i < arrays.length; i++) { + totalLength += arrays[i].length; + } + + byte[] result = new byte[totalLength]; + + int currentIndex = 0; + for (int i = 0; i < arrays.length; i++) { + System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length); + currentIndex += arrays[i].length; + } + + return result; + } + + public static String safeTrim(final String string) { + if (string == null) { + return null; + } + return string.trim(); + } + + public static String toString(final byte[] bytes) { + if (bytes == null) { + return null; + } + return toString(bytes, 0, bytes.length); + } + + public static String toString(final byte [] bytes, final int offset, final int length) { + if (bytes == null) { + return null; + } + if (offset < 0) { + throw new IllegalArgumentException("negative offset:" + offset); + } + if (length == 0) { + return ""; + } + try { + return new String(bytes, offset, length, UTF8); + } catch (UnsupportedEncodingException e) { + LOGGER.log(Level.SEVERE, "UTF-8 encoding fail.", e); + return null; + } + } + + public static String toStringAndRightTrim(final byte[] bytes, final int offset, final int length) { + String string = toString(bytes, offset, length); + return trimRight(string); + } + + public static String trimRight(final String string) { + if (string == null) { + return null; + } + final int length = string.length(); + int index = length; +// Character.isWhitespace() 로 해야 하는 의문이 생김?? 안해도 될것 같기는 함. + while (string.charAt(index - 1) <= ' ') { + index--; + } + if (index == length) { + return string; + } else { + return string.substring(0, index); + } + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/DateUtils.java b/src/main/java/com/nhn/pinpoint/common/util/DateUtils.java new file mode 100644 index 000000000..55309bf95 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/DateUtils.java @@ -0,0 +1,36 @@ +package com.nhn.pinpoint.common.util; + +import org.springframework.core.NamedThreadLocal; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author emeroad + */ +public final class DateUtils { + + private static final NamedThreadLocal CACHE = new NamedThreadLocal(DateUtils.class.getName()) { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat(FORMAT); + } + }; + + private static final String FORMAT = "yyyy-MM-dd HH:mm:ss SSS"; + + private DateUtils() { + } + + public static String longToDateStr(long date) { + final DateFormat dateFormat = CACHE.get(); + return dateFormat.format(date); + } + + public static String longToDateStr(long date, String fmt) { + String pattern = (fmt == null) ? FORMAT : fmt; + final SimpleDateFormat format = new SimpleDateFormat(pattern); + return format.format(new Date(date)); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/DefaultParsingResult.java b/src/main/java/com/nhn/pinpoint/common/util/DefaultParsingResult.java new file mode 100644 index 000000000..60db1765b --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/DefaultParsingResult.java @@ -0,0 +1,83 @@ +package com.nhn.pinpoint.common.util; + + +/** + * @author emeroad + */ +public class DefaultParsingResult implements ParsingResult { + public static final char SEPARATOR = ','; + private String sql; + private StringBuilder output; + private int id; + + + public DefaultParsingResult() { + + } + + public DefaultParsingResult(String sql, StringBuilder output) { + this.output = output; + this.sql = sql; + } + + @Override + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + @Override + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public String getOutput() { + if (output == null) { + return ""; + } + return output.toString(); + } + + /** + * 최초 한번은 불려야 된다 안불리고 appendOutputParam을 호출하면 nullpointer exception + */ + void appendOutputSeparator() { + if (output == null) { + this.output = new StringBuilder(); + } else { + this.output.append(SEPARATOR); + } + } + + void appendOutputParam(String str) { + this.output.append(str); + } + + void appendSeparatorCheckOutputParam(char ch) { + if (ch == ',') { + this.output.append(",,"); + } else { + this.output.append(ch); + } + } + + void appendOutputParam(char ch) { + this.output.append(ch); + } + + @Override + public String toString() { + return "ParsingResult{" + + "sql='" + sql + '\'' + + ", output=" + output + + '}'; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/DefaultTimeSlot.java b/src/main/java/com/nhn/pinpoint/common/util/DefaultTimeSlot.java new file mode 100644 index 000000000..02eebec18 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/DefaultTimeSlot.java @@ -0,0 +1,27 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +//@Component +// spring 디펜던시를 걸어야 되서 그냥 안함. +public class DefaultTimeSlot implements TimeSlot { + + private static final long ONE_MIN_RESOLUTION = 60000; // 1min + + private final long resolution; + + public DefaultTimeSlot() { + this(ONE_MIN_RESOLUTION); + } + + public DefaultTimeSlot(long resolution) { + this.resolution = resolution; + } + + @Override + public long getTimeSlot(long time) { + // 과거 time을 기준으로 얻어오나, 모두 동일하게 과거 시간의 슬롯을 얻어오게 되므로 + RESOLUTION을 하지 않아도 된다. + return (time / resolution) * resolution; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/ExecutorFactory.java b/src/main/java/com/nhn/pinpoint/common/util/ExecutorFactory.java new file mode 100644 index 000000000..ac6333b86 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/ExecutorFactory.java @@ -0,0 +1,28 @@ +package com.nhn.pinpoint.common.util; + +import java.util.concurrent.*; + +/** + * @author emeroad + */ +public final class ExecutorFactory { + + private static final ThreadFactory DEFAULT_THREAD_FACTORY = new PinpointThreadFactory("Pinpoint-defaultThreadFactory", true); + + private ExecutorFactory() { + } + + public static ThreadPoolExecutor newFixedThreadPool(int nThreads, int workQueueMaxSize, ThreadFactory threadFactory) { + return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(workQueueMaxSize), threadFactory); + } + + public static ThreadPoolExecutor newFixedThreadPool(int nThreads, int workQueueMaxSize) { + return newFixedThreadPool(nThreads, workQueueMaxSize, DEFAULT_THREAD_FACTORY); + } + + public static ThreadPoolExecutor newFixedThreadPool(int nThreads, int workQueueMaxSize, String threadFactoryName, boolean daemon) { + ThreadFactory threadFactory = new PinpointThreadFactory(threadFactoryName, daemon); + return newFixedThreadPool(nThreads, workQueueMaxSize, threadFactory); + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/HttpUtils.java b/src/main/java/com/nhn/pinpoint/common/util/HttpUtils.java new file mode 100644 index 000000000..865aa51f7 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/HttpUtils.java @@ -0,0 +1,36 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public class HttpUtils { + + private static final String UTF8 = "UTF-8"; + + private static final String CHARSET = "charset="; + + public static String parseContentTypeCharset(String contentType) { + return parseContentTypeCharset(contentType, UTF8); + } + + public static String parseContentTypeCharset(String contentType, String defaultCharset) { + if (contentType == null) { + // 스펙상으로는 iso-8859-1 이나 요즘 대부분 was에서 UTF-8 고치기 때문에 애매하다. 옵션 설정에서 고칠수 있게 해야 될지도 모름. + return defaultCharset; + } + int charsetStart = contentType.indexOf(CHARSET); + if (charsetStart == -1) { + // 없음. + return defaultCharset; + } + // 요기가 시작점. + charsetStart = charsetStart + CHARSET.length(); + int charsetEnd = contentType.indexOf(';', charsetStart); + if (charsetEnd == -1) { + charsetEnd = contentType.length(); + } + contentType = contentType.substring(charsetStart, charsetEnd); + + return contentType.trim(); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/JvmUtils.java b/src/main/java/com/nhn/pinpoint/common/util/JvmUtils.java new file mode 100644 index 000000000..7d248e2e2 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/JvmUtils.java @@ -0,0 +1,43 @@ +package com.nhn.pinpoint.common.util; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.Map; + +import com.nhn.pinpoint.common.SystemPropertyKey; +import com.nhn.pinpoint.common.JvmVersion; + +/** + * @author hyungil.jeong + */ +public class JvmUtils { + private static final RuntimeMXBean RUNTIME_MX_BEAN = ManagementFactory.getRuntimeMXBean(); + private static final Map SYSTEM_PROPERTIES = RUNTIME_MX_BEAN.getSystemProperties(); + + private static final JvmVersion JVM_VERSION = _getVersion(); + + private JvmUtils() { + throw new IllegalAccessError(); + } + + public static JvmVersion getVersion() { + return JVM_VERSION; + } + + public static boolean supportsVersion(JvmVersion other) { + return JVM_VERSION.onOrAfter(other); + } + + public static String getSystemProperty(SystemPropertyKey systemPropertyKey) { + String key = systemPropertyKey.getKey(); + if (SYSTEM_PROPERTIES.containsKey(key)) { + return SYSTEM_PROPERTIES.get(key); + } + return ""; + } + + private static JvmVersion _getVersion() { + String javaVersion = getSystemProperty(SystemPropertyKey.JAVA_SPECIFICATION_VERSION); + return JvmVersion.getFromVersion(javaVersion); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/MathUtils.java b/src/main/java/com/nhn/pinpoint/common/util/MathUtils.java new file mode 100644 index 000000000..e5f1c76c1 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/MathUtils.java @@ -0,0 +1,14 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public final class MathUtils { + private MathUtils() { + } + + public static int fastAbs(final int value) { + return value & Integer.MAX_VALUE; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/OutputParameterParser.java b/src/main/java/com/nhn/pinpoint/common/util/OutputParameterParser.java new file mode 100644 index 000000000..aa89dd434 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/OutputParameterParser.java @@ -0,0 +1,51 @@ +package com.nhn.pinpoint.common.util; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * @author emeroad + */ +public class OutputParameterParser { + + public static final char SEPARATOR = DefaultParsingResult.SEPARATOR; + + public List parseOutputParameter(String outputParams) { + // 추가적으로 parsing result를 알수 있어야 될거 같음. + if (outputParams == null || outputParams.length() == 0) { + return Collections.emptyList(); + } + + final List result = new LinkedList(); + StringBuilder params = new StringBuilder(); + for (int index = 0; index < outputParams.length(); index++) { + final char ch = outputParams.charAt(index); + if (ch == SEPARATOR) { + if (lookAhead1(outputParams, index) == SEPARATOR) { + params.append(SEPARATOR); + index++; + } else { + result.add(params.toString()); + params = new StringBuilder(); + } + } else { + params.append(ch); + } + } + + result.add(params.toString()); + + return result; + } + + private int lookAhead1(String sql, int index) { + index++; + if (index < sql.length()) { + return sql.charAt(index); + } else { + return -1; + } + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/ParsingResult.java b/src/main/java/com/nhn/pinpoint/common/util/ParsingResult.java new file mode 100644 index 000000000..0d924bead --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/ParsingResult.java @@ -0,0 +1,12 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public interface ParsingResult { + String getSql(); + + String getOutput(); + + int getId(); +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/PinpointThreadFactory.java b/src/main/java/com/nhn/pinpoint/common/util/PinpointThreadFactory.java new file mode 100644 index 000000000..3bd00836c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/PinpointThreadFactory.java @@ -0,0 +1,68 @@ +package com.nhn.pinpoint.common.util; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author emeroad + */ +public class PinpointThreadFactory implements ThreadFactory { + + private final static AtomicInteger FACTORY_NUMBER = new AtomicInteger(0); + private final AtomicInteger threadNumber = new AtomicInteger(0); + + private final String threadPrefix; + private final boolean daemon; + + + public PinpointThreadFactory() { + this("Pinpoint", false); + } + + public PinpointThreadFactory(String threadName) { + this(threadName, false); + } + + public PinpointThreadFactory(String threadName, boolean daemon) { + if (threadName == null) { + throw new NullPointerException("threadName"); + } + this.threadPrefix = prefix(threadName, FACTORY_NUMBER.getAndIncrement()); + this.daemon = daemon; + } + + private String prefix(String threadName, int factoryId) { + final StringBuilder buffer = new StringBuilder(32); + buffer.append(threadName); + buffer.append('('); + buffer.append(factoryId); + buffer.append('-'); + return buffer.toString(); + } + + @Override + public Thread newThread(Runnable job) { + String newThreadName = createThreadName(); + Thread thread = new Thread(job, newThreadName); + if (daemon) { + thread.setDaemon(daemon); + } + return thread; + } + + private String createThreadName() { + StringBuilder buffer = new StringBuilder(threadPrefix.length() + 8); + buffer.append(threadPrefix); + buffer.append(threadNumber.getAndIncrement()); + buffer.append(')'); + return buffer.toString(); + } + + public static ThreadFactory createThreadFactory(String threadName) { + return createThreadFactory(threadName, false); + } + + public static ThreadFactory createThreadFactory(String threadName, boolean daemon) { + return new PinpointThreadFactory(threadName, daemon); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/PropertyUtils.java b/src/main/java/com/nhn/pinpoint/common/util/PropertyUtils.java new file mode 100644 index 000000000..ba4d2483c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/PropertyUtils.java @@ -0,0 +1,35 @@ +package com.nhn.pinpoint.common.util; + +import java.io.*; +import java.util.Properties; + +/** + * @author emeroad + */ +public class PropertyUtils { + + public static Properties readProperties(String propertyPath) throws IOException { + Properties properties = new Properties(); + InputStream in = null; + Reader reader = null; + try { + in = new FileInputStream(propertyPath); + reader = new InputStreamReader(in, "UTF-8"); + properties.load(reader); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignore) { + } + } + if (reader != null) { + try { + reader.close(); + } catch (IOException ignore) { + } + } + } + return properties; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/RowKeyUtils.java b/src/main/java/com/nhn/pinpoint/common/util/RowKeyUtils.java new file mode 100644 index 000000000..88a4cba72 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/RowKeyUtils.java @@ -0,0 +1,50 @@ +package com.nhn.pinpoint.common.util; + +import static com.nhn.pinpoint.common.PinpointConstants.AGENT_NAME_MAX_LEN; +import static com.nhn.pinpoint.common.util.BytesUtils.INT_BYTE_LENGTH; +import static com.nhn.pinpoint.common.util.BytesUtils.LONG_BYTE_LENGTH; + +import org.apache.hadoop.hbase.util.Bytes; + +/** + * @author emeroad + */ +public class RowKeyUtils { + + public static byte[] concatFixedByteAndLong(byte[] fixedBytes, int maxFixedLength, long l) { + if (fixedBytes == null) { + throw new NullPointerException("fixedBytes must not null"); + } + if (fixedBytes.length > maxFixedLength) { + throw new IllegalArgumentException("fixedBytes.length too big. length:" + fixedBytes.length); + } + byte[] rowKey = new byte[maxFixedLength + LONG_BYTE_LENGTH]; + Bytes.putBytes(rowKey, 0, fixedBytes, 0, fixedBytes.length); + BytesUtils.writeLong(l, rowKey, maxFixedLength); + return rowKey; + } + + + public static byte[] getMetaInfoRowKey(String agentId, long agentStartTime, int keyCode) { + // TODO 일단 agent의 조회 시간 로직을 따로 만들어야 되므로 그냥0으로 하자. + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + + final byte[] agentBytes = Bytes.toBytes(agentId); + if (agentBytes.length > AGENT_NAME_MAX_LEN) { + throw new IllegalArgumentException("agent.length too big. agent:" + agentId + " length:" + agentId.length()); + } + + final byte[] buffer = new byte[AGENT_NAME_MAX_LEN + LONG_BYTE_LENGTH + INT_BYTE_LENGTH]; + Bytes.putBytes(buffer, 0, agentBytes, 0, agentBytes.length); + + long reverseCurrentTimeMillis = TimeUtils.reverseTimeMillis(agentStartTime); + BytesUtils.writeLong(reverseCurrentTimeMillis, buffer, AGENT_NAME_MAX_LEN); + + BytesUtils.writeInt(keyCode, buffer, AGENT_NAME_MAX_LEN + LONG_BYTE_LENGTH); + return buffer; + } + + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/RpcCodeRange.java b/src/main/java/com/nhn/pinpoint/common/util/RpcCodeRange.java new file mode 100644 index 000000000..d5c4ab0f9 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/RpcCodeRange.java @@ -0,0 +1,15 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public final class RpcCodeRange { + + public static final short RPC_START = 9000; + public static final short RPC_END = 10000; + + public static boolean isRpcRange(short code) { + return code >= RPC_START && code < RPC_END; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/SpanEventUtils.java b/src/main/java/com/nhn/pinpoint/common/util/SpanEventUtils.java new file mode 100644 index 000000000..4f76bd653 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/SpanEventUtils.java @@ -0,0 +1,20 @@ +package com.nhn.pinpoint.common.util; + +import com.nhn.pinpoint.common.AnnotationKey; +import com.nhn.pinpoint.thrift.dto.TAnnotation; +import com.nhn.pinpoint.thrift.dto.TSpanEvent; + +import java.util.List; + +/** + * @author emeroad + */ +public class SpanEventUtils { + + public static boolean hasException(TSpanEvent spanEvent) { + if (spanEvent.isSetExceptionInfo()) { + return true; + } + return false; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/SpanUtils.java b/src/main/java/com/nhn/pinpoint/common/util/SpanUtils.java new file mode 100644 index 000000000..ffe3f2214 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/SpanUtils.java @@ -0,0 +1,82 @@ +package com.nhn.pinpoint.common.util; + +import static com.nhn.pinpoint.common.PinpointConstants.AGENT_NAME_MAX_LEN; + +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.thrift.dto.TSpan; +import com.nhn.pinpoint.thrift.dto.TSpanChunk; + +/** + * @author emeroad + */ +public class SpanUtils { + @Deprecated + public static byte[] getAgentIdTraceIndexRowKey(String agentId, long timestamp) { + if (agentId == null) { + throw new IllegalArgumentException("agentId must not null"); + } + final byte[] bAgentId = BytesUtils.toBytes(agentId); + return RowKeyUtils.concatFixedByteAndLong(bAgentId, AGENT_NAME_MAX_LEN, TimeUtils.reverseTimeMillis(timestamp)); + } + + public static byte[] getApplicationTraceIndexRowKey(String applicationName, long timestamp) { + if (applicationName == null) { + throw new IllegalArgumentException("agentId must not null"); + } + final byte[] bApplicationName = BytesUtils.toBytes(applicationName); + return RowKeyUtils.concatFixedByteAndLong(bApplicationName, AGENT_NAME_MAX_LEN, TimeUtils.reverseTimeMillis(timestamp)); + } + + public static byte[] getTraceIndexRowKey(byte[] agentId, long timestamp) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + return RowKeyUtils.concatFixedByteAndLong(agentId, AGENT_NAME_MAX_LEN, TimeUtils.reverseTimeMillis(timestamp)); + } + + public static byte[] getVarTransactionId(TSpan span) { + if (span == null) { + throw new NullPointerException("span must not be null"); + } + final byte[] transactionIdBytes = span.getTransactionId(); + TransactionId transactionId = TransactionIdUtils.parseTransactionId(transactionIdBytes); + String agentId = transactionId.getAgentId(); + if (agentId == null) { + agentId = span.getAgentId(); + } + + final Buffer buffer= new AutomaticBuffer(32); + buffer.putPrefixedString(agentId); + buffer.putSVar(transactionId.getAgentStartTime()); + buffer.putVar(transactionId.getTransactionSequence()); + return buffer.getBuffer(); + } + + public static byte[] getTransactionId(TSpan span) { + if (span == null) { + throw new NullPointerException("span must not be null"); + } + final byte[] transactionIdBytes = span.getTransactionId(); + TransactionId transactionId = TransactionIdUtils.parseTransactionId(transactionIdBytes); + String agentId = transactionId.getAgentId(); + if (agentId == null) { + agentId = span.getAgentId(); + } + return BytesUtils.stringLongLongToBytes(agentId, AGENT_NAME_MAX_LEN, transactionId.getAgentStartTime(), transactionId.getTransactionSequence()); + + } + + public static byte[] getTransactionId(TSpanChunk spanChunk) { + if (spanChunk == null) { + throw new NullPointerException("spanChunk must not be null"); + } + final byte[] transactionIdBytes = spanChunk.getTransactionId(); + final TransactionId transactionId = TransactionIdUtils.parseTransactionId(transactionIdBytes); + String agentId = transactionId.getAgentId(); + if (agentId == null) { + agentId = spanChunk.getAgentId(); + } + return BytesUtils.stringLongLongToBytes(agentId, AGENT_NAME_MAX_LEN, transactionId.getAgentStartTime(), transactionId.getTransactionSequence()); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/SqlParser.java b/src/main/java/com/nhn/pinpoint/common/util/SqlParser.java new file mode 100644 index 000000000..41a398d4b --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/SqlParser.java @@ -0,0 +1,415 @@ +package com.nhn.pinpoint.common.util; + +import java.util.List; + +/** + * @author emeroad + */ +public class SqlParser { + + public static final char SYMBOL_REPLACE = '$'; + public static final char NUMBER_REPLACE = '#'; + + private static final DefaultParsingResult NULL = new DefaultParsingResult("", new StringBuilder()); + private static final int NEXT_TOKEN_NOT_EXIST = -1; + + + public SqlParser() { + } + + public DefaultParsingResult normalizedSql(String sql) { + if (sql == null) { + return NULL; + } + + DefaultParsingResult parsingResult = new DefaultParsingResult(); + final int length = sql.length(); + final StringBuilder normalized = new StringBuilder(length + 16); + boolean change = false; + int replaceIndex = 0; + boolean numberTokenStartEnable = true; + for (int i = 0; i < length; i++) { + final char ch = sql.charAt(i); + switch (ch) { + // COMMENT start check + case '/': + // comment state + int lookAhead1Char = lookAhead1(sql, i); + // multi line comment and oracle hint /*+ */ + if (lookAhead1Char == '*') { + normalized.append("/*"); + i += 2; + for (; i < length; i++) { + char stateCh = sql.charAt(i); + if (stateCh == '*') { + if (lookAhead1(sql, i) == '/') { + normalized.append("*/"); + i++; + break; + } + } + normalized.append(stateCh); + } + break; + // single line comment + } else if (lookAhead1Char == '/') { + normalized.append("//"); + i += 2; + i = readLine(sql, normalized, i); + break; + + } else { + // unary operator + numberTokenStartEnable = true; + normalized.append(ch); + break; + } +// case '#' +// mysql 에서는 #도 한줄 짜리 comment이다. + case '-': + // single line comment state + if (lookAhead1(sql, i) == '-') { + normalized.append("--"); + i += 2; + i = readLine(sql, normalized, i); + break; + } else { + // unary operator + numberTokenStartEnable = true; + normalized.append(ch); + break; + } + + // SYMBOL start check + case '\'': + // empty symbol + if (lookAhead1(sql, i) == '\'') { + normalized.append("''"); + // $로 치환하지 않으므로 output에 파라미터를 넣을필요가 없다 + i += 2; + break; + } else { + change = true; + normalized.append('\''); + i++; + parsingResult.appendOutputSeparator(); + for (; i < length; i++) { + char stateCh = sql.charAt(i); + if (stateCh == '\'') { + // '' 이 연속으로 나왔을 경우는 \' 이므로 그대로 넣는다. + if (lookAhead1(sql, i) == '\'') { + i++; + parsingResult.appendOutputParam("''"); + continue; + } else { + normalized.append(replaceIndex++); + normalized.append(SYMBOL_REPLACE); + normalized.append('\''); +// outputParam.append(','); + break; + } + } + parsingResult.appendSeparatorCheckOutputParam(stateCh); + } + break; + } + + // number start check + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // http://www.h2database.com/html/grammar.html 추가로 state machine을 더볼것. + if (numberTokenStartEnable) { + change = true; + normalized.append(replaceIndex++); + normalized.append(NUMBER_REPLACE); + // number token start + parsingResult.appendOutputSeparator(); + parsingResult.appendOutputParam(ch); + i++; + tokenEnd: + for (; i < length; i++) { + char stateCh = sql.charAt(i); + switch (stateCh) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + case 'E': + case 'e': + parsingResult.appendOutputParam(stateCh); + break; + default: + // 여기서 처리하지 말고 루프 바깥으로 나가서 다시 token을 봐야 된다. +// outputParam.append(SEPARATOR); + i--; + break tokenEnd; + } + } + break; + } else { + normalized.append(ch); + break; + } + + // 공백 space를 만남 + case ' ': + case '\t': + case '\n': + case '\r': + numberTokenStartEnable = true; + normalized.append(ch); + break; + // http://msdn.microsoft.com/en-us/library/ms174986.aspx 참조. + case '*': + case '+': + case '%': + case '=': + case '<': + case '>': + case '&': + case '|': + case '^': + case '~': + case '!': + numberTokenStartEnable = true; + normalized.append(ch); + break; + + case '(': + case ')': + case ',': + case ';': + numberTokenStartEnable = true; + normalized.append(ch); + break; + + case '.': + case '_': + case '@': // Assignment Operator + case ':': // 오라클쪽의 bind 변수는 :bindvalue로도 가능. + numberTokenStartEnable = false; + normalized.append(ch); + break; + + default: + // 한글이면 ?? + if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') { + numberTokenStartEnable = false; + } else { + numberTokenStartEnable = true; + } + normalized.append(ch); + break; + } + } + if (change) { + parsingResult.setSql(normalized.toString()); + return parsingResult; + } else { + // 수정되지 않았을 경우의 재활용. + // 1. 성능향상을 위해 string을 생성하지 않도록. + // 2. hash code재활용. + parsingResult.setSql(sql); + return parsingResult; + } + } + + private int readLine(String sql, StringBuilder normalized, int index) { + final int length = sql.length(); + for (; index < length; index++) { + char ch = sql.charAt(index); + normalized.append(ch); + if (ch == '\n') { + break; + } + } + return index; + } + + /** + * 미리 다음 문자열 하나를 까본다. + * + * @param sql + * @param index + * @return + */ + private int lookAhead1(String sql, int index) { + index++; + if (index < sql.length()) { + return sql.charAt(index); + } else { + return NEXT_TOKEN_NOT_EXIST; + } + } + + public String combineOutputParams(String sql, List outputParams) { + + final int length = sql.length(); + final StringBuilder normalized = new StringBuilder(length + 16); + for (int i = 0; i < length; i++) { + final char ch = sql.charAt(i); + switch (ch) { + // COMMENT start check + case '/': + // comment state + int lookAhead1Char = lookAhead1(sql, i); + // multi line comment and oracle hint /*+ */ + if (lookAhead1Char == '*') { + normalized.append("/*"); + i += 2; + for (; i < length; i++) { + char stateCh = sql.charAt(i); + if (stateCh == '*') { + if (lookAhead1(sql, i) == '/') { + normalized.append("*/"); + i++; + break; + } + } + normalized.append(stateCh); + } + break; + // single line comment + } else if (lookAhead1Char == '/') { + normalized.append("//"); + i += 2; + i = readLine(sql, normalized, i); + break; + + } else { + // unary operator +// numberTokenStartEnable = true; + normalized.append(ch); + break; + } +// case '#' +// mysql 에서는 #도 한줄 짜리 comment이다. + case '-': + // single line comment state + if (lookAhead1(sql, i) == '-') { + normalized.append("--"); + i += 2; + i = readLine(sql, normalized, i); + break; + } else { + // unary operator +// numberTokenStartEnable = true; + normalized.append(ch); + break; + } + + // number start check + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + // http://www.h2database.com/html/grammar.html 추가로 state machine을 더볼것. + if (lookAhead1(sql, i) == NEXT_TOKEN_NOT_EXIST) { + normalized.append(ch); + break; + } + StringBuilder outputIndex = new StringBuilder(); + outputIndex.append(ch); + // number token start + i++; + tokenEnd: + for (; i < length; i++) { + char stateCh = sql.charAt(i); + switch (stateCh) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (lookAhead1(sql, i) == NEXT_TOKEN_NOT_EXIST) { + outputIndex.append(stateCh); + normalized.append(outputIndex.toString()); + break tokenEnd; + } + outputIndex.append(stateCh); + break; + case NUMBER_REPLACE: + int numberIndex = 0; + try { + numberIndex = Integer.parseInt(outputIndex.toString()); + } catch (NumberFormatException e) { + // 잘못된 파라미터일 경우 그냥 쓰자. + normalized.append(outputIndex.toString()); + normalized.append(NUMBER_REPLACE); + break tokenEnd; + } + try { + String replaceNumber = outputParams.get(numberIndex); + normalized.append(replaceNumber); + } catch (IndexOutOfBoundsException e) { + // 잘못된 파라미터일 경우 그냥 쓰자. + normalized.append(outputIndex.toString()); + normalized.append(NUMBER_REPLACE); + break tokenEnd; + } + break tokenEnd; + + case SYMBOL_REPLACE: + int symbolIndex = 0; + try { + symbolIndex = Integer.parseInt(outputIndex.toString()); + } catch (NumberFormatException e) { + // 잘못된 파라미터일 경우 그냥 쓰자. + normalized.append(outputIndex.toString()); + normalized.append(SYMBOL_REPLACE); + } + try { + String replaceSymbol = outputParams.get(symbolIndex); + normalized.append(replaceSymbol); + } catch (IndexOutOfBoundsException e) { + normalized.append(outputIndex.toString()); + normalized.append(SYMBOL_REPLACE); + } + break tokenEnd; + + default: + // 여기서 처리하지 말고 루프 바깥으로 나가서 다시 token을 봐야 된다. +// outputParam.append(SEPARATOR); + normalized.append(outputIndex.toString()); + i--; + break tokenEnd; + } + } + break; + + default: + normalized.append(ch); + break; + } + } + + return normalized.toString(); + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/StopWatch.java b/src/main/java/com/nhn/pinpoint/common/util/StopWatch.java new file mode 100644 index 000000000..81c97048c --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/StopWatch.java @@ -0,0 +1,18 @@ +package com.nhn.pinpoint.common.util; + +/** + * 단순한 stopwatch + * @author emeroad + */ +public class StopWatch { + private long start; + + public void start() { + this.start = System.currentTimeMillis(); + } + + public long stop() { + return System.currentTimeMillis() - this.start; + } + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/StringTraceHeaderParser.java b/src/main/java/com/nhn/pinpoint/common/util/StringTraceHeaderParser.java new file mode 100644 index 000000000..1a379eee0 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/StringTraceHeaderParser.java @@ -0,0 +1,71 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public class StringTraceHeaderParser { + + // request.addHeader(Header.HTTP_TRACE_ID.toString(), nextId.getId().toString()); +// request.addHeader(Header.HTTP_SPAN_ID.toString(), Long.toString(nextId.getSpanId())); +// request.addHeader(Header.HTTP_PARENT_SPAN_ID.toString(), Long.toString(nextId.getParentSpanId())); +// request.addHeader(Header.HTTP_SAMPLED.toString(), String.valueOf(nextId.isSampled())); +// request.addHeader(Header.HTTP_FLAGS.toString(), String.valueOf(nextId.getFlags())); + public static final char DELIMITER_STRING = ':'; + public static final int ID_INDEX = 36; + + public String createHeader(String uuid, int spanId, int parentSpanId, int sampling, short flag) { + StringBuilder sb = new StringBuilder(128); + sb.append(uuid); + sb.append(DELIMITER_STRING); + sb.append(spanId); + sb.append(DELIMITER_STRING); + sb.append(parentSpanId); + sb.append(DELIMITER_STRING); + sb.append(sampling); + sb.append(DELIMITER_STRING); + sb.append(flag); + return sb.toString(); + } + + public TraceHeader parseHeader(String traceHeader) { + if (traceHeader == null) { + return null; + } + + char c = traceHeader.charAt(ID_INDEX); + if (c != DELIMITER_STRING) { + return null; + } + String id = traceHeader.substring(0, ID_INDEX); + + int spanIdStartIndex = ID_INDEX + 1; + int spanIdEndIndex = traceHeader.indexOf(DELIMITER_STRING, spanIdStartIndex); + String spanId = traceHeader.substring(spanIdStartIndex, spanIdEndIndex); + + int parentSpanIdStartIndex = spanIdEndIndex + 1; + int parentSpanIdEndIndex = traceHeader.indexOf(DELIMITER_STRING, parentSpanIdStartIndex); + String parentSpanId = traceHeader.substring(parentSpanIdStartIndex, parentSpanIdEndIndex); + + int samplingStartIndex = parentSpanIdEndIndex + 1; + int samplingEndIndex = traceHeader.indexOf(DELIMITER_STRING, samplingStartIndex); + if (samplingEndIndex == -1) { + return new TraceHeader(id, spanId, parentSpanId, "", ""); + } + String sampling = traceHeader.substring(samplingStartIndex, samplingEndIndex); + + + int flagStartIndex = samplingEndIndex + 1; + if (flagStartIndex == -1) { + return new TraceHeader(id, spanId, parentSpanId, sampling, ""); + } + int flagEndIndex = traceHeader.indexOf(DELIMITER_STRING, flagStartIndex); + if (flagEndIndex == -1) { + String flag = traceHeader.substring(flagStartIndex); + return new TraceHeader(id, spanId, parentSpanId, sampling, flag); + } + String flag = traceHeader.substring(flagStartIndex, flagEndIndex); + return new TraceHeader(id, spanId, parentSpanId, sampling, flag); + } + + +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/TimeSlot.java b/src/main/java/com/nhn/pinpoint/common/util/TimeSlot.java new file mode 100644 index 000000000..a25781169 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/TimeSlot.java @@ -0,0 +1,8 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public interface TimeSlot { + public long getTimeSlot(long time); +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/TimeUtils.java b/src/main/java/com/nhn/pinpoint/common/util/TimeUtils.java new file mode 100644 index 000000000..fa357ffe8 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/TimeUtils.java @@ -0,0 +1,19 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public final class TimeUtils { + + public static long reverseTimeMillis(long currentTimeMillis) { + return Long.MAX_VALUE - currentTimeMillis; + } + + public static long reverseCurrentTimeMillis() { + return reverseTimeMillis(System.currentTimeMillis()); + } + + public static long recoveryTimeMillis(long reverseCurrentTimeMillis) { + return Long.MAX_VALUE - reverseCurrentTimeMillis; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/TraceHeader.java b/src/main/java/com/nhn/pinpoint/common/util/TraceHeader.java new file mode 100644 index 000000000..7674a5486 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/TraceHeader.java @@ -0,0 +1,74 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public class TraceHeader { + private String id; + private String spanId; + private String parentSpanId; + private String sampling; + private String flag; + + public TraceHeader() { + } + + public TraceHeader(String id, String spanId, String parentSpanId, String sampling, String flag) { + this.id = id; + this.spanId = spanId; + this.parentSpanId = parentSpanId; + this.sampling = sampling; + this.flag = flag; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getSpanId() { + return spanId; + } + + public void setSpanId(String spanId) { + this.spanId = spanId; + } + + public String getParentSpanId() { + return parentSpanId; + } + + public void setParentSpanId(String parentSpanId) { + this.parentSpanId = parentSpanId; + } + + public String getSampling() { + return sampling; + } + + public void setSampling(String sampling) { + this.sampling = sampling; + } + + public String getFlag() { + return flag; + } + + public void setFlag(String flag) { + this.flag = flag; + } + + @Override + public String toString() { + return "TraceHeader{" + + "id='" + id + '\'' + + ", spanId='" + spanId + '\'' + + ", parentSpanId='" + parentSpanId + '\'' + + ", sampling='" + sampling + '\'' + + ", flag='" + flag + '\'' + + '}'; + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/TransactionId.java b/src/main/java/com/nhn/pinpoint/common/util/TransactionId.java new file mode 100644 index 000000000..9484e4b0b --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/TransactionId.java @@ -0,0 +1,70 @@ +package com.nhn.pinpoint.common.util; + +/** + * @author emeroad + */ +public class TransactionId { + + protected String agentId; + protected long agentStartTime; + protected long transactionSequence; + + public TransactionId(String agentId, long agentStartTime, long transactionSequence) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + this.agentId = agentId; + this.agentStartTime = agentStartTime; + this.transactionSequence = transactionSequence; + } + + public TransactionId(long agentStartTime, long transactionSequence) { + this.agentStartTime = agentStartTime; + this.transactionSequence = transactionSequence; + } + + public String getAgentId() { + return agentId; + } + + public long getAgentStartTime() { + return agentStartTime; + } + + public long getTransactionSequence() { + return transactionSequence; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + TransactionId that = (TransactionId) o; + + if (agentStartTime != that.agentStartTime) return false; + if (transactionSequence != that.transactionSequence) return false; + if (!agentId.equals(that.agentId)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = agentId.hashCode(); + result = 31 * result + (int) (agentStartTime ^ (agentStartTime >>> 32)); + result = 31 * result + (int) (transactionSequence ^ (transactionSequence >>> 32)); + return result; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("TransactionId{"); + sb.append("agentId='").append(agentId).append('\''); + sb.append(", agentStartTime=").append(agentStartTime); + sb.append(", transactionSequence=").append(transactionSequence); + sb.append('}'); + return sb.toString(); + } +} diff --git a/src/main/java/com/nhn/pinpoint/common/util/TransactionIdUtils.java b/src/main/java/com/nhn/pinpoint/common/util/TransactionIdUtils.java new file mode 100644 index 000000000..076a6bb99 --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/common/util/TransactionIdUtils.java @@ -0,0 +1,92 @@ +package com.nhn.pinpoint.common.util; + +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import com.nhn.pinpoint.common.buffer.FixedBuffer; + +/** + * @author emeroad + */ +public final class TransactionIdUtils { + // html 에서 표시되는 값이라. html 상에서 해석이 다르게 되는 문자열은 사용하면 안됨. + public static final String TRANSACTION_ID_DELIMITER = "^"; + public static final byte VERSION = 0; + + public static String formatString(String agentId, long agentStartTime, long transactionSequence) { + if (agentId == null) { + throw new NullPointerException("agentId must not be null"); + } + StringBuilder sb = new StringBuilder(64); + sb.append(agentId); + sb.append(TRANSACTION_ID_DELIMITER); + sb.append(agentStartTime); + sb.append(TRANSACTION_ID_DELIMITER); + sb.append(transactionSequence); + return sb.toString(); + } + + public static byte[] formatBytes(String agentId, long agentStartTime, long transactionSequence) { + // agentId는 null이 될수 있음. + // vesion + prefixed size + string + long + long + final Buffer buffer = new AutomaticBuffer(1 + 5 + 24 + 10 + 10); + buffer.put(VERSION); + buffer.putPrefixedString(agentId); + buffer.putVar(agentStartTime); + buffer.putVar(transactionSequence); + return buffer.getBuffer(); + } + + public static TransactionId parseTransactionId(final byte[] transactionId) { + if (transactionId == null) { + throw new NullPointerException("transactionId must not be null"); + } + final Buffer buffer = new FixedBuffer(transactionId); + final byte version = buffer.readByte(); + if (version != VERSION) { + throw new IllegalArgumentException("invalid Version"); + } + + final String agentId = buffer.readPrefixedString(); + final long agentStartTime = buffer.readVarLong(); + final long transactionSequence = buffer.readVarLong(); + if (agentId == null) { + return new TransactionId(agentStartTime, transactionSequence); + } else { + return new TransactionId(agentId, agentStartTime,transactionSequence); + } + } + + public static TransactionId parseTransactionId(final String transactionId) { + if (transactionId == null) { + throw new NullPointerException("transactionId must not be null"); + } + + final int agentIdIndex = transactionId.indexOf(TRANSACTION_ID_DELIMITER); + if (agentIdIndex == -1) { + throw new IllegalArgumentException("agentIndex not found:" + transactionId); + } + final String agentId = transactionId.substring(0, agentIdIndex); + + final int agentStartTimeIndex = transactionId.indexOf(TRANSACTION_ID_DELIMITER, agentIdIndex + 1); + if (agentStartTimeIndex == -1) { + throw new IllegalArgumentException("agentStartTimeIndex not found:" + transactionId); + } + final long agentStartTime = parseLong(transactionId.substring(agentIdIndex + 1, agentStartTimeIndex)); + + int transactionSequenceIndex = transactionId.indexOf(TRANSACTION_ID_DELIMITER, agentStartTimeIndex + 1); + if (transactionSequenceIndex == -1) { + // 이거는 없을수 있음. transactionSequence 다음에 델리미터가 일단 없는게 기본값임. 향후 추가 아이디 스펙이 확장가능하므로 보완한다. + transactionSequenceIndex = transactionId.length(); + } + final long transactionSequence = parseLong(transactionId.substring(agentStartTimeIndex + 1, transactionSequenceIndex)); + return new TransactionId(agentId, agentStartTime, transactionSequence); + } + + private static long parseLong(String longString) { + try { + return Long.parseLong(longString); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("parseError. " + longString); + } + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/AnnotationKeyTest.java b/src/test/java/com/nhn/pinpoint/common/AnnotationKeyTest.java new file mode 100644 index 000000000..73d6f3dcf --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/AnnotationKeyTest.java @@ -0,0 +1,46 @@ +package com.nhn.pinpoint.common; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class AnnotationKeyTest { + + @Test + public void getCode() { + + AnnotationKey annotationKey = AnnotationKey.findAnnotationKey(AnnotationKey.API.getCode()); + Assert.assertEquals(annotationKey, AnnotationKey.API); + } + +// @Test + public void intSize() { +// 2147483647 + System.out.println(Integer.MAX_VALUE); +// -2147483648 + System.out.println(Integer.MIN_VALUE); + } + + @Test + public void isArgsKey() { + Assert.assertTrue(AnnotationKey.isArgsKey(AnnotationKey.ARGS0.getCode())); + Assert.assertTrue(AnnotationKey.isArgsKey(AnnotationKey.ARGSN.getCode())); + Assert.assertTrue(AnnotationKey.isArgsKey(AnnotationKey.ARGS5.getCode())); + + Assert.assertFalse(AnnotationKey.isArgsKey(AnnotationKey.ARGS0.getCode() +1)); + Assert.assertFalse(AnnotationKey.isArgsKey(AnnotationKey.ARGSN.getCode() -1)); + Assert.assertFalse(AnnotationKey.isArgsKey(Integer.MAX_VALUE)); + Assert.assertFalse(AnnotationKey.isArgsKey(Integer.MIN_VALUE)); + + } + + @Test + public void isCachedArgsToArgs() { + int i = AnnotationKey.cachedArgsToArgs(AnnotationKey.CACHE_ARGS0.getCode()); + Assert.assertEquals(i, AnnotationKey.ARGS0.getCode()); + + + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/HistogramSchemaTest.java b/src/test/java/com/nhn/pinpoint/common/HistogramSchemaTest.java new file mode 100644 index 000000000..a6b2ec1f3 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/HistogramSchemaTest.java @@ -0,0 +1,39 @@ +package com.nhn.pinpoint.common; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class HistogramSchemaTest { + @Test + public void testAddHistogramSlot() throws Exception { + + } + + @Test + public void testGetHistogramSlotList() throws Exception { + + } + + @Test + public void testCreateNode() throws Exception { + + } + + @Test + public void testFindHistogramSlot() throws Exception { + HistogramSchema histogramSchema = ServiceType.TOMCAT.getHistogramSchema(); + Assert.assertEquals(histogramSchema.findHistogramSlot(999).getSlotTime(), 1000); + Assert.assertEquals(histogramSchema.findHistogramSlot(1000).getSlotTime(), 1000); + Assert.assertEquals(histogramSchema.findHistogramSlot(1111).getSlotTime(), 3000); + } + + + + @Test + public void testGetHistogramSlotIndex() throws Exception { + + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/JvmVersionTest.java b/src/test/java/com/nhn/pinpoint/common/JvmVersionTest.java new file mode 100644 index 000000000..0ebb0b312 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/JvmVersionTest.java @@ -0,0 +1,103 @@ +package com.nhn.pinpoint.common; + +import static org.junit.Assert.*; +import static com.nhn.pinpoint.common.JvmVersion.*; + +import org.junit.Test; + +/** + * @author hyungil.jeong + */ +public class JvmVersionTest { + + @Test + public void testOnOrAfter() { + // JDK 5 + assertTrue(JAVA_5.onOrAfter(JAVA_5)); + assertFalse(JAVA_5.onOrAfter(JAVA_6)); + assertFalse(JAVA_5.onOrAfter(JAVA_7)); + assertFalse(JAVA_5.onOrAfter(JAVA_8)); + assertFalse(JAVA_5.onOrAfter(UNSUPPORTED)); + // JDK 6 + assertTrue(JAVA_6.onOrAfter(JAVA_5)); + assertTrue(JAVA_6.onOrAfter(JAVA_6)); + assertFalse(JAVA_6.onOrAfter(JAVA_7)); + assertFalse(JAVA_6.onOrAfter(JAVA_8)); + assertFalse(JAVA_6.onOrAfter(UNSUPPORTED)); + // JDK 7 + assertTrue(JAVA_7.onOrAfter(JAVA_5)); + assertTrue(JAVA_7.onOrAfter(JAVA_6)); + assertTrue(JAVA_7.onOrAfter(JAVA_7)); + assertFalse(JAVA_7.onOrAfter(JAVA_8)); + assertFalse(JAVA_7.onOrAfter(UNSUPPORTED)); + // JDK 8 + assertTrue(JAVA_8.onOrAfter(JAVA_5)); + assertTrue(JAVA_8.onOrAfter(JAVA_6)); + assertTrue(JAVA_8.onOrAfter(JAVA_7)); + assertTrue(JAVA_8.onOrAfter(JAVA_8)); + assertFalse(JAVA_8.onOrAfter(UNSUPPORTED)); + // Unsupported + assertFalse(UNSUPPORTED.onOrAfter(JAVA_5)); + assertFalse(UNSUPPORTED.onOrAfter(JAVA_6)); + assertFalse(UNSUPPORTED.onOrAfter(JAVA_7)); + assertFalse(UNSUPPORTED.onOrAfter(JAVA_8)); + assertFalse(UNSUPPORTED.onOrAfter(UNSUPPORTED)); + } + + @Test + public void testGetFromDoubleVersion() { + // JDK 5 + final JvmVersion java_5 = JvmVersion.getFromVersion(1.5); + assertSame(java_5, JAVA_5); + // JDK 6 + final JvmVersion java_6 = JvmVersion.getFromVersion(1.6); + assertSame(java_6, JAVA_6); + // JDK 7 + final JvmVersion java_7 = JvmVersion.getFromVersion(1.7); + assertSame(java_7, JAVA_7); + // JDK 8 + final JvmVersion java_8 = JvmVersion.getFromVersion(1.8); + assertSame(java_8, JAVA_8); + // Unsupported + final JvmVersion java_unsupported = JvmVersion.getFromVersion(0.9); + assertSame(java_unsupported, UNSUPPORTED); + } + + @Test + public void testGetFromStringVersion() { + // JDK 5 + final JvmVersion java_5 = JvmVersion.getFromVersion("1.5"); + assertSame(java_5, JAVA_5); + // JDK 6 + final JvmVersion java_6 = JvmVersion.getFromVersion("1.6"); + assertSame(java_6, JAVA_6); + // JDK 7 + final JvmVersion java_7 = JvmVersion.getFromVersion("1.7"); + assertSame(java_7, JAVA_7); + // JDK 8 + final JvmVersion java_8 = JvmVersion.getFromVersion("1.8"); + assertSame(java_8, JAVA_8); + // Unsupported + final JvmVersion java_unsupported = JvmVersion.getFromVersion("abc"); + assertSame(java_unsupported, UNSUPPORTED); + } + + @Test + public void testGetFromClassVersion() { + // JDK 5 + final JvmVersion java_5 = JvmVersion.getFromClassVersion(49); + assertSame(java_5, JAVA_5); + // JDK 6 + final JvmVersion java_6 = JvmVersion.getFromClassVersion(50); + assertSame(java_6, JAVA_6); + // JDK 7 + final JvmVersion java_7 = JvmVersion.getFromClassVersion(51); + assertSame(java_7, JAVA_7); + // JDK 8 + final JvmVersion java_8 = JvmVersion.getFromClassVersion(52); + assertSame(java_8, JAVA_8); + // Unsupported + final JvmVersion java_unsupported = JvmVersion.getFromClassVersion(-1); + assertSame(java_unsupported, UNSUPPORTED); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/ServiceTypeTest.java b/src/test/java/com/nhn/pinpoint/common/ServiceTypeTest.java new file mode 100644 index 000000000..a09be2b72 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/ServiceTypeTest.java @@ -0,0 +1,56 @@ +package com.nhn.pinpoint.common; + +import junit.framework.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class ServiceTypeTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + @Test + public void testIndexable() { + System.out.println(ServiceType.TOMCAT.isIndexable()); + System.out.println(ServiceType.BLOC.isIndexable()); + System.out.println(ServiceType.ARCUS.isIndexable()); + } + + @Test + public void findDesc() { + String desc = "MYSQL"; + List mysqlList = ServiceType.findDesc(desc); + boolean find = false; + for (ServiceType serviceType : mysqlList) { + if(serviceType.getDesc().equals(desc)) { + find = true; + } + } + Assert.assertTrue(find); + + try { + mysqlList.add(ServiceType.ARCUS); + Assert.fail(); + } catch (Exception e) { + } + } + + @Test + public void child() { + ServiceType oracle = ServiceType.ORACLE; + + + } + + @Test + public void test() { + ServiceType[] values = ServiceType.values(); + for (ServiceType value : values) { + logger.debug(value.toString() + " " + value.getCode()); + } + + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/bo/AgentStatCpuLoadBoTest.java b/src/test/java/com/nhn/pinpoint/common/bo/AgentStatCpuLoadBoTest.java new file mode 100644 index 000000000..ebf34eaf3 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/bo/AgentStatCpuLoadBoTest.java @@ -0,0 +1,82 @@ +package com.nhn.pinpoint.common.bo; + +import static org.junit.Assert.*; + +import org.junit.Test; + +/** + * @author hyungil.jeong + */ +public class AgentStatCpuLoadBoTest { + + // CPU 사용량 소수점 2자리 표시 + private static final double DELTA = 1e-4; + + @Test + public void testByteArrayConversion() { + // Given + final AgentStatCpuLoadBo testBo = createTestBo(0.22871734201908112D, 0.23790152370929718D); + // When + final byte[] serializedBo = testBo.writeValue(); + final AgentStatCpuLoadBo deserializedBo = new AgentStatCpuLoadBo.Builder(serializedBo).build(); + // Then + assertEquals(testBo.getAgentId(), deserializedBo.getAgentId()); + assertEquals(testBo.getStartTimestamp(), deserializedBo.getStartTimestamp()); + assertEquals(testBo.getTimestamp(), deserializedBo.getTimestamp()); + assertEquals(testBo.getJvmCpuLoad(), deserializedBo.getJvmCpuLoad(), DELTA); + assertEquals(testBo.getSystemCpuLoad(), deserializedBo.getSystemCpuLoad(), DELTA); + } + + @Test + public void testByteArrayConversionEdges() { + // Given + final AgentStatCpuLoadBo testBo = createTestBo(Double.MIN_VALUE, Double.MAX_VALUE); + // When + final byte[] serializedBo = testBo.writeValue(); + final AgentStatCpuLoadBo deserializedBo = new AgentStatCpuLoadBo.Builder(serializedBo).build(); + // Then + assertEquals(testBo.getAgentId(), deserializedBo.getAgentId()); + assertEquals(testBo.getStartTimestamp(), deserializedBo.getStartTimestamp()); + assertEquals(testBo.getTimestamp(), deserializedBo.getTimestamp()); + assertEquals(testBo.getJvmCpuLoad(), deserializedBo.getJvmCpuLoad(), DELTA); + assertEquals(testBo.getSystemCpuLoad(), deserializedBo.getSystemCpuLoad(), DELTA); + } + + @Test + public void testByteArrayConversionNanValues() { + // Given + final AgentStatCpuLoadBo testBo = createTestBo(Double.NaN, Double.NaN); + // When + final byte[] serializedBo = testBo.writeValue(); + final AgentStatCpuLoadBo deserializedBo = new AgentStatCpuLoadBo.Builder(serializedBo).build(); + // Then + assertEquals(testBo.getAgentId(), deserializedBo.getAgentId()); + assertEquals(testBo.getStartTimestamp(), deserializedBo.getStartTimestamp()); + assertEquals(testBo.getTimestamp(), deserializedBo.getTimestamp()); + assertEquals(testBo.getJvmCpuLoad(), deserializedBo.getJvmCpuLoad(), DELTA); + assertEquals(testBo.getSystemCpuLoad(), deserializedBo.getSystemCpuLoad(), DELTA); + } + + @Test + public void testByteArrayConversionInfiniteValues() { + // Given + final AgentStatCpuLoadBo testBo = createTestBo(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY); + // When + final byte[] serializedBo = testBo.writeValue(); + final AgentStatCpuLoadBo deserializedBo = new AgentStatCpuLoadBo.Builder(serializedBo).build(); + // Then + assertEquals(testBo.getAgentId(), deserializedBo.getAgentId()); + assertEquals(testBo.getStartTimestamp(), deserializedBo.getStartTimestamp()); + assertEquals(testBo.getTimestamp(), deserializedBo.getTimestamp()); + assertEquals(testBo.getJvmCpuLoad(), deserializedBo.getJvmCpuLoad(), DELTA); + assertEquals(testBo.getSystemCpuLoad(), deserializedBo.getSystemCpuLoad(), DELTA); + } + + private AgentStatCpuLoadBo createTestBo(double jvmCpuLoad, double systemCpuLoad) { + final AgentStatCpuLoadBo.Builder builder = new AgentStatCpuLoadBo.Builder("agentId", 0L, 0L); + builder.jvmCpuLoad(jvmCpuLoad); + builder.systemCpuLoad(systemCpuLoad); + return builder.build(); + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/bo/AgentStatMemoryGcBoTest.java b/src/test/java/com/nhn/pinpoint/common/bo/AgentStatMemoryGcBoTest.java new file mode 100644 index 000000000..3bff52451 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/bo/AgentStatMemoryGcBoTest.java @@ -0,0 +1,42 @@ +package com.nhn.pinpoint.common.bo; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import com.nhn.pinpoint.thrift.dto.TJvmGcType; + +/** + * @author hyungil.jeong + */ +public class AgentStatMemoryGcBoTest { + + @Test + public void testByteArrayConversion() { + // Given + final AgentStatMemoryGcBo.Builder builder = new AgentStatMemoryGcBo.Builder("agentId", 0L, 1L); + builder.gcType(TJvmGcType.G1.name()); + builder.jvmMemoryHeapUsed(Long.MIN_VALUE); + builder.jvmMemoryHeapMax(Long.MAX_VALUE); + builder.jvmMemoryNonHeapUsed(Long.MIN_VALUE); + builder.jvmMemoryNonHeapMax(Long.MAX_VALUE); + builder.jvmGcOldCount(1L); + builder.jvmGcOldTime(2L); + final AgentStatMemoryGcBo testBo = builder.build(); + // When + final byte[] serializedBo = testBo.writeValue(); + final AgentStatMemoryGcBo deserializedBo = new AgentStatMemoryGcBo.Builder(serializedBo).build(); + // Then + assertEquals(testBo.getAgentId(), deserializedBo.getAgentId()); + assertEquals(testBo.getStartTimestamp(), deserializedBo.getStartTimestamp()); + assertEquals(testBo.getTimestamp(), deserializedBo.getTimestamp()); + assertEquals(testBo.getGcType(), deserializedBo.getGcType()); + assertEquals(testBo.getJvmMemoryHeapUsed(), deserializedBo.getJvmMemoryHeapUsed()); + assertEquals(testBo.getJvmMemoryHeapMax(), deserializedBo.getJvmMemoryHeapMax()); + assertEquals(testBo.getJvmMemoryNonHeapUsed(), deserializedBo.getJvmMemoryNonHeapUsed()); + assertEquals(testBo.getJvmMemoryNonHeapMax(), deserializedBo.getJvmMemoryNonHeapMax()); + assertEquals(testBo.getJvmGcOldCount(), deserializedBo.getJvmGcOldCount()); + assertEquals(testBo.getJvmGcOldTime(), deserializedBo.getJvmGcOldTime()); + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/bo/AnnotationBoTest.java b/src/test/java/com/nhn/pinpoint/common/bo/AnnotationBoTest.java new file mode 100644 index 000000000..148839950 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/bo/AnnotationBoTest.java @@ -0,0 +1,41 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.AnnotationKey; +import com.nhn.pinpoint.common.buffer.AutomaticBuffer; +import com.nhn.pinpoint.common.buffer.Buffer; +import org.junit.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class AnnotationBoTest { + @Test + public void testGetVersion() throws Exception { + + } + + @Test + public void testSetVersion() throws Exception { + + } + + @Test + public void testWriteValue() throws Exception { + AnnotationBo bo = new AnnotationBo(); + bo.setKey(AnnotationKey.API.getCode()); + bo.setByteValue("value".getBytes("UTF-8")); +// int bufferSize = bo.getBufferSize(); + + Buffer buffer = new AutomaticBuffer(128); + bo.writeValue(buffer); + + AnnotationBo bo2 = new AnnotationBo(); + buffer.setOffset(0); + bo2.readValue(buffer); + Assert.assertEquals(bo.getKey(), bo2.getKey()); + Assert.assertEquals(bo.getValueType(), bo2.getValueType()); + Assert.assertArrayEquals(bo.getByteValue(), bo2.getByteValue()); + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/bo/SpanBoTest.java b/src/test/java/com/nhn/pinpoint/common/bo/SpanBoTest.java new file mode 100644 index 000000000..bed9f0093 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/bo/SpanBoTest.java @@ -0,0 +1,111 @@ +package com.nhn.pinpoint.common.bo; + + +import com.nhn.pinpoint.common.ServiceType; +import junit.framework.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author emeroad + */ +public class SpanBoTest { + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void testVersion() { + SpanBo spanBo = new SpanBo(); + check(spanBo, 0); + check(spanBo, 254); + check(spanBo, 255); + try { + check(spanBo, 256); + Assert.fail(); + } catch (Exception e) { + } + + + } + + private void check(SpanBo spanBo, int v) { + spanBo.setVersion(v); + int version = spanBo.getVersion(); + + Assert.assertEquals(v, version); + } + + @Test + public void serialize() { + SpanBo spanBo = new SpanBo(); + spanBo.setAgentId("agentId"); + spanBo.setApplicationId("applicationId"); + spanBo.setEndPoint("end"); + spanBo.setRpc("rpc"); + + spanBo.setParentSpanId(5); + + spanBo.setAgentStartTime(1); + spanBo.setTraceAgentStartTime(2); + spanBo.setTraceTransactionSequence(3); + spanBo.setElapsed(4); + spanBo.setStartTime(5); + + + spanBo.setServiceType(ServiceType.BLOC); + byte[] bytes = spanBo.writeValue(); + logger.info("length:{}", bytes.length); + + SpanBo newSpanBo = new SpanBo(); + int i = newSpanBo.readValue(bytes, 0); + logger.info("length:{}", i); + Assert.assertEquals(bytes.length, i); + Assert.assertEquals(newSpanBo.getAgentId(), spanBo.getAgentId()); + Assert.assertEquals(newSpanBo.getApplicationId(), spanBo.getApplicationId()); + Assert.assertEquals(newSpanBo.getAgentStartTime(), spanBo.getAgentStartTime()); + Assert.assertEquals(newSpanBo.getElapsed(), spanBo.getElapsed()); + Assert.assertEquals(newSpanBo.getEndPoint(), spanBo.getEndPoint()); + Assert.assertEquals(newSpanBo.getErrCode(), spanBo.getErrCode()); + Assert.assertEquals(newSpanBo.getFlag(), spanBo.getFlag()); + +// 이건 serialize에서 안가져옴. +// Assert.assertEquals(newSpanBo.getTraceAgentStartTime(), spanBo.getTraceAgentStartTime()); +// Assert.assertEquals(newSpanBo.getTraceTransactionSequence(), spanBo.getTraceTransactionSequence()); + Assert.assertEquals(newSpanBo.getParentSpanId(), spanBo.getParentSpanId()); + + Assert.assertEquals(newSpanBo.getVersion(), spanBo.getVersion()); + + + } + + @Test + public void serialize2() { + SpanBo spanBo = new SpanBo(); + spanBo.setAgentId("agent"); + String service = createString(5); + spanBo.setApplicationId(service); + String endPoint = createString(127); + spanBo.setEndPoint(endPoint); + String rpc = createString(255); + spanBo.setRpc(rpc); + + spanBo.setServiceType(ServiceType.BLOC); + + byte[] bytes = spanBo.writeValue(); + logger.info("length:{}", bytes.length); + + SpanBo newSpanBo = new SpanBo(); + int i = newSpanBo.readValue(bytes, 0); + logger.info("length:{}", i); + Assert.assertEquals(bytes.length, i); + } + + private String createString(int size) { + StringBuilder sb = new StringBuilder(size); + for (int i = 0; i < size; i++) { + sb.append('a'); + } + return sb.toString(); + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/bo/SpanEventBoTest.java b/src/test/java/com/nhn/pinpoint/common/bo/SpanEventBoTest.java new file mode 100644 index 000000000..eaa72b4be --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/bo/SpanEventBoTest.java @@ -0,0 +1,67 @@ +package com.nhn.pinpoint.common.bo; + +import com.nhn.pinpoint.common.ServiceType; +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class SpanEventBoTest { + + @Test + public void testSerialize() throws Exception { + SpanEventBo spanEventBo = new SpanEventBo(); + spanEventBo.setAgentId("test"); + spanEventBo.setAgentStartTime(1); + spanEventBo.setDepth(3); + spanEventBo.setDestinationId("testdest"); + spanEventBo.setEndElapsed(2); + spanEventBo.setEndPoint("endpoint"); + + spanEventBo.setNextSpanId(4); + spanEventBo.setRpc("rpc"); + + spanEventBo.setServiceType(ServiceType.TOMCAT); + spanEventBo.setSpanId(12); + spanEventBo.setStartElapsed(100); + + byte[] bytes = spanEventBo.writeValue(); + + SpanEventBo newSpanEventBo = new SpanEventBo(); + int i = newSpanEventBo.readValue(bytes, 0); + Assert.assertEquals(bytes.length, i); + + + Assert.assertEquals(spanEventBo.getAgentId(), newSpanEventBo.getAgentId()); + Assert.assertEquals(spanEventBo.getAgentStartTime(), newSpanEventBo.getAgentStartTime()); + Assert.assertEquals(spanEventBo.getDepth(), newSpanEventBo.getDepth()); + Assert.assertEquals(spanEventBo.getDestinationId(), newSpanEventBo.getDestinationId()); + Assert.assertEquals(spanEventBo.getEndElapsed(), newSpanEventBo.getEndElapsed()); + Assert.assertEquals(spanEventBo.getEndPoint(), newSpanEventBo.getEndPoint()); + + + Assert.assertEquals(spanEventBo.getNextSpanId(), newSpanEventBo.getNextSpanId()); + Assert.assertEquals(spanEventBo.getRpc(), newSpanEventBo.getRpc()); + Assert.assertEquals(spanEventBo.getServiceType(), newSpanEventBo.getServiceType()); + Assert.assertEquals(spanEventBo.getStartElapsed(), newSpanEventBo.getStartElapsed()); + + + // 아래는 rowKeye에서 가져 오는값. + spanEventBo.setSpanId(1); + newSpanEventBo.setSpanId(1); + Assert.assertEquals(spanEventBo.getSpanId(), newSpanEventBo.getSpanId()); + + spanEventBo.setTraceTransactionSequence(1); + newSpanEventBo.setTraceTransactionSequence(1); + Assert.assertEquals(spanEventBo.getTraceTransactionSequence(), newSpanEventBo.getTraceTransactionSequence()); + + spanEventBo.setTraceAgentStartTime(3); + newSpanEventBo.setTraceAgentStartTime(3); + Assert.assertEquals(spanEventBo.getTraceAgentStartTime(), newSpanEventBo.getTraceAgentStartTime()); + + spanEventBo.setSequence((short) 3); + newSpanEventBo.setSequence((short) 3); + Assert.assertEquals(spanEventBo.getSequence(), newSpanEventBo.getSequence()); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/buffer/AutomaticBufferTest.java b/src/test/java/com/nhn/pinpoint/common/buffer/AutomaticBufferTest.java new file mode 100644 index 000000000..516a96bd1 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/buffer/AutomaticBufferTest.java @@ -0,0 +1,294 @@ +package com.nhn.pinpoint.common.buffer; + +import com.nhn.pinpoint.common.util.BytesUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.Charset; +import java.util.Random; + +/** + * @author emeroad + */ +public class AutomaticBufferTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private Random random = new Random(); + + @Test + public void testPutPrefixedBytes() throws Exception { + Buffer buffer = new AutomaticBuffer(0); + buffer.put(1); + byte[] buf = buffer.getBuffer(); + Assert.assertEquals(buf.length, 4); + Assert.assertEquals(1, BytesUtils.bytesToInt(buf, 0)); + } + + + @Test + public void testPadBytes() throws Exception { + int TOTAL_LENGTH = 20; + int TEST_SIZE = 10; + int PAD_SIZE = TOTAL_LENGTH - TEST_SIZE; + Buffer buffer = new AutomaticBuffer(10); + byte[] test = new byte[10]; + + random.nextBytes(test); + + buffer.putPadBytes(test, TOTAL_LENGTH); + + byte[] result = buffer.getBuffer(); + junit.framework.Assert.assertEquals(result.length, TOTAL_LENGTH); + junit.framework.Assert.assertTrue("check data", Bytes.equals(test, 0, TEST_SIZE, result, 0, TEST_SIZE)); + byte[] padBytes = new byte[TOTAL_LENGTH - TEST_SIZE]; + junit.framework.Assert.assertTrue("check pad", Bytes.equals(padBytes, 0, TEST_SIZE, result, TEST_SIZE, PAD_SIZE)); + + } + + @Test + public void testPadBytes_Error() throws Exception { + + Buffer buffer1_1 = new AutomaticBuffer(32); + try { + buffer1_1.putPadBytes(new byte[11], 10); + } catch (Exception e) { + } + + Buffer buffer1_2 = new AutomaticBuffer(32); + try { + buffer1_2.putPadBytes(new byte[20], 10); + junit.framework.Assert.fail("error"); + } catch (Exception e) { + } + + Buffer buffer2 = new AutomaticBuffer(32); + buffer2.putPadBytes(new byte[10], 10); + + + Buffer buffer3 = new AutomaticBuffer(5); + buffer3.putPadBytes(new byte[10], 10); + } + + + @Test + public void testPadString() throws Exception { + int TOTAL_LENGTH = 20; + int TEST_SIZE = 10; + int PAD_SIZE = TOTAL_LENGTH - TEST_SIZE; + Buffer buffer = new AutomaticBuffer(32); + String test = StringUtils.repeat('a', TEST_SIZE); + + buffer.putPadString(test, TOTAL_LENGTH); + + byte[] result = buffer.getBuffer(); + String decodedString = new String(result); + String trimString = decodedString.trim(); + junit.framework.Assert.assertEquals(result.length, TOTAL_LENGTH); + + junit.framework.Assert.assertEquals("check data", test, trimString); + + String padString = new String(result, TOTAL_LENGTH - TEST_SIZE, PAD_SIZE, "UTF-8"); + byte[] padBytes = new byte[TOTAL_LENGTH - TEST_SIZE]; + junit.framework.Assert.assertEquals("check pad", padString, new String(padBytes, Charset.forName("UTF-8"))); + + } + + @Test + public void testPadString_Error() throws Exception { + + Buffer buffer1_1 = new AutomaticBuffer(32); + try { + buffer1_1.putPadString(StringUtils.repeat('a', 11), 10); + } catch (Exception e) { + } + + Buffer buffer1_2 = new AutomaticBuffer(32); + try { + buffer1_2.putPadString(StringUtils.repeat('a', 20), 10); + junit.framework.Assert.fail("error"); + } catch (Exception e) { + } + + Buffer buffer2 = new AutomaticBuffer(32); + buffer2.putPadString(StringUtils.repeat('a', 10), 10); + + Buffer buffer3 = new AutomaticBuffer(5); + buffer3.putPadString(StringUtils.repeat('a', 10), 10); + } + + @Test + public void testPut2PrefixedBytes() throws Exception { + byte[] bytes1 = new byte[2]; + checkPut2PrefixedBytes(bytes1); + + byte[] bytes2 = new byte[0]; + checkPut2PrefixedBytes(bytes2); + + byte[] bytes3 = new byte[Short.MAX_VALUE]; + checkPut2PrefixedBytes(bytes3); + + checkPut2PrefixedBytes(null); + + try { + byte[] bytes4 = new byte[Short.MAX_VALUE+1]; + checkPut2PrefixedBytes(bytes4); + Assert.fail("too large bytes"); + } catch (Exception e) { + } + } + + private void checkPut2PrefixedBytes(byte[] bytes) { + Buffer buffer = new AutomaticBuffer(0); + buffer.put2PrefixedBytes(bytes); + + Buffer copy = new FixedBuffer(buffer.getBuffer()); + Assert.assertArrayEquals(bytes, copy.read2PrefixedBytes()); + } + + @Test + public void testPut4PrefixedBytes() throws Exception { + byte[] bytes1 = new byte[2]; + checkPut4PrefixedBytes(bytes1); + + byte[] bytes2 = new byte[0]; + checkPut4PrefixedBytes(bytes2); + + checkPut4PrefixedBytes(null); + + } + + private void checkPut4PrefixedBytes(byte[] bytes) { + Buffer buffer = new AutomaticBuffer(0); + buffer.put4PrefixedBytes(bytes); + + Buffer copy = new FixedBuffer(buffer.getBuffer()); + Assert.assertArrayEquals(bytes, copy.read4PrefixedBytes()); + } + + @Test + public void testPutPrefixedBytesCheckRange() throws Exception { + Buffer buffer = new AutomaticBuffer(1); + buffer.putPrefixedString(null); + byte[] internalBuffer = buffer.getInternalBuffer(); + // 상속 관계에 의해서 강제로 버퍼 사이즈를 늘어나지 않아도 되는데 사이즈가 늘어남. + Assert.assertEquals(1, internalBuffer.length); + } + + + + @Test + public void testCurrentTime() throws InterruptedException { + Buffer buffer = new AutomaticBuffer(32); + + long l = System.currentTimeMillis(); + buffer.putSVar(l); + logger.trace("currentTime size:{}", buffer.getOffset()); + buffer.setOffset(0); + Assert.assertEquals(buffer.readSVarLong(), l); + + + } + + @Test + public void testPutVarInt() throws Exception { + Buffer buffer = new AutomaticBuffer(0); + buffer.putVar(Integer.MAX_VALUE); + buffer.putVar(Integer.MIN_VALUE); + buffer.putVar(0); + buffer.putVar(1); + buffer.putVar(12345); + + buffer.setOffset(0); + Assert.assertEquals(buffer.readVarInt(), Integer.MAX_VALUE); + Assert.assertEquals(buffer.readVarInt(), Integer.MIN_VALUE); + Assert.assertEquals(buffer.readVarInt(), 0); + Assert.assertEquals(buffer.readVarInt(), 1); + Assert.assertEquals(buffer.readVarInt(), 12345); + } + + @Test + public void testPutVarLong() throws Exception { + Buffer buffer = new AutomaticBuffer(0); + buffer.putVar(Long.MAX_VALUE); + buffer.putVar(Long.MIN_VALUE); + buffer.putVar(0L); + buffer.putVar(1L); + buffer.putVar(12345L); + + buffer.setOffset(0); + Assert.assertEquals(buffer.readVarLong(), Long.MAX_VALUE); + Assert.assertEquals(buffer.readVarLong(), Long.MIN_VALUE); + Assert.assertEquals(buffer.readVarLong(), 0L); + Assert.assertEquals(buffer.readVarLong(), 1L); + Assert.assertEquals(buffer.readVarLong(), 12345L); + } + + @Test + public void testPutSVarLong() throws Exception { + Buffer buffer = new AutomaticBuffer(32); + buffer.putSVar(Long.MAX_VALUE); + buffer.putSVar(Long.MIN_VALUE); + buffer.putSVar(0L); + buffer.putSVar(1L); + buffer.putSVar(12345L); + + buffer.setOffset(0); + Assert.assertEquals(buffer.readSVarLong(), Long.MAX_VALUE); + Assert.assertEquals(buffer.readSVarLong(), Long.MIN_VALUE); + Assert.assertEquals(buffer.readSVarLong(), 0L); + Assert.assertEquals(buffer.readSVarLong(), 1L); + Assert.assertEquals(buffer.readSVarLong(), 12345L); + } + + @Test + public void testPutSVarInt() throws Exception { + Buffer buffer = new AutomaticBuffer(32); + buffer.putSVar(Integer.MAX_VALUE); + buffer.putSVar(Integer.MIN_VALUE); + buffer.putSVar(0); + buffer.putSVar(1); + buffer.putSVar(12345); + + buffer.setOffset(0); + Assert.assertEquals(buffer.readSVarInt(), Integer.MAX_VALUE); + Assert.assertEquals(buffer.readSVarInt(), Integer.MIN_VALUE); + Assert.assertEquals(buffer.readSVarInt(), 0); + Assert.assertEquals(buffer.readSVarInt(), 1); + Assert.assertEquals(buffer.readSVarInt(), 12345); + } + + @Test + public void testPut() throws Exception { + Buffer buffer = new AutomaticBuffer(0); + buffer.put(1); + buffer.put(1L); + buffer.putPrefixedBytes(new byte[10]); + buffer.put((byte)1); + + + } + + @Ignore + @Test + public void testUdp() throws Exception { + // Signature:Header{signature=85, version=100, type=28704} + Buffer buffer = new AutomaticBuffer(10); + buffer.put((byte)85); + buffer.put((byte) 100); + buffer.put((short)28704); + + Buffer read = new FixedBuffer(buffer.getBuffer()); + logger.info("{}", (char)read.readByte()); + logger.info("{}", (char)read.readByte()); + logger.info("{}", (char)read.readByte()); + logger.info("{}", (char)read.readByte()); + + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/buffer/FixedBufferTest.java b/src/test/java/com/nhn/pinpoint/common/buffer/FixedBufferTest.java new file mode 100644 index 000000000..f5b1ba7f9 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/buffer/FixedBufferTest.java @@ -0,0 +1,444 @@ +package com.nhn.pinpoint.common.buffer; + +import com.nhn.pinpoint.common.util.BytesUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Random; + +/** + * @author emeroad + */ +public class FixedBufferTest { + private Logger logger = LoggerFactory.getLogger(this.getClass()); + + private Random random = new Random(); + + @Test + public void testPutPrefixedBytes() throws Exception { + String test = "test"; + int endExpected = 3333; + testPutPrefixedBytes(test, endExpected); + testPutPrefixedBytes(null, endExpected); + testPutPrefixedBytes("", endExpected); + } + + private void testPutPrefixedBytes(String test, int expected) throws UnsupportedEncodingException { + Buffer buffer = new FixedBuffer(1024); + if (test != null) { + buffer.putPrefixedBytes(test.getBytes("UTF-8")); + } else { + buffer.putPrefixedString(null); + } + + buffer.put(expected); + byte[] buffer1 = buffer.getBuffer(); + + Buffer actual = new FixedBuffer(buffer1); + String s = actual.readPrefixedString(); + Assert.assertEquals(test, s); + + int i = actual.readInt(); + Assert.assertEquals(expected, i); + } + + @Test + public void testPadBytes() throws Exception { + int TOTAL_LENGTH = 20; + int TEST_SIZE = 10; + int PAD_SIZE = TOTAL_LENGTH - TEST_SIZE; + Buffer buffer = new FixedBuffer(32); + byte[] test = new byte[10]; + + random.nextBytes(test); + + buffer.putPadBytes(test, TOTAL_LENGTH); + + byte[] result = buffer.getBuffer(); + Assert.assertEquals(result.length, TOTAL_LENGTH); + Assert.assertTrue("check data", Bytes.equals(test, 0, TEST_SIZE, result, 0, TEST_SIZE)); + byte[] padBytes = new byte[TOTAL_LENGTH - TEST_SIZE]; + Assert.assertTrue("check pad", Bytes.equals(padBytes, 0, TEST_SIZE, result, TEST_SIZE, PAD_SIZE)); + + } + + @Test + public void readPadBytes() { + byte[] bytes = new byte[10]; + random.nextBytes(bytes); + Buffer writeBuffer = new FixedBuffer(32); + writeBuffer.putPadBytes(bytes, 20); + writeBuffer.put(255); + + Buffer readBuffer = new FixedBuffer(writeBuffer.getBuffer()); + byte[] readPadBytes = readBuffer.readPadBytes(20); + Assert.assertArrayEquals(bytes, Arrays.copyOf(readPadBytes, 10)); + int readInt = readBuffer.readInt(); + Assert.assertEquals(255, readInt); + } + + + @Test + public void testPadBytes_Error() throws Exception { + + Buffer buffer1_1 = new FixedBuffer(32); + try { + buffer1_1.putPadBytes(new byte[11], 10); + } catch (Exception e) { + } + + Buffer buffer1_2 = new FixedBuffer(32); + try { + buffer1_2.putPadBytes(new byte[20], 10); + Assert.fail("error"); + } catch (Exception e) { + } + + Buffer buffer2 = new FixedBuffer(32); + buffer2.putPadBytes(new byte[10], 10); + + } + + @Test + public void testPadString() throws Exception { + int TOTAL_LENGTH = 20; + int TEST_SIZE = 10; + int PAD_SIZE = TOTAL_LENGTH - TEST_SIZE; + Buffer buffer= new FixedBuffer(32); + String test = StringUtils.repeat('a', TEST_SIZE); + + buffer.putPadString(test, TOTAL_LENGTH); + + byte[] result = buffer.getBuffer(); + String decodedString = new String(result); + String trimString = decodedString.trim(); + Assert.assertEquals(result.length, TOTAL_LENGTH); + + Assert.assertEquals("check data", test, trimString); + + String padString = new String(result, TOTAL_LENGTH - TEST_SIZE, PAD_SIZE, "UTF-8"); + byte[] padBytes = new byte[TOTAL_LENGTH - TEST_SIZE]; + Assert.assertEquals("check pad", padString, new String(padBytes, Charset.forName("UTF-8"))); + + } + + @Test + public void readPadString() { + String testString = StringUtils.repeat('a', 10); + Buffer writeBuffer = new FixedBuffer(32); + writeBuffer.putPadString(testString, 20); + writeBuffer.put(255); + + Buffer readBuffer = new FixedBuffer(writeBuffer.getBuffer()); + String readPadString = readBuffer.readPadString(20); + Assert.assertEquals(testString, readPadString.substring(0, 10)); + int readInt = readBuffer.readInt(); + Assert.assertEquals(255, readInt); + } + + @Test + public void readPadStringAndRightTrim() { + String testString = StringUtils.repeat('a', 10); + Buffer writeBuffer = new FixedBuffer(32); + writeBuffer.putPadString(testString, 20); + writeBuffer.put(255); + + Buffer readBuffer = new FixedBuffer(writeBuffer.getBuffer()); + String readPadString = readBuffer.readPadStringAndRightTrim(20); + Assert.assertEquals(testString, readPadString); + int readInt = readBuffer.readInt(); + Assert.assertEquals(255, readInt); + } + + @Test + public void testPadString_Error() throws Exception { + + Buffer buffer1_1 = new FixedBuffer(32); + try { + buffer1_1.putPadString(StringUtils.repeat('a', 11), 10); + } catch (Exception e) { + } + + Buffer buffer1_2 = new FixedBuffer(32); + try { + buffer1_2.putPadString(StringUtils.repeat('a', 20), 10); + Assert.fail("error"); + } catch (Exception e) { + } + + Buffer buffer2 = new FixedBuffer(32); + buffer2.putPadString(StringUtils.repeat('a', 10), 10); + } + + @Test + public void testPut2PrefixedBytes() throws Exception { + String test = "test"; + int endExpected = 3333; + + checkPut2PrefixedBytes(test, endExpected); + checkPut2PrefixedBytes(null, endExpected); + checkPut2PrefixedBytes("", endExpected); + + byte[] bytes = new byte[Short.MAX_VALUE]; + checkPut2PrefixedBytes(BytesUtils.toString(bytes), endExpected, Short.MAX_VALUE * 2); + + try { + byte[] bytes2 = new byte[Short.MAX_VALUE + 1]; + checkPut2PrefixedBytes(BytesUtils.toString(bytes2), endExpected, Short.MAX_VALUE * 2); + Assert.fail("too large bytes"); + } catch (Exception e) { + } + + } + + private void checkPut2PrefixedBytes(String test, int expected) throws UnsupportedEncodingException { + checkPut2PrefixedBytes(test, expected, 1024); + } + + private void checkPut2PrefixedBytes(String test, int expected, int bufferSize) throws UnsupportedEncodingException { + Buffer buffer = new FixedBuffer(bufferSize); + if (test != null) { + buffer.put2PrefixedBytes(test.getBytes("UTF-8")); + } else { + buffer.put2PrefixedBytes(null); + } + + buffer.put(expected); + byte[] buffer1 = buffer.getBuffer(); + + Buffer actual = new FixedBuffer(buffer1); + String s = actual.read2PrefixedString(); + Assert.assertEquals(test, s); + + int i = actual.readInt(); + Assert.assertEquals(expected, i); + } + + @Test + public void testPut4PrefixedBytes() throws Exception { + String test = "test"; + int endExpected = 3333; + + checkPut4PrefixedBytes(test, endExpected); + checkPut4PrefixedBytes(null, endExpected); + checkPut4PrefixedBytes("", endExpected); + + } + + private void checkPut4PrefixedBytes(String test, int expected) throws UnsupportedEncodingException { + Buffer buffer = new FixedBuffer(1024); + if (test != null) { + buffer.put4PrefixedBytes(test.getBytes("UTF-8")); + } else { + buffer.put4PrefixedBytes(null); + } + + buffer.put(expected); + byte[] buffer1 = buffer.getBuffer(); + + Buffer actual = new FixedBuffer(buffer1); + String s = actual.read4PrefixedString(); + Assert.assertEquals(test, s); + + int i = actual.readInt(); + Assert.assertEquals(expected, i); + } + + @Test + public void testReadByte() throws Exception { + + } + + @Test + public void testReadBoolean() throws Exception { + + } + + @Test + public void testReadInt() throws Exception { + + } + + @Test + public void testReadLong() throws Exception { + + } + + + + + @Test + public void testReadPrefixedString() throws Exception { + + } + + @Test + public void testRead4PrefixedString() throws Exception { + String value = "test"; + byte[] length = Bytes.toBytes(value.length()); + byte[] string = Bytes.toBytes(value); + byte[] result = Bytes.add(length, string); + + + Buffer buffer = new FixedBuffer(result); + String prefixedString = buffer.read4PrefixedString(); + Assert.assertEquals(prefixedString, value); + + } + + @Test + public void testRead4PrefixedString_Null() throws Exception { + byte[] length = Bytes.toBytes(-1); + + + Buffer buffer = new FixedBuffer(length); + String prefixedString = buffer.read4PrefixedString(); + Assert.assertEquals(prefixedString, null); + + } + + @Test + public void testPut() throws Exception { + checkUnsignedByte(255); + + checkUnsignedByte(0); + } + + @Test + public void testPutVar32() throws Exception { + checkVarInt(Integer.MAX_VALUE, 5); + checkVarInt(25, 1); + checkVarInt(100, 1); + + checkVarInt(Integer.MIN_VALUE, 10); + + checkVarInt(0, -1); + checkVarInt(Integer.MAX_VALUE / 2, -1); + checkVarInt(Integer.MAX_VALUE / 10, -1); + checkVarInt(Integer.MAX_VALUE / 10000, -1); + + checkVarInt(Integer.MIN_VALUE / 2, -1); + checkVarInt(Integer.MIN_VALUE / 10, -1); + checkVarInt(Integer.MIN_VALUE / 10000, -1); + + } + + private void checkVarInt(int v, int offset) { + Buffer buffer = new FixedBuffer(32); + buffer.putVar(v); + if (offset != -1) { + Assert.assertEquals(buffer.getOffset(), offset); + } else { + logger.info("{} offsetSize:{}", v, buffer.getOffset()); + } + buffer.setOffset(0); + int readV = buffer.readVarInt(); + Assert.assertEquals(readV, v); + } + + @Test + public void testPutSVar32() throws Exception { + // 63이 1바이트 경계. + checkSVarInt(63, -1); + // 8191이 2바이트 경계 + checkSVarInt((1024*8)-1, -1); + + checkSVarInt(3, -1); + + checkSVarInt(Integer.MAX_VALUE, 5); + + checkSVarInt(Integer.MIN_VALUE, 5); + + checkSVarInt(0, -1); + checkSVarInt(Integer.MAX_VALUE / 2, -1); + checkSVarInt(Integer.MAX_VALUE / 10, -1); + checkSVarInt(Integer.MAX_VALUE / 10000, -1); + + checkSVarInt(Integer.MIN_VALUE / 2, -1); + checkSVarInt(Integer.MIN_VALUE / 10, -1); + checkSVarInt(Integer.MIN_VALUE / 10000, -1); + + + } + + private void checkSVarInt(int v, int offset) { + Buffer buffer = new FixedBuffer(32); + buffer.putSVar(v); + if (offset != -1) { + Assert.assertEquals(buffer.getOffset(), offset); + } else { + logger.info("{} offsetSize:{}", v, buffer.getOffset()); + } + buffer.setOffset(0); + int readV = buffer.readSVarInt(); + Assert.assertEquals(readV, v); + } + + @Test + public void testPutVar64() throws Exception { + + } + + private void checkUnsignedByte(int value) { + Buffer buffer = new FixedBuffer(1024); + buffer.put((byte) value); + byte[] buffer1 = buffer.getBuffer(); + + Buffer reader = new FixedBuffer(buffer1); + int i = reader.readUnsignedByte(); + Assert.assertEquals(value, i); + } + + + @Test + public void testGetBuffer() throws Exception { + Buffer buffer = new FixedBuffer(4); + buffer.put(1); + Assert.assertEquals(buffer.getOffset(), 4); + Assert.assertEquals(buffer.getBuffer().length, 4); + } + + @Test + public void testSliceGetBuffer() throws Exception { + Buffer buffer = new FixedBuffer(5); + buffer.put(1); + Assert.assertEquals(buffer.getOffset(), 4); + Assert.assertEquals(buffer.getBuffer().length, 4); + + byte[] buffer1 = buffer.getBuffer(); + byte[] buffer2 = buffer.getBuffer(); + Assert.assertTrue(buffer1 != buffer2); + + } + + @Test + public void testBoolean() { + Buffer buffer = new FixedBuffer(16); + buffer.put(true); + buffer.put(false); + + Buffer read = new FixedBuffer(buffer.getBuffer()); + boolean b = read.readBoolean(); + Assert.assertEquals(true, b); + + boolean c = read.readBoolean(); + Assert.assertEquals(false, c); + } + + @Test + public void testGetOffset() throws Exception { + Buffer buffer = new FixedBuffer(); + Assert.assertEquals(buffer.getOffset(), 0); + + buffer.put(4); + Assert.assertEquals(buffer.getOffset(), 4); + + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/buffer/OffsetAutomaticBufferTest.java b/src/test/java/com/nhn/pinpoint/common/buffer/OffsetAutomaticBufferTest.java new file mode 100644 index 000000000..ff7eebde4 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/buffer/OffsetAutomaticBufferTest.java @@ -0,0 +1,22 @@ +package com.nhn.pinpoint.common.buffer; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class OffsetAutomaticBufferTest { + @Test + public void testGetBuffer() throws Exception { + final int putValue = 10; + Buffer buffer = new OffsetAutomaticBuffer(new byte[10], 2); + buffer.put(putValue); + byte[] intBuffer = buffer.getBuffer(); + Assert.assertEquals(intBuffer.length, 4); + + Buffer read = new FixedBuffer(intBuffer); + int value = read.readInt(); + Assert.assertEquals(putValue, value); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/buffer/OffsetFixedBufferTest.java b/src/test/java/com/nhn/pinpoint/common/buffer/OffsetFixedBufferTest.java new file mode 100644 index 000000000..b4e21e8b7 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/buffer/OffsetFixedBufferTest.java @@ -0,0 +1,38 @@ +package com.nhn.pinpoint.common.buffer; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class OffsetFixedBufferTest { + + @Test + public void testFixedBuffer() throws Exception { + new OffsetFixedBuffer(new byte[10], 10); + try { + new OffsetFixedBuffer(new byte[10], 11); + Assert.fail(); + } catch (Exception e) { + } + try { + new OffsetFixedBuffer(new byte[10], -1); + Assert.fail(); + } catch (Exception e) { + } + } + + @Test + public void testGetBuffer() throws Exception { + final int putValue = 10; + Buffer buffer = new OffsetFixedBuffer(new byte[10], 2); + buffer.put(putValue); + byte[] intBuffer = buffer.getBuffer(); + Assert.assertEquals(intBuffer.length, 4); + + Buffer read = new FixedBuffer(intBuffer); + int value = read.readInt(); + Assert.assertEquals(putValue, value); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/hbase/HbaseTemplate2Test.java b/src/test/java/com/nhn/pinpoint/common/hbase/HbaseTemplate2Test.java new file mode 100644 index 000000000..6658d093b --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/hbase/HbaseTemplate2Test.java @@ -0,0 +1,70 @@ +package com.nhn.pinpoint.common.hbase; + +import com.nhn.pinpoint.common.util.PropertyUtils; +import junit.framework.Assert; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.TableNotFoundException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.hadoop.hbase.HbaseConfigurationFactoryBean; +import org.springframework.data.hadoop.hbase.HbaseSystemException; + +import java.io.IOException; +import java.util.Properties; + + +/** + * @author emeroad + */ +public class HbaseTemplate2Test { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private static HbaseConfigurationFactoryBean hbaseConfigurationFactoryBean; + + @BeforeClass + public static void beforeClass() throws IOException { + String path = HbaseTemplate2Test.class.getClassLoader().getResource("test-hbase.properties").getPath(); + Properties properties = PropertyUtils.readProperties(path); + + Configuration cfg = HBaseConfiguration.create(); + cfg.set("hbase.zookeeper.quorum", properties.getProperty("hbase.client.host")); + cfg.set("hbase.zookeeper.property.clientPort", properties.getProperty("hbase.client.port")); + hbaseConfigurationFactoryBean = new HbaseConfigurationFactoryBean(); + hbaseConfigurationFactoryBean.setConfiguration(cfg); + hbaseConfigurationFactoryBean.afterPropertiesSet(); + } + + @AfterClass + public static void afterClass() { + if (hbaseConfigurationFactoryBean != null) { + hbaseConfigurationFactoryBean.destroy(); + } + + } + + + @Test + public void notExist() throws Exception { + + HbaseTemplate2 hbaseTemplate2 = new HbaseTemplate2(); + hbaseTemplate2.setConfiguration(hbaseConfigurationFactoryBean.getObject()); + hbaseTemplate2.afterPropertiesSet(); + + try { + hbaseTemplate2.put("NOT_EXIST", new byte[0], "familyName".getBytes(), "columnName".getBytes(), new byte[0]); + Assert.fail("exceptions"); + } catch (HbaseSystemException e) { + if (!(e.getCause().getCause() instanceof TableNotFoundException)) { + Assert.fail("unexpected exception :" + e.getCause()); + } + } finally { + hbaseTemplate2.destroy(); + } + + + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/AnnotationTranscoderTest.java b/src/test/java/com/nhn/pinpoint/common/util/AnnotationTranscoderTest.java new file mode 100644 index 000000000..355a2df55 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/AnnotationTranscoderTest.java @@ -0,0 +1,146 @@ +package com.nhn.pinpoint.common.util; + + +import com.nhn.pinpoint.common.bo.IntStringValue; +import com.nhn.pinpoint.thrift.dto.TIntStringValue; +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TIOStreamTransport; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.ByteArrayOutputStream; +import java.util.Arrays; +import java.util.Date; + +/** + * @author emeroad + */ +public class AnnotationTranscoderTest { + + private Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + @Test + public void testDecode() throws Exception { + typeCode("test"); + typeCode(""); + typeCode("adfesdfsesdfsdfserfsdfsdfe"); + + typeCode(1); + typeCode(0); + typeCode(-1212); + + typeCode((short) 4); + typeCode((short) -124); + + typeCode(2L); + typeCode(-22342342L); + + typeCode(3f); + typeCode(123.3f); + + typeCode(4D); + typeCode(-124D); + + typeCode((byte) 4); + typeCode((byte) -14); + + typeCode(true); + typeCode(false); + + typeCode(null); + + typeUnsupportCode(new Date()); + + typeBinaryCode(new byte[]{12, 3, 4, 1, 23, 4, 1, 2, 3, 4, 4}); + + } + + private void typeCode(Object value) { + AnnotationTranscoder transcoder = new AnnotationTranscoder(); + + byte typeCode = transcoder.getTypeCode(value); + byte[] bytes = transcoder.encode(value, typeCode); + Object decode = transcoder.decode(typeCode, bytes); + + Assert.assertEquals(value, decode); + } + + private void typeUnsupportCode(Object value) { + AnnotationTranscoder transcoder = new AnnotationTranscoder(); + + byte typeCode = transcoder.getTypeCode(value); + byte[] bytes = transcoder.encode(value, typeCode); + Object decode = transcoder.decode(typeCode, bytes); + + Assert.assertEquals(value.toString(), decode.toString()); + } + + private void typeBinaryCode(byte[] value) { + AnnotationTranscoder transcoder = new AnnotationTranscoder(); + + byte typeCode = transcoder.getTypeCode(value); + byte[] bytes = transcoder.encode(value, typeCode); + Object decode = transcoder.decode(typeCode, bytes); + + Assert.assertArrayEquals(value, (byte[]) decode); + } + + @Test + public void testGetTypeCode() throws Exception { + int i = 2 << 8; + System.out.println(i); + write(i); + int j = 3 << 8; + System.out.println(j); + write(j); + write(10); + write(512); + write(256); + + + } + + @Test + public void testIntString() { + + testIntString(-1, ""); + testIntString(0, ""); + testIntString(1, ""); + testIntString(Integer.MAX_VALUE, "test"); + testIntString(Integer.MIN_VALUE, "test"); + + // null일때 0인자열로 생각하는 문제점이 있음. + testIntString(2, null); + } + + private void testIntString(int intValue, String stringValue) { + AnnotationTranscoder transcoder = new AnnotationTranscoder(); + TIntStringValue tIntStringValue = new TIntStringValue(intValue); + tIntStringValue.setStringValue(stringValue); + byte[] encode = transcoder.encode(tIntStringValue, AnnotationTranscoder.CODE_INT_STRING); + IntStringValue decode = (IntStringValue) transcoder.decode(AnnotationTranscoder.CODE_INT_STRING, encode); + Assert.assertEquals(tIntStringValue.getIntValue(), decode.getIntValue()); + Assert.assertEquals(tIntStringValue.getStringValue(), decode.getStringValue()); + } + + private void write(int value) throws TException { + TCompactProtocol.Factory factory = new TCompactProtocol.Factory(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(16); + TIOStreamTransport transport = new TIOStreamTransport(baos); + TProtocol protocol = factory.getProtocol(transport); + + protocol.writeI32(value); + byte[] buffer = baos.toByteArray(); + logger.info(Arrays.toString(buffer)); + } + + @Test + public void testEncode() throws Exception { + + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/ApiDescriptionParserTest.java b/src/test/java/com/nhn/pinpoint/common/util/ApiDescriptionParserTest.java new file mode 100644 index 000000000..4a7184247 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/ApiDescriptionParserTest.java @@ -0,0 +1,75 @@ +package com.nhn.pinpoint.common.util; + + +import org.junit.Assert; +import org.junit.Test; + + +/** + * @author emeroad + */ +public class ApiDescriptionParserTest { + private ApiDescriptionParser apiParser = new ApiDescriptionParser(); + + @Test + public void parse() { +// org.springframework.web.servlet.FrameworkServlet.doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) +// com.mysql.jdbc.ConnectionImpl.setAutoCommit(boolean autoCommitFlag) +// com.mysql.jdbc.ConnectionImpl.commit() +// org.apache.catalina.core.StandardHostValve.invoke(org.apache.catalina.connector.Request request, org.apache.catalina.connector.Response response):110 + String api = "a.StandardHostValve.invoke(b.Request request, b.Response response)"; + ApiDescription result = apiParser.parse(api); + + Assert.assertEquals("a.StandardHostValve", result.getClassName()); + Assert.assertEquals("StandardHostValve", result.getSimpleClassName()); + Assert.assertEquals("a", result.getPackageNameName()); + + Assert.assertEquals("invoke", result.getMethodName()); + + Assert.assertEquals("invoke(Request request, Response response)", result.getSimpleMethodDescription()); + Assert.assertEquals("StandardHostValve", result.getSimpleClassName()); + + Assert.assertArrayEquals(new String[]{"Request request", "Response response"}, result.getSimpleParameter()); + } + + + @Test + public void parseNoArgs() { + String api = "a.StandardHostValve.invoke()"; + ApiDescription result = apiParser.parse(api); + + Assert.assertEquals("a.StandardHostValve", result.getClassName()); + Assert.assertEquals("StandardHostValve", result.getSimpleClassName()); + Assert.assertEquals("a", result.getPackageNameName()); + + Assert.assertEquals("invoke", result.getMethodName()); + + Assert.assertEquals("invoke()", result.getSimpleMethodDescription()); + Assert.assertEquals("StandardHostValve", result.getSimpleClassName()); + + Assert.assertArrayEquals(new String[]{}, result.getSimpleParameter()); + } + + + @Test + public void parseNoPackage() { + + String api = "StandardHostValve.invoke(Request request, Response response)"; + ApiDescription result = apiParser.parse(api); + + Assert.assertEquals("StandardHostValve", result.getClassName()); + Assert.assertEquals("StandardHostValve", result.getSimpleClassName()); + Assert.assertEquals("", result.getPackageNameName()); + + Assert.assertEquals("invoke", result.getMethodName()); + + Assert.assertEquals("invoke(Request request, Response response)", result.getSimpleMethodDescription()); + Assert.assertEquals("StandardHostValve", result.getSimpleClassName()); + + Assert.assertArrayEquals(new String[]{"Request request", "Response response"}, result.getSimpleParameter()); + + } + + + +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/ApplicationMapStatisticsUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/ApplicationMapStatisticsUtilsTest.java new file mode 100644 index 000000000..5dff69f5e --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/ApplicationMapStatisticsUtilsTest.java @@ -0,0 +1,20 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; + +import org.junit.Test; + +public class ApplicationMapStatisticsUtilsTest { + + @Test + public void makeRowKey() { + String applicationName = "TESTAPP"; + short serviceType = 123; + long time = System.currentTimeMillis(); + + byte[] bytes = ApplicationMapStatisticsUtils.makeRowKey(applicationName, serviceType, time); + + Assert.assertEquals(applicationName, ApplicationMapStatisticsUtils.getApplicationNameFromRowKey(bytes)); + Assert.assertEquals(serviceType, ApplicationMapStatisticsUtils.getApplicationTypeFromRowKey(bytes)); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/ByteSizeTest.java b/src/test/java/com/nhn/pinpoint/common/util/ByteSizeTest.java new file mode 100644 index 000000000..1abe69d06 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/ByteSizeTest.java @@ -0,0 +1,36 @@ +package com.nhn.pinpoint.common.util; + +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TIOStreamTransport; +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** + * + */ +public class ByteSizeTest { + @Test + public void test() throws TException { + TCompactProtocol.Factory factory = new TCompactProtocol.Factory(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(16); + TIOStreamTransport transport = new TIOStreamTransport(baos); + TProtocol protocol = factory.getProtocol(transport); + + long l = TimeUnit.DAYS.toMillis(1); + System.out.println("day:" + l); + long currentTime = System.currentTimeMillis(); + System.out.println("currentTime:" + currentTime); + protocol.writeI64(l); + byte[] buffer = baos.toByteArray(); + System.out.println(buffer.length); + + } + + +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/BytesUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/BytesUtilsTest.java new file mode 100644 index 000000000..c09d78f28 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/BytesUtilsTest.java @@ -0,0 +1,187 @@ +package com.nhn.pinpoint.common.util; + +import java.util.Arrays; +import java.util.UUID; + +import org.apache.hadoop.hbase.util.Bytes; +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.transport.TMemoryBuffer; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class BytesUtilsTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void testLongLongToBytes() throws Exception { + long most = Long.MAX_VALUE; + long least = Long.MAX_VALUE - 1; + + test(most, least); + + UUID uuid = UUID.randomUUID(); + test(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + } + + @Test + public void testStringLongLongToBytes() throws Exception { + BytesUtils.stringLongLongToBytes("123", 3, 1, 2); + try { + BytesUtils.stringLongLongToBytes("123", 2, 1, 2); + Assert.fail(); + } catch (Exception e) { + } + } + + @Test + public void testStringLongLongToBytes2() throws Exception { + byte[] bytes = BytesUtils.stringLongLongToBytes("123", 10, 1, 2); + String s = BytesUtils.toStringAndRightTrim(bytes, 0, 10); + Assert.assertEquals("123", s); + long l = BytesUtils.bytesToLong(bytes, 10); + Assert.assertEquals(l, 1); + long l2 = BytesUtils.bytesToLong(bytes, 10 + BytesUtils.LONG_BYTE_LENGTH); + Assert.assertEquals(l2, 2); + } + + @Test + public void testRightTrim() throws Exception { + String trim = BytesUtils.trimRight("test "); + Assert.assertEquals("test", trim); + + String trim1 = BytesUtils.trimRight("test"); + Assert.assertEquals("test", trim1); + + String trim2 = BytesUtils.trimRight(" test"); + Assert.assertEquals(" test", trim2); + + } + + + @Test + public void testInt() { + int i = Integer.MAX_VALUE - 5; + checkInt(i); + checkInt(23464); + } + + private void checkInt(int i) { + byte[] bytes = Bytes.toBytes(i); + int i2 = BytesUtils.bytesToInt(bytes, 0); + Assert.assertEquals(i, i2); + int i3 = Bytes.toInt(bytes); + Assert.assertEquals(i, i3); + } + + private void test(long most, long least) { + byte[] bytes1 = Bytes.toBytes(most); + byte[] bytes2 = Bytes.toBytes(least); + byte[] add = Bytes.add(bytes1, bytes2); + byte[] bytes = BytesUtils.longLongToBytes(most, least); + Assert.assertArrayEquals(add, bytes); + + + long[] longLong = BytesUtils.bytesToLongLong(bytes); + Assert.assertEquals(most, longLong[0]); + Assert.assertEquals(least, longLong[1]); + + + long bMost = BytesUtils.bytesToLong(bytes, 0); + long bLeast = BytesUtils.bytesToLong(bytes, 8); + Assert.assertEquals(most, bMost); + Assert.assertEquals(least, bLeast); + + byte bBytes[] = new byte[16]; + BytesUtils.writeLong(most, bBytes, 0); + BytesUtils.writeLong(least, bBytes, 8); + Assert.assertArrayEquals(add, bBytes); + } + + @Test + public void testAddStringLong() throws Exception { + byte[] testAgents = BytesUtils.add("testAgent", 11L); + byte[] buf = Bytes.add(Bytes.toBytes("testAgent"), Bytes.toBytes(11L)); + Assert.assertArrayEquals(testAgents, buf); + } + + @Test + public void testAddStringLong_NullError() throws Exception { + try { + BytesUtils.add((String)null, 11L); + Assert.fail(); + } catch (Exception e) { + } + } + + @Test + public void testToFixedLengthBytes() { + byte[] testValue = BytesUtils.toFixedLengthBytes("test", 10); + Assert.assertEquals(testValue.length, 10); + Assert.assertEquals(testValue[5], 0); + + try { + BytesUtils.toFixedLengthBytes("test", 2); + Assert.fail(); + } catch (Exception e) { + } + + try { + BytesUtils.toFixedLengthBytes("test", -1); + Assert.fail(); + } catch (Exception e) { + } + + byte[] testValue2 = BytesUtils.toFixedLengthBytes(null, 10); + Assert.assertEquals(testValue2.length, 10); + + } + + @Test + public void testMerge() { + byte[] b1 = new byte[] { 1, 2 }; + byte[] b2 = new byte[] { 3, 4 }; + + byte[] b3 = BytesUtils.merge(b1, b2); + + Assert.assertTrue(Arrays.equals(new byte[] { 1, 2, 3, 4 }, b3)); + } + + @Test + public void testZigZag() throws Exception { + testEncodingDecodingZigZag(0); + testEncodingDecodingZigZag(1); + testEncodingDecodingZigZag(2); + testEncodingDecodingZigZag(3); + } + + + private void testEncodingDecodingZigZag(int value) { + int encode = BytesUtils.intToZigZag(value); + int decode = BytesUtils.zigzagToInt(encode); + Assert.assertEquals(value, decode); + } + + + @Test + public void compactProtocolVint() throws TException { + TMemoryBuffer tMemoryBuffer = writeVInt32(BytesUtils.zigzagToInt(64)); + logger.debug("length:{}", tMemoryBuffer.length()); + + TMemoryBuffer tMemoryBuffer2 = writeVInt32(64); + logger.debug("length:{}", tMemoryBuffer2.length()); + + } + + private TMemoryBuffer writeVInt32(int i) throws TException { + TMemoryBuffer tMemoryBuffer = new TMemoryBuffer(10); + TCompactProtocol tCompactProtocol = new TCompactProtocol(tMemoryBuffer); + tCompactProtocol.writeI32(i); + return tMemoryBuffer; + } + + +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/HashCodeTest.java b/src/test/java/com/nhn/pinpoint/common/util/HashCodeTest.java new file mode 100644 index 000000000..900e844de --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/HashCodeTest.java @@ -0,0 +1,121 @@ +package com.nhn.pinpoint.common.util; + +import org.junit.Test; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * test를 위해 hashcode를 찾을때 돌려볼수 있는 코드 + */ +public class HashCodeTest { + // @Test + public void test2() throws InterruptedException { +// "test" +// "tetU" +// "uGTt" +// System.out.println((int)'A'); +// System.out.println((int)'Z'); + System.out.println("test".hashCode()); + System.out.println("tfUU".hashCode()); + String a = "23 123"; + System.out.println(a.hashCode()); + System.out.println("test:" + a.hashCode()); + final int hashCode = a.hashCode(); + final ExecutorService es = Executors.newFixedThreadPool(4); + Runnable runnable = new Runnable() { + @Override + public void run() { + execute(hashCode); + } + }; + es.execute(runnable); + es.execute(runnable); + es.execute(runnable); + es.execute(runnable); + es.awaitTermination(1, TimeUnit.HOURS); +// execute(hashCode, random); +// test +// -1757224452 + + + } + + private void execute(int hashCode) { + Random random = new Random(); + while (true) { + int i = random.nextInt(30); +// System.out.println(i); + StringBuilder sb = new StringBuilder(); +// sb.append("12 "); + for (int j = 0; j < i; j++) { + char c = get(random); + sb.append(c); + } + sb.append(" 7"); + String s = sb.toString(); +// System.out.println(s.hashCode()); +// System.out.println(s); + if (hashCode == s.hashCode()) { +// if(a.equals(s)) { +// continue; +// } + System.out.println("find!!! equals:" + s); + break; + } + } + } + + // @Test + public void test() { +// "test" +// "tetU" +// "uGTt" +// System.out.println((int)'A'); +// System.out.println((int)'Z'); + String a = "test"; + System.out.println("test:" + a.hashCode()); + int hashCode = a.hashCode(); + Random random = new Random(); + while (true) { + int i = random.nextInt(50); +// System.out.println(i); + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < i; j++) { + char c = get(random); + sb.append(c); + } + String s = sb.toString(); +// System.out.println(s); + if (hashCode == s.hashCode()) { + if ("test".equals(s)) { + continue; + } + System.out.println("equals:" + s); + break; + } + } +// test +// -1757224452 + } + + char get(Random rand) { +// 65->90 : 25 +// 97->122; 25 + int choice = (char) rand.nextInt(2); + char ch; + if (choice == 0) { + ch = (char) ((rand.nextInt(25)) + 97); + } else { + ch = (char) ((rand.nextInt(25)) + 65); + } + + while (true) { + if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') { + return ch; + } + } + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/HttpUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/HttpUtilsTest.java new file mode 100644 index 000000000..93a04330c --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/HttpUtilsTest.java @@ -0,0 +1,39 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; + +public class HttpUtilsTest { + @Test + public void contentTypeCharset1() { + String test = "text/plain; charset=UTF-8"; + + String charset = HttpUtils.parseContentTypeCharset(test); + Assert.assertEquals("UTF-8", charset); + } + + @Test + public void contentTypeCharset2() { + String test = "text/plain; charset=UTF-8;"; + + String charset = HttpUtils.parseContentTypeCharset(test); + Assert.assertEquals("UTF-8", charset); + } + + @Test + public void contentTypeCharset3() { + String test = "text/plain; charset=UTF-8; test=a"; + + String charset = HttpUtils.parseContentTypeCharset(test); + Assert.assertEquals("UTF-8", charset); + } + + @Test + public void contentTypeCharset4() { + String test = "text/plain; charset= UTF-8 ; test=a"; + + String charset = HttpUtils.parseContentTypeCharset(test); + Assert.assertEquals("UTF-8", charset); + } + +} \ No newline at end of file diff --git a/src/test/java/com/nhn/pinpoint/common/util/InetAddressUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/InetAddressUtilsTest.java new file mode 100644 index 000000000..42da6f270 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/InetAddressUtilsTest.java @@ -0,0 +1,22 @@ +package com.nhn.pinpoint.common.util; + +import org.junit.Test; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * + */ +public class InetAddressUtilsTest { + @Test + public void test() throws UnknownHostException { + InetAddress byName = InetAddress.getByName("0:0:0:0:0:0:0:1"); + + System.out.println(byName); + System.out.println(byName.getAddress().length); + + InetAddress ipv4= InetAddress.getByName("127.0.0.1"); + System.out.println(ipv4); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/MathUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/MathUtilsTest.java new file mode 100644 index 000000000..d66113d9f --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/MathUtilsTest.java @@ -0,0 +1,47 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author emeroad + */ +public class MathUtilsTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void fastAbs() { + Assert.assertTrue(MathUtils.fastAbs(-1) > 0); + Assert.assertTrue(MathUtils.fastAbs(0) == 0); + Assert.assertTrue(MathUtils.fastAbs(1) > 0); + } + + + @Test + public void overflow() { + + + logger.debug("abs:{}", Math.abs(Integer.MIN_VALUE)); + logger.debug("fastabs:{}", MathUtils.fastAbs(Integer.MIN_VALUE)); + + int index = Integer.MIN_VALUE -2; + for(int i =0; i<5; i++) { + logger.debug("{}------------", i); + logger.debug("{}", index); + logger.debug("mod:{}", index % 3); + logger.debug("abs:{}", Math.abs(index)); + logger.debug("fastabs:{}", MathUtils.fastAbs(index)); + + index++; + } + + + + } + + +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/OutputParameterParserTest.java b/src/test/java/com/nhn/pinpoint/common/util/OutputParameterParserTest.java new file mode 100644 index 000000000..c3fbe0674 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/OutputParameterParserTest.java @@ -0,0 +1,45 @@ +package com.nhn.pinpoint.common.util; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * @author emeroad + */ +public class OutputParameterParserTest { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final OutputParameterParser parser = new OutputParameterParser(); + + @Test + public void testParseOutputParameter() throws Exception { + assertOutputParameter("12,34", "12", "34"); + assertOutputParameter("12,,34", "12,34"); + + assertOutputParameter("12,,", "12,"); + + assertOutputParameter("12,,34,123", "12,34", "123"); + + assertOutputParameter("12,", "12", ""); + + assertOutputParameter(""); + + } + + private void assertOutputParameter(String outputParam, String... params) { + List result = parser.parseOutputParameter(outputParam); + logger.info("parseResult:{}", result); + try { + Assert.assertArrayEquals(result.toArray(new String[result.size()]), params); + } catch (AssertionError e) { + logger.warn("parseResult:{}", result); + logger.warn("params:{}", params); + throw e; + } + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/PinpointThreadFactoryTest.java b/src/test/java/com/nhn/pinpoint/common/util/PinpointThreadFactoryTest.java new file mode 100644 index 000000000..2b8cd34aa --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/PinpointThreadFactoryTest.java @@ -0,0 +1,43 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author emeroad + */ +public class PinpointThreadFactoryTest { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Test + public void testCreateThreadFactory() throws Exception { + final AtomicInteger test = new AtomicInteger(0); + + PinpointThreadFactory pinpoint = new PinpointThreadFactory("pinpoint"); + Thread thread = pinpoint.newThread(new Runnable() { + @Override + public void run() { + test.getAndIncrement(); + } + }); + thread.start(); + thread.join(); + Assert.assertEquals(test.get(), 1); + String threadName = thread.getName(); + logger.info(threadName); + Assert.assertTrue(threadName.startsWith("pinpoint(")); + Assert.assertTrue(threadName.endsWith(")")); + + Thread thread2 = pinpoint.newThread(new Runnable() { + @Override + public void run() { + } + }); + logger.info(thread2.getName()); + + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/RowKeyUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/RowKeyUtilsTest.java new file mode 100644 index 000000000..94227c761 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/RowKeyUtilsTest.java @@ -0,0 +1,25 @@ +package com.nhn.pinpoint.common.util; + +import com.nhn.pinpoint.common.bo.SqlMetaDataBo; +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class RowKeyUtilsTest { + @Test + public void testGetSqlId() throws Exception { + long startTime = System.currentTimeMillis(); + SqlMetaDataBo sqlMetaDataBo = new SqlMetaDataBo("agent", startTime, 1); + byte[] agents = sqlMetaDataBo.toRowKey(); + + + SqlMetaDataBo sqlId = new SqlMetaDataBo(); + sqlId.readRowKey(agents); + + Assert.assertEquals(sqlId.getAgentId(), "agent"); + Assert.assertEquals(sqlId.getHashCode(), 1); + Assert.assertEquals(sqlId.getStartTime(), startTime); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/RpcCodeRangeTest.java b/src/test/java/com/nhn/pinpoint/common/util/RpcCodeRangeTest.java new file mode 100644 index 000000000..354e46921 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/RpcCodeRangeTest.java @@ -0,0 +1,17 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class RpcCodeRangeTest { + + @Test + public void testIsRpcRange() throws Exception { + Assert.assertTrue(RpcCodeRange.isRpcRange(RpcCodeRange.RPC_START)); + Assert.assertTrue(RpcCodeRange.isRpcRange((short) (RpcCodeRange.RPC_END - 1))); + Assert.assertFalse(RpcCodeRange.isRpcRange((short) 1)); + } + +} \ No newline at end of file diff --git a/src/test/java/com/nhn/pinpoint/common/util/SpanUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/SpanUtilsTest.java new file mode 100644 index 000000000..47d6b5b33 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/SpanUtilsTest.java @@ -0,0 +1,67 @@ +package com.nhn.pinpoint.common.util; + +import com.nhn.pinpoint.common.PinpointConstants; +import com.nhn.pinpoint.thrift.dto.TSpan; + +import junit.framework.Assert; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.Test; + +/** + * @author emeroad + */ +public class SpanUtilsTest { + @Test + public void testGetTraceIndexRowKeyWhiteSpace() throws Exception { + String agentId = "test test"; + long time = System.currentTimeMillis(); + check(agentId, time); + } + + @Test + public void testGetTraceIndexRowKey1() throws Exception { + String agentId = "test"; + long time = System.currentTimeMillis(); + check(agentId, time); + } + + @Test + public void testGetTraceIndexRowKey2() throws Exception { + String agentId = ""; + for (int i = 0; i < PinpointConstants.AGENT_NAME_MAX_LEN; i++) { + agentId += "1"; + } + + long time = System.currentTimeMillis(); + check(agentId, time); + } + + @Test + public void testGetTraceIndexRowKey3() throws Exception { + String agentId = ""; + for (int i = 0; i < PinpointConstants.AGENT_NAME_MAX_LEN + 1; i++) { + agentId += "1"; + } + + long time = System.currentTimeMillis(); + try { + check(agentId, time); + Assert.fail(); + } catch (Exception e) { + } + } + + private void check(String agentId0, long l1) { + TSpan span = new TSpan(); + span.setAgentId(agentId0); + span.setStartTime(l1); + + byte[] traceIndexRowKey = SpanUtils.getAgentIdTraceIndexRowKey(span.getAgentId(), span.getStartTime()); + + String agentId = Bytes.toString(traceIndexRowKey, 0, PinpointConstants.AGENT_NAME_MAX_LEN).trim(); + Assert.assertEquals(agentId0, agentId); + + long time = TimeUtils.recoveryTimeMillis(Bytes.toLong(traceIndexRowKey, PinpointConstants.AGENT_NAME_MAX_LEN)); + Assert.assertEquals(time, l1); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/SqlParserTest.java b/src/test/java/com/nhn/pinpoint/common/util/SqlParserTest.java new file mode 100644 index 000000000..c75bb9e16 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/SqlParserTest.java @@ -0,0 +1,305 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import junit.framework.AssertionFailedError; +import org.junit.Test; + +import java.util.List; + +/** + * @author emeroad + */ +public class SqlParserTest { + private SqlParser sqlParser = new SqlParser(); + private OutputParameterParser outputParameterParser = new OutputParameterParser(); + + @Test + public void normalizedSql() { + + ParsingResult parsingResult = sqlParser.normalizedSql("select * from table a = 1 and b=50 and c=? and d='11'"); + String s = parsingResult.getSql(); + + System.out.println(s); + System.out.println(parsingResult.getOutput()); + + ParsingResult parsingResult2 = sqlParser.normalizedSql(" "); + String s2 = parsingResult2.getSql(); + System.out.println(s2); + + System.out.println((char) -1); + String str = "s"; + System.out.println(str.codePointAt(0)); + System.out.println((int) str.charAt(0)); + System.out.println("high" + (char) Character.MAX_HIGH_SURROGATE); + System.out.println("low" + (char) Character.MIN_LOW_SURROGATE); + + System.out.println((int) Character.MIN_LOW_SURROGATE); + System.out.println((int) Character.MAX_HIGH_SURROGATE); + + ParsingResult parsingResult3 = sqlParser.normalizedSql("''"); + String s3 = parsingResult3.getSql(); + System.out.println("s3:" + s3); + System.out.println("sb3:" + parsingResult3.getOutput()); + } + + @Test + public void nullCheck() { + sqlParser.normalizedSql(null); + } + + @Test + public void complex() { + + assertEqual("select * from table a = 1 and b=50 and c=? and d='11'", + "select * from table a = 0# and b=1# and c=? and d='2$'", "1,50,11"); + + assertEqual("select * from table a = -1 and b=-50 and c=? and d='-11'", + "select * from table a = -0# and b=-1# and c=? and d='2$'", "1,50,-11"); + + assertEqual("select * from table a = +1 and b=+50 and c=? and d='+11'", + "select * from table a = +0# and b=+1# and c=? and d='2$'", "1,50,+11"); + + assertEqual("select * from table a = 1/*test*/ and b=50/*test*/ and c=? and d='11'", + "select * from table a = 0#/*test*/ and b=1#/*test*/ and c=? and d='2$'", "1,50,11"); + + assertEqual("select ZIPCODE,CITY from ZIPCODE"); + assertEqual("select a.ZIPCODE,a.CITY from ZIPCODE as a"); + assertEqual("select ZIPCODE,123 from ZIPCODE", + "select ZIPCODE,0# from ZIPCODE", "123"); + + assertEqual("SELECT * from table a=123 and b='abc' and c=1-3", + "SELECT * from table a=0# and b='1$' and c=2#-3#", "123,abc,1,3"); + + assertEqual("SYSTEM_RANGE(1, 10)", + "SYSTEM_RANGE(0#, 1#)", "1,10"); + + } + + @Test + public void etcState() { + + assertEqual("test.abc", "test.abc", ""); + assertEqual("test.abc123", "test.abc123", ""); + assertEqual("test.123", "test.123", ""); + + } + + @Test + public void objectEquals() { + + assertEqualObject("test.abc"); + assertEqualObject("test.abc123"); + assertEqualObject("test.123"); + + } + + + @Test + public void numberState() { + assertEqual("123", "0#", "123"); + // -가 진짜 숫자의 -인지 알려면 구문분석이 필요하므로 그냥 숫자만 치환한다. + assertEqual("-123", "-0#", "123"); + assertEqual("+123", "+0#", "123"); + assertEqual("1.23", "0#", "1.23"); + assertEqual("1.23.34", "0#", "1.23.34"); + assertEqual("123 456", "0# 1#", "123,456"); + assertEqual("1.23 4.56", "0# 1#", "1.23,4.56"); + assertEqual("1.23-4.56", "0#-1#", "1.23,4.56"); + + assertEqual("1<2", "0#<1#", "1,2"); + assertEqual("1< 2", "0#< 1#", "1,2"); + assertEqual("(1< 2)", "(0#< 1#)", "1,2"); + + assertEqual("-- 1.23", "-- 1.23", ""); + assertEqual("- -1.23", "- -0#", "1.23"); + assertEqual("--1.23", "--1.23", ""); + assertEqual("/* 1.23 */", "/* 1.23 */", ""); + assertEqual("/*1.23*/", "/*1.23*/", ""); + assertEqual("/* 1.23 \n*/", "/* 1.23 \n*/", ""); + + assertEqual("test123", "test123", ""); + assertEqual("test_123", "test_123", ""); + assertEqual("test_ 123", "test_ 0#", "123"); + + // 사실 이건 불가능한 토큰임. + assertEqual("123tst", "0#tst", "123"); + } + + @Test + public void numberState2() { + assertEqual("1.23e", "0#", "1.23e"); + assertEqual("1.23E", "0#", "1.23E"); + // -가 진짜 숫자의 -인지 알려면 구문분석이 필요하므로 그냥 숫자만 치환한다. + assertEqual("1.4e-10", "0#-1#", "1.4e,10"); + + } + + + @Test + public void singleLineCommentState() { + assertEqual("--", "--", ""); + assertEqual("//", "//", ""); + assertEqual("--123", "--123", ""); + assertEqual("//123", "//123", ""); + assertEqual("--test", "--test"); + assertEqual("//test", "//test"); + assertEqual("--test\ntest", "--test\ntest", ""); + assertEqual("--test\t\n", "--test\t\n", ""); + assertEqual("--test\n123 test", "--test\n0# test", "123"); + } + + + @Test + public void multiLineCommentState() { + assertEqual("/**/", "/**/", ""); + assertEqual("/* */", "/* */", ""); + assertEqual("/* */abc", "/* */abc", ""); + assertEqual("/* * */", "/* * */", ""); + assertEqual("/* * */", "/* * */", ""); + + assertEqual("/* abc", "/* abc", ""); + + assertEqual("select * from table", "select * from table", ""); + } + + @Test + public void symbolState() { + assertEqual("''", "''", ""); + assertEqual("'abc'", "'0$'", "abc"); + assertEqual("'a''bc'", "'0$'", "a''bc"); + assertEqual("'a' 'bc'", "'0$' '1$'", "a,bc"); + + assertEqual("'a''bc' 'a''bc'", "'0$' '1$'", "a''bc,a''bc"); + + + assertEqual("select * from table where a='a'", "select * from table where a='0$'", "a"); + } + + // @Test + public void charout() { + for (int i = 11; i < 67; i++) { + System.out.println((char) i); + } + } + + @Test + public void commentAndSymbolCombine() { + assertEqual("/* 'test' */", "/* 'test' */", ""); + assertEqual("/* 'test'' */", "/* 'test'' */", ""); + assertEqual("/* '' */", "/* '' */"); + + assertEqual("/* */ 123 */", "/* */ 0# */", "123"); + + assertEqual("' /* */'", "'0$'", " /* */"); + + } + + @Test + public void sepratorTest() { + + assertEqual("1234 456,7", "0# 1#,2#", "1234,456,7"); + + assertEqual("'1234 456,7'", "'0$'", "1234 456,,7"); + + assertEqual("'1234''456,7'", "'0$'", "1234''456,,7"); + ParsingResult parsingResult2 = this.sqlParser.normalizedSql("'1234''456,7'"); + System.out.println(parsingResult2); + // 문자열 토큰 + + + assertEqual("'1234' '456,7'", "'0$' '1$'", "1234,456,,7"); + } + + + @Test + public void combineTest() { + assertCombine("123 345", "0# 1#", "123,345"); + assertCombine("123 345 'test'", "0# 1# '2$'", "123,345,test"); + assertCombine("1 2 3 4 5 6 7 8 9 10 11", "0# 1# 2# 3# 4# 5# 6# 7# 8# 9# 10#", "1,2,3,4,5,6,7,8,9,10,11"); + } + + @Test + public void combineErrorTest() { + assertCombineErrorCase("123 10#", "0# 10#", "123,345"); + + assertCombineErrorCase("1 3 10#", "0# 2# 10#", "1,2,3"); + + assertCombineErrorCase("1 2 3", "0# 2 3", "1,2,3"); + assertCombineErrorCase("1 2 10", "0# 2 10", "1,2,3"); + assertCombineErrorCase("1 2 201", "0# 2 201", "1,2,3"); + + assertCombineErrorCase("1 2 11", "0# 2 10#", "1,2,3,4,5,6,7,8,9,10,11"); + + } + + private void assertCombine(String result, String sql, String outputParams) { + List output = this.outputParameterParser.parseOutputParameter(outputParams); + + ParsingResult parsingResult = this.sqlParser.normalizedSql(result); + Assert.assertEquals("sql", parsingResult.getSql(), sql); + String combine = this.sqlParser.combineOutputParams(sql, output); + Assert.assertEquals("combine", result, combine); + } + + private void assertCombineErrorCase(String expectedError, String sql, String outputParams) { + List output = this.outputParameterParser.parseOutputParameter(outputParams); +// ParsingResult parsingResult = this.sqlParser.normalizedSql(result); + String combine = this.sqlParser.combineOutputParams(sql, output); + Assert.assertEquals("combine", expectedError, combine); + } + + + private void assertEqual(String expected) { + ParsingResult parsingResult = sqlParser.normalizedSql(expected); + String normalizedSql = parsingResult.getSql(); + try { + Assert.assertEquals(expected, normalizedSql); + } catch (AssertionFailedError e) { + System.err.println("Original :" + expected); + throw e; + } + } + + private void assertEqual(String expected, String actual) { + ParsingResult parsingResult = sqlParser.normalizedSql(expected); + String normalizedSql = parsingResult.getSql(); + try { + Assert.assertEquals(actual, normalizedSql); + } catch (AssertionFailedError e) { + System.err.println("Original :" + expected); + throw e; + } + } + + private void assertEqual(String expected, String actual, String ouputExpected) { + ParsingResult parsingResult = sqlParser.normalizedSql(expected); + String normalizedSql = parsingResult.getSql(); + String output = parsingResult.getOutput(); + List outputParams = outputParameterParser.parseOutputParameter(output); + String s = sqlParser.combineOutputParams(normalizedSql, outputParams); + System.out.println("combine:" + s); + try { + Assert.assertEquals("normalizedSql check", actual, normalizedSql); + } catch (AssertionFailedError e) { + System.err.println("Original :" + expected); + throw e; + } + + Assert.assertEquals("outputParam check", ouputExpected, parsingResult.getOutput()); + } + + private void assertEqualObject(String expected) { + ParsingResult parsingResult = sqlParser.normalizedSql(expected); + String normalizedSql = parsingResult.getSql(); + try { + Assert.assertEquals("normalizedSql check", expected, normalizedSql); + Assert.assertSame(expected, normalizedSql); + } catch (AssertionFailedError e) { + System.err.println("Original :" + expected); + throw e; + } + + } + + +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/StringTraceHeaderParserTest.java b/src/test/java/com/nhn/pinpoint/common/util/StringTraceHeaderParserTest.java new file mode 100644 index 000000000..acd12b145 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/StringTraceHeaderParserTest.java @@ -0,0 +1,46 @@ +package com.nhn.pinpoint.common.util; + +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.UUID; + +/** + * @author emeroad + */ +public class StringTraceHeaderParserTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private StringTraceHeaderParser parser= new StringTraceHeaderParser(); + + @Test + public void getIdSize() { + String test = "3ccb94f3-a8fe-4464-bfbd-d35490afab3d"; + logger.info("idSize={}", test.length()); + } + + + @Test + public void createStringBaseTraceHeader() { + createAndParser(UUID.randomUUID().toString(), 123, 345, 23423, (short) 22); + createAndParser(UUID.randomUUID().toString(), -1, 2, 0, (short) 0); + createAndParser(UUID.randomUUID().toString(), 234, 2, 0, (short) 0); + } + + + + private void createAndParser(String uuid, int spanId, int pSpanId, int sampling, short flag) { + String traceHeader = parser.createHeader(uuid, spanId, pSpanId, sampling, (short) flag); + + TraceHeader header = parser.parseHeader(traceHeader); + Assert.assertEquals("id", uuid, header.getId()); + Assert.assertEquals("spanId", String.valueOf(spanId), header.getSpanId()); + Assert.assertEquals("pSpanId", String.valueOf(pSpanId), header.getParentSpanId()); + Assert.assertEquals("sampling", String.valueOf(sampling), header.getSampling()); + Assert.assertEquals("flag", String.valueOf(flag), header.getFlag()); + logger.info("{}, parse:" + header); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/TimeSlotTest.java b/src/test/java/com/nhn/pinpoint/common/util/TimeSlotTest.java new file mode 100644 index 000000000..6a21aa378 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/TimeSlotTest.java @@ -0,0 +1,53 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + */ +public class TimeSlotTest { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final TimeSlot timeSlot = new DefaultTimeSlot(); + + @Test + public void testGetTimeSlot() throws Exception { + long currentTime = System.currentTimeMillis(); + // 슬롯 넘버를 알아온다. + long timeSlot = this.timeSlot.getTimeSlot(currentTime); + + logger.info("{} currentTime ", currentTime); + logger.info("{} timeSlot", timeSlot); + Assert.assertTrue(currentTime >= timeSlot); + } + + @Test + public void testSlotTime1() throws Exception { + int slotTest = 60 * 1000; + + // 슬롯 넘버를 알아온다. + long timeSlot = this.timeSlot.getTimeSlot(slotTest); + + logger.info("{} slotTest ", slotTest); + logger.info("{} timeSlot", timeSlot); + Assert.assertEquals(slotTest, timeSlot); + } + + @Test + public void testSlotTime2() throws Exception { + int sourceTest = 60 * 1000; + int slotTest = sourceTest + 1; + + + // 슬롯 넘버를 알아온다. + long timeSlot = this.timeSlot.getTimeSlot(slotTest); + + logger.info("{} slotTest ", slotTest); + logger.info("{} timeSlot", timeSlot); + Assert.assertEquals(sourceTest, timeSlot); + } +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/TimeUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/TimeUtilsTest.java new file mode 100644 index 000000000..af0ff83d2 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/TimeUtilsTest.java @@ -0,0 +1,28 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class TimeUtilsTest { + @Test + public void testReverseCurrentTimeMillis() throws Exception { + long currentTime = System.currentTimeMillis(); + long reverseTime = TimeUtils.reverseTimeMillis(currentTime); + long recoveryTime = TimeUtils.recoveryTimeMillis(reverseTime); + + Assert.assertEquals(currentTime, recoveryTime); + } + + @Test + public void testTimeOrder() throws InterruptedException { + long l1 = TimeUtils.reverseCurrentTimeMillis(); + Thread.sleep(5); + long l2 = TimeUtils.reverseCurrentTimeMillis(); + + Assert.assertTrue(l1 > l2); + } + +} diff --git a/src/test/java/com/nhn/pinpoint/common/util/TransactionIdUtilsTest.java b/src/test/java/com/nhn/pinpoint/common/util/TransactionIdUtilsTest.java new file mode 100644 index 000000000..f62de88a1 --- /dev/null +++ b/src/test/java/com/nhn/pinpoint/common/util/TransactionIdUtilsTest.java @@ -0,0 +1,47 @@ +package com.nhn.pinpoint.common.util; + +import junit.framework.Assert; +import org.junit.Test; + +/** + * @author emeroad + */ +public class TransactionIdUtilsTest { + @Test + public void testParseTransactionId() { + TransactionId transactionId = TransactionIdUtils.parseTransactionId("test" + TransactionIdUtils.TRANSACTION_ID_DELIMITER + "1" + TransactionIdUtils.TRANSACTION_ID_DELIMITER + "2"); + Assert.assertEquals(transactionId.getAgentId(), "test"); + Assert.assertEquals(transactionId.getAgentStartTime(), 1L); + Assert.assertEquals(transactionId.getTransactionSequence(), 2L); + } + + @Test + public void testParseTransactionId2() { + TransactionId transactionId = TransactionIdUtils.parseTransactionId("test" + TransactionIdUtils.TRANSACTION_ID_DELIMITER + "1" + TransactionIdUtils.TRANSACTION_ID_DELIMITER + "2" + TransactionIdUtils.TRANSACTION_ID_DELIMITER); + Assert.assertEquals(transactionId.getAgentId(), "test"); + Assert.assertEquals(transactionId.getAgentStartTime(), 1L); + Assert.assertEquals(transactionId.getTransactionSequence(), 2L); + } + + + @Test + public void testParseTransactionIdByte() { + long time = System.currentTimeMillis(); + byte[] bytes = TransactionIdUtils.formatBytes("test", time, 2); + TransactionId transactionId = TransactionIdUtils.parseTransactionId(bytes); + Assert.assertEquals(transactionId.getAgentId(), "test"); + Assert.assertEquals(transactionId.getAgentStartTime(), time); + Assert.assertEquals(transactionId.getTransactionSequence(), 2L); + } + + @Test + public void testParseTransactionIdByte_AgentIdisNull() { + long time = System.currentTimeMillis(); + byte[] bytes = TransactionIdUtils.formatBytes(null, time, 1); + TransactionId transactionId = TransactionIdUtils.parseTransactionId(bytes); + Assert.assertEquals(transactionId.getAgentId(), null); + Assert.assertEquals(transactionId.getAgentStartTime(), time); + Assert.assertEquals(transactionId.getTransactionSequence(), 1L); + } + +} diff --git a/src/test/resources/log4j.xml b/src/test/resources/log4j.xml new file mode 100644 index 000000000..7067a1bb8 --- /dev/null +++ b/src/test/resources/log4j.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/test-hbase.properties b/src/test/resources/test-hbase.properties new file mode 100644 index 000000000..121a25f03 --- /dev/null +++ b/src/test/resources/test-hbase.properties @@ -0,0 +1,8 @@ +#hbase.client.host=localhost +#hbase.client.host=10.64.84.188 +#dev-hippo002.ncl +hbase.client.host=10.101.17.108 + +hbase.client.port=2181 + +hbase.htable.threads.max=32 \ No newline at end of file