Java Plugin

와탭에서 제공하는 Plugin을 활용해 프로파일 정보 내에 부가적인 정보를 추가하거나, 메소드 수행 전/후로 원하는 코드를 주입하는 것과 같은 다양한 일을 할 수 있습니다.

에이전트 옵션

에이전트 플러그인은 메소드 시작/종료 부분에 삽입되어 실행됩니다. 플러그인을 적용할 위치(클래스, 메소드 명)를 지정하는 옵션은 다음과 같습니다.

hook_trace_helper_end_patterns

메소드 종료 부분에 프로파일 플러그인을 삽입할 포인트(클래스 및 메소드명)를 지정합니다.
플러그인 코드는 $WHATAP_HOME/plugin/TraceHelperEnd.x 파일에 작성합니다.

hook_trace_helper_start_patterns

default: 메소드 시작 부분에 프로파일 플러그인을 삽일할 포인트(클래스 및 메소드명)를 지정합니다.
플러그인 코드는 $WHATAP_HOME/plugin/TraceHelperStart.x 파일에 작성합니다.

hook_trace_helper_patterns

메소드 시작/종료 양쪽에 프로파일 플러그인을 삽입할 포인트(클래스 및 메소드명)를 지정합니다.
플러그인 코드는 $WHATAP_HOME/plugin/TraceHelperStart.x, $WHATAP_HOME/plugin/TraceHelperEnd.x 각각 작성합니다.

custom_pool_classes

사용자 정의 Pool을 모니터링하기 위해 Pool 사용량 정보를 가진 클래스를 지정합니다.
플러그인 코드는 $WHATAP_HOME/plugin/CustomPool.x에 작성합니다.

설정 예

여러 개의 클래스를 지정하는 경우 ,로 구분합니다.
패키지 명의 문자열 일부/전부를 *로 치환할 수 있습니다.

패키지와 메소드 Full Name을 지정하는 경우
whatap.bytecode.instrument.PluginTestA.testA, whatap.bytecode.instrument.PluginTestB.testB
패키지명과 메소드 일부를 *로 치환한 경우
*PluginTestA.testA, whatap.bytecode.instrument.PluginTestB.*
*.testA, *PluginTestB.testB
전체를 대상으로 하는 경우
*.*

Custom Pool은 식별자@패키지 명 형태로 지정합니다.

Custom Pool을 지정하는 경우
whatap_plugin_guide@com.ibm.ws.connectionpool.monitor.ConnectionPoolStats (1)
1 Class 명 앞에 whatap_plugin_guide라는 식별자를 지정했습니다. 식별자와 클래스는 @로 구분합니다.

Plugin 코드 작성 예

plugin 코드 작성 예입니다. 대부분의 경우 Object를 반환하므로 명시적 type casting 처리가 필요합니다.

설정한 메소드 시작 시간을 프로파일에 기록하는 예

에이전트 hook_trace_helper_patterns 옵션에 적용할 메소드를 정의합니다.

$WHATAP_HOME/whatap.conf
hook_trace_helper_patterns=org.apache.catalina.connector.RequestFacade.*

TraceHelperStart.x에 Plugin 코드를 작성합니다.

$WHATAP_HOME/plugin/TraceHelperStart.x
String prefix = $point.class1 + "." + $point.method; (1)
$ctx.setAttribute(prefix + "st", new Long(System.currentTimeMillis())); (2)
$ctx.profile(prefix + " Start", new java.util.Date().toString()); (3)
1 String prefix에 클래스명, 메소드명을 대입합니다.
2 와탭 프로파일 속성명 prefix + "st" 로 현재 시간을 설정합니다.
3 프로파일 정보에 현재 시간을 추가합니다.

프로파일 내역에 메소드 시작 시간이 표시됩니다.

tracehelper start
Figure 1. 시작 시간 기록된 프로파일 내역

설정한 메소드 종료시간과 수행 시간을 프로파일에 기록하는 예

에이전트 hook_trace_helper_patterns 옵션에 적용할 메소드를 정의합니다.

$WHATAP_HOME/whatap.conf
hook_trace_helper_patterns=org.apache.catalina.connector.RequestFacade.*

TraceHelperEnd.x에 Plugin 코드를 작성합니다.

$WHATAP_HOME/plugin/TraceHelperEnd.x
String prefix = $point.class1 + "." + $point.method;
long st = ((Long) $ctx.getAttribute(prefix + "st")).longValue(); (1)
long gap = System.currentTimeMillis() - st;
StringBuilder sb = new StringBuilder();
sb.append(new java.util.Date().toString() + " (Gap:" + gap + " milliseconds)");
$ctx.profile(prefix + " End", sb.toString()); (2)
1 TraceHelperStart.x에서 추가한 프로파일 속성을 가져옵니다.
2 프로파일 정보에 시작 시간과의 현재 시간과의 Gap(수행 시간)을 추가합니다.

프로파일 내역에 메소드 종료 시간과 수행 시간이 표시됩니다.

tracehelper end
Figure 2. 종료 / 수행 시간까지 기록된 프로파일 내역

Plugin API

Plugin API는 공통 항목인 $ctx, $point 와 $pack, $req, $res로 구분됩니다.
트랜잭션 시작/종료 시, HTTPC 구간, 특정 메소드 실행구간 등에 적용 가능합니다.

Table 1. 공통 속성
플러그인 파일 파라미터 메소드/변수 설명

공통

$ctx

속성 관리

void setAttribute(String key, Object value)

Attribute를 set 합니다.

Object getAttribute(String key)

Attribute를 get 합니다.

프로파일 데이터

void profile(String desc)

프로파일 메시지 기록

void profile(String name, String msg)

프로파일 Step명, 메시지 기록

void profile(String name, String msg, int elapsed)

프로파일 Step명, 메시지, 수행 시간 기록

void profile(String name, String msg, int elapsed, int value)

프로파일 Step명, 메시지, 수행 시간, 순서 기록

HTTP Request

String service()

서비스 이름 반환

void service(String name)

서비스 이름 지정

int serviceHash()

서비스 이름의 Hash 값 반환

String remoteIp()

서비스 요청 IP 반환

void remoteIp(String ip)

서비스 요청 IP 지정

boolean isError()

에러 여부 반환

login(String id)

로그인 ID 반환

String login()

로그인 ID 지정

String httpMethod()

HTTP Method 반환

String httpQuery()

HTTP Query 반환

String httpContentType()

HTTP ContentType 반환

String userAgent()

User-Agent 반환

int status()

HTTP status 반환

$point

String class1

클래스명

String method

메소드명

Object this1

Hooking 대상 클래스/메소드

Object[] args

인자

Object return1

리턴

Table 2. 공통 속성 - 파라미터 없음
플러그인 파일 파라미터 메소드/변수 설명

공통

없음

void log(Object c)

Logger를 통한 Logging

void println(Object c)

System.out.println() 을 통한 출력

Object field(Object o, String field)

Field 값 반환

Object method(Object o, String method)

Invoke 메소드

Object method(Object o, String method, String param)

Invoke 메소드

String toString(Object o)

Object를 toSting() 반환

String toString(Object o, String def)

Object를 toSting() 반환, null 인 경우 def 반환

int syshash(Object o)

hash 값 반환

int syshash(HookArgs hook, int x)

x 번째 argument의 hash 값 반환

int syshash(HookArgs hook)

argument의 hash 값 반환

int cint(Object o)

int로 반환

float cfloat(Object o)

float으로 반환

String cString(Object o)

String으로 반환

long clong(Object o)

long으로 반환

double cdouble(Object o)

double로 반환

String desc(Object o)

Class signature 반환

String toJson(Object o)

json으로 반환

void shell(final String cmd, final String env)

shell 실행

데몬 및 배치

데몬, 배치와 같은 애플리케이션을 모니터링할 때 시작점으로 설정한 메소드에 적용하는 API입니다.

서비스 시작 부분에 적용하는 경우 $WHATAP_HOME/plugin/AppServiceStart.x, 서비스 종료 부분이라면 $WHATAP_HOME/plugin/AppServiceEnd.x라는 파일 명으로 코드를 작성합니다.

Table 3. 일반 서비스(데몬 및 배치)
플러그인 파일 파라미터 메소드/변수 설명

AppServiceStart.x

$ctx

공통 속성 참조

$point

공통 속성 참조

AppServiceEnd.x

$ctx

공통 속성 참조

HTTP 서비스

javax.servlet.http.HTTPServlet을 사용하는 일반적인 웹 어플리케이션에 적용할 수 있는 API입니다.

서비스 시작 부분에 적용하는 경우 $WHATAP_HOME/plugin/HttpServiceStart.x, 서비스 종료 부분이라면 $WHATAP_HOME/plugin/HttpServiceEnd.x라는 파일 명으로 코드를 작성합니다.

Table 4. HTTP 서비스
플러그인 파일 파라미터 메소드/변수 설명

HttpServiceStart.x/
HttpServiceEnd.x

$ctx

공통 속성 참조

$req

String getCookie(String key)

Cookie 값 반환

String getRequestURI()

RequestURI 반환

String getRemoteAddr()

RemoteAddr 반환

String getMethod()

HTTP Method 반환

String getQueryString()

HTTP QueryString 반환

String getParameter(String key)

Parameter 값 반환

Object getAttribute(String key)

Attribute 값 반환

String getHeader(String key)

Header 값 반환

Enumeration getParameterNames()

getParameterNames 반환

Enumeration getHeaderNames()

getHeaderNames 반환

WrSession getSession()

Session Wrapper 반환

Set getSessionNames()

getSessionNames 반환

Object getSessionAttribute(String key)

getSessionAttribute 반환

boolean isOk()

Plugin 상태 반환

Throwable error()

Error 반환

$res

String getContentType()

ContentType 반환

String getCharacterEncoding()

CharacterEncoding 반환

boolean isOk()

Plugin 상태 반환

Throwable error()

Error 반환

HTTP Outbound

HttpClient와 같은 라이브러리를 사용하여 HTTP Outbound Call 수행할 때 적용할 수 있는 API입니다.

서비스 시작 부분에 적용하는 경우 $WHATAP_HOME/plugin/HttpCallStart.x, 서비스 종료 부분이라면 $WHATAP_HOME/plugin/HttpCallEnd.x라는 파일 명으로 코드를 작성합니다.

Table 5. HTTP Outbound
플러그인 파일 파라미터 메소드/변수 설명

HttpCallStart.x

$ctx

공통 속성 참조

$req

String url()

URL 반환

String host()

Hostname 반환

int port()

Port 반환

boolean isOk()

Plugin 상태 반환

Throwable error()

Error 반환

HttpCallEnd.x

$ctx

공통 속성 참조

$res

String getContentType()

ContentType 반환

String getCharacterEncoding()

CharacterEncoding 반환

boolean isOk()

Plugin 상태 반환

Throwable error()

Error 반환

특정된 메소드

와탭 에이전트 옵션 (hook_trace_helper_*)을 통해 지정한 메소드에 대해 적용하는 API입니다.

Table 6. 지정한 메소드 구간
플러그인 파일 파라미터 메소드/변수 설명

TraceHelperStart.x

$ctx

공통 속성 참조

$point

공통 속성 참조

TraceHelperEnd.x

$ctx

공통 속성 참조

$point

공통 속성 참조

사용자 정의 Pool

사용자 정의 Pool을 모니터링하기 위한 API입니다.
Pool 사용량 정보를 가진 메소드를 지정하면 와탭에서 모니터링하고 통계정보를 확인할 수 있습니다. 사례와 같이 사용됩니다.

Table 7. Custom Pool
플러그인 파일 파라미터 메소드/변수 설명

CustomPool.x

$id

custom_pool_classes에 설정한 id 값

$pool

custom_pool_classes에 설정한 class

$result

int active(Object o)

Active Pool Count 지정

int idle(Object o)

Idle Pool Count 지정

Plugin 적용 사례

실제 Plugin 적용 사례입니다.

ElasticSearch 엔진의 검색 요청 모니터링

ElasticSearch 엔진(이하 ES)는 서블릿 엔진이 아니기 때문에 비정형 모니터링을 해야 합니다.
타제품이 지표 중심의 모니터링을 한다면 와탭의 Plugin 을 활용하면 ES의 요청, 처리시간 그리고 검색 키워드를 프로파일링 할 수 있습니다.

whatap.conf
hook_service_patterns=org.elasticsearch.search.SearchService.executeQueryPhase (1)
hook_trace_helper_start_patterns=org.elasticsearch.search.query.QueryPhase.execute (2)
1 트랜잭션 EndPoint로 org.elasticsearch.search.SearchService.executeQueryPhase를 설정 합니다.
2 hook_trace_helper_start_patterns에 등록된 메소드가 실행될 때마다 TraceHelperStart.x 내의 코드가 실행됩니다.
${WHATAP_HOME}/plugin/TraceHelperStart.x
if ($ctx.inner()==null){
	return;
}

try {

	String tclass = "org.elasticsearch.search.query.QueryPhase";
	String tmethod = "execute";

	if (tclass.equals($point.class1) && tmethod.equals($point.method)) {
		// 첫번째 argument 의 query 메소드 호출 결과를 String query 에 저장
		String query = " " + method($point.args[0],"query"); (1)
		// String query를 프로파일 정보로 출력
		$ctx.profile(query);
	}
} catch(Exception e) {
	$ctx.profile(e.toString());
}
1 org.elasticsearch.search.query.QueryPhase.execute(SearchContext searchContext)입니다.
즉, SearchContext.query() 메소드를 invoke 한 결과를 String query에 저장합니다.

특정 IP로 유입되는 트랜잭션 수집 제외

Health Check, 내부 사용자들이 유발한 트랜잭션을 수집 제외하려고 할 때 Plugin을 활용할 수 있습니다.

${WHATAP_HOME}/plugin/HttpServiceStart.x
String ignoreIP = "123.234.123.234"; (1)
String remoteIP = $req.getRemoteAddr();

if($ctx.ok() && remoteIP != null ) {
     if(remoteIP.equals(ignoreIP)){
         $ctx.ignore();
     }
}
1 수집 제외할 IP를 설정합니다.

Atomikos Pool 모니터링

API 문서 참고해 적용했습니다.

whatap.conf
custom_pool_classes=atomikos@com.atomikos.jdbc.internal.AbstractDataSourceBean
${WHATAP_HOME}/plugin/CustomPool.x
int total = cint(method($pool,"poolTotalSize"));
int avail = cint(method($pool,"poolAvailableSize"));

$result.active(total - avail);
$result.idle(avail);

쿠키값을 프로파일에서 확인할 수 있습니다.

${WHATAP_HOME}/plugin/HttpServiceStart.x
String cookie = $req.getCookie("AWSALB"); (1)

if($ctx.ok()) {
    if(cookie != null){
        $ctx.profile(cookie);
    }
}
1 $req.getCookie() parameter로 보고자 하는 Cookie를 설정합니다.