Skip to content

Commit

Permalink
Merge pull request #771 from scouter-project/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
gunlee01 authored Dec 19, 2020
2 parents 7ad7efa + de59038 commit ec58f93
Show file tree
Hide file tree
Showing 25 changed files with 170 additions and 48 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ SCOUTER can help you.

- **Server (Collector)** : save the performance metrics from scouter agents or telegraf. The data is streamed to scouter client.

- **Client (Viewer)** : client program based on RCP.
- **Client (Viewer)** : client program based on RCP. (not support OSX Big Sur.)

- **Web API (Since @1.8.0)** : scouter web apis to get counters, XLogs, profiles and another performance metrics via HTTP protocol.
- [Web API Guide](./scouter.document/tech/Web-API-Guide.md)
Expand Down
2 changes: 1 addition & 1 deletion README_kr.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

- **Server (Collector)** : Agent가 전송한 데이터를 저장하고 Client 요청시 Client에게 적절한 데이터를 전송

- **Client (Viewer)** : 수집된 데이터를 보기 위한 RCP 기반 Client 프로그램
- **Client (Viewer)** : 수집된 데이터를 보기 위한 RCP 기반 Client 프로그램. (OSX Big Sur 미지원)

- **Web API (Since @1.8.0)** : 성능 카운터, XLog, 프로파일등의 정보를 HTTP 프로토콜을 통해 제공
- [Web API Guide](./scouter.document/tech/Web-API-Guide_kr.md)
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.github.scouter-project</groupId>
<artifactId>scouter-parent</artifactId>
<version>2.10.0</version>
<version>2.10.2</version>
<packaging>pom</packaging>

<name>SCOUTER APM</name>
Expand Down
2 changes: 1 addition & 1 deletion scouter.agent.batch/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.github.scouter-project</groupId>
<artifactId>scouter-parent</artifactId>
<version>2.10.0</version>
<version>2.10.2</version>
</parent>

<artifactId>scouter-agent-batch</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion scouter.agent.host/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.scouter-project</groupId>
<artifactId>scouter-parent</artifactId>
<version>2.10.0</version>
<version>2.10.2</version>
</parent>

<artifactId>scouter-agent-host</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion scouter.agent.java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.github.scouter-project</groupId>
<artifactId>scouter-parent</artifactId>
<version>2.10.0</version>
<version>2.10.2</version>
</parent>

<artifactId>scouter-agent-java</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,19 @@
package reactor.core.publisher;

import scouter.agent.Logger;
import scouter.agent.util.Tuple;

/**
* @author Gun Lee ([email protected]) on 2020/08/08
*/
public class ScouterOptimizableOperatorProxy {

public static final String EMPTY = "";
public static final Tuple.StringLongPair EMPTYOBJ = new Tuple.StringLongPair("", 0);
public static boolean accessible = false;
public static boolean first = true;

public static String nameOnCheckpoint(Object candidate) {
public static Tuple.StringLongPair nameOnCheckpoint(Object candidate, int maxScanDepth) {
try {
if (!accessible && first) {
try {
Expand All @@ -42,34 +44,47 @@ public static String nameOnCheckpoint(Object candidate) {
first = false;
}
if (!accessible) {
return EMPTY;
return EMPTYOBJ;
}

if (candidate instanceof OptimizableOperator) {
OptimizableOperator<?, ?> operator = ((OptimizableOperator<?, ?>) candidate).nextOptimizableSource();
if (operator == null) {
return EMPTY;
OptimizableOperator<?, ?> closeAssembly = findCloseAssembly((OptimizableOperator<?, ?>) candidate, maxScanDepth);
if (closeAssembly == null) {
return EMPTYOBJ;
}
if (operator instanceof MonoOnAssembly) {
FluxOnAssembly.AssemblySnapshot snapshot = ((MonoOnAssembly) operator).stacktrace;
if (closeAssembly instanceof MonoOnAssembly) {
FluxOnAssembly.AssemblySnapshot snapshot = ((MonoOnAssembly) closeAssembly).stacktrace;
if (snapshot != null && snapshot.checkpointed) {
return snapshot.cached;
return new Tuple.StringLongPair(snapshot.cached, snapshot.hashCode());
}
} else if (operator instanceof FluxOnAssembly) {
FluxOnAssembly.AssemblySnapshot snapshot = ((FluxOnAssembly) operator).snapshotStack;
} else if (closeAssembly instanceof FluxOnAssembly) {
FluxOnAssembly.AssemblySnapshot snapshot = ((FluxOnAssembly) closeAssembly).snapshotStack;
if (snapshot != null && snapshot.checkpointed) {
return snapshot.cached;
return new Tuple.StringLongPair(snapshot.cached, snapshot.hashCode());
}
}
}
return EMPTY;
return EMPTYOBJ;
} catch (Throwable e) {

return EMPTY;
return EMPTYOBJ;
}
}

public static void appendSources4Dump(Object candidate, StringBuilder builder) {
public static OptimizableOperator<?, ?> findCloseAssembly(OptimizableOperator<?, ?> candidate, int maxScanDepth) {
OptimizableOperator<?, ?> operator = candidate;
for (int i = 0; i < maxScanDepth; i++) {
operator = operator.nextOptimizableSource();
if (operator == null) {
return null;
} else if (operator instanceof MonoOnAssembly || operator instanceof FluxOnAssembly) {
return operator;
}
}
return null;
}

public static void appendSources4Dump(Object candidate, StringBuilder builder, int maxScanDepth) {
try {
if (!accessible && first) {
try {
Expand All @@ -86,14 +101,14 @@ public static void appendSources4Dump(Object candidate, StringBuilder builder) {
}

if (candidate instanceof OptimizableOperator) {
OptimizableOperator<?, ?> operator = ((OptimizableOperator<?, ?>) candidate).nextOptimizableSource();
if (operator == null) {
OptimizableOperator<?, ?> closeAssembly = findCloseAssembly((OptimizableOperator<?, ?>) candidate, maxScanDepth);
if (closeAssembly == null) {
return;
}
String p1 = operator.toString();
String p1 = closeAssembly.toString();
builder.append(" (<-) ").append(p1);
if (p1.startsWith("checkpoint")) {
OptimizableOperator<?, ?> operator2 = operator.nextOptimizableSource();
OptimizableOperator<?, ?> operator2 = closeAssembly.nextOptimizableSource();
if (operator2 != null) {
builder.append(" (<-) ").append(operator2.toString());
}
Expand Down
6 changes: 6 additions & 0 deletions scouter.agent.java/src/main/java/scouter/agent/Configure.java
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ public static final Configure getInstance() {

@ConfigDesc("profile reactor's important checkpoint")
public boolean profile_reactor_checkpoint_enabled = true;
@ConfigDesc("reactor's important checkpoint scan depth")
public int profile_reactor_checkpoint_search_depth = 5;
@ConfigDesc("profile reactor's another checkpoints")
public boolean profile_reactor_more_checkpoint_enabled = false;

Expand Down Expand Up @@ -597,6 +599,8 @@ public static final Configure getInstance() {
public boolean hook_method_access_none_enabled = false;
@ConfigDesc("Activating lambda Method hooking")
public boolean hook_method_lambda_enable = true;
@ConfigDesc("Activating anonymous Method hooking")
public boolean hook_method_anonymous_enable = true;

@ConfigDesc("Method set for service hooking")
@ConfigValueType(ValueType.COMMA_SEPARATED_VALUE)
Expand Down Expand Up @@ -989,6 +993,7 @@ private void apply() {
this.hook_method_access_private_enabled = getBoolean("hook_method_access_private_enabled", false);
this.hook_method_access_none_enabled = getBoolean("hook_method_access_none_enabled", false);
this.hook_method_lambda_enable = getBoolean("hook_method_lambda_enable", true);
this.hook_method_anonymous_enable = getBoolean("hook_method_anonymous_enable", true);

this.hook_method_ignore_prefixes = StringUtil.removeWhitespace(getValue("hook_method_ignore_prefixes", "get,set"));
this._hook_method_ignore_prefix = StringUtil.split(this.hook_method_ignore_prefixes, ",");
Expand Down Expand Up @@ -1087,6 +1092,7 @@ private void apply() {
this.profile_elasticsearch_full_query_enabled = getBoolean("profile_elasticsearch_full_query_enabled", false);

this.profile_reactor_checkpoint_enabled = getBoolean("profile_reactor_checkpoint_enabled", true);
this.profile_reactor_checkpoint_search_depth = getInt("profile_reactor_checkpoint_search_depth", 5);
this.profile_reactor_more_checkpoint_enabled = getBoolean("profile_reactor_more_checkpoint_enabled", false);

this.net_udp_collection_interval_ms = getInt("net_udp_collection_interval_ms", 100);
Expand Down
13 changes: 13 additions & 0 deletions scouter.agent.java/src/main/java/scouter/agent/asm/MethodASM.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ public ClassVisitor transform(ClassVisitor cv, String className, ClassDesc class
if (conf.isIgnoreMethodClass(className))
return cv;

if (!conf.hook_method_anonymous_enable && classIsAnnon(className)) {
return cv;
}

for (int i = 0; i < target.size(); i++) {
HookingSet mset = target.get(i);
if (mset.classMatch.include(className)) {
Expand All @@ -82,6 +86,15 @@ public ClassVisitor transform(ClassVisitor cv, String className, ClassDesc class
}
return cv;
}

private boolean classIsAnnon(String className) {
int spIndex = className.lastIndexOf('$');
if (spIndex > 0 && spIndex < className.length() - 1) {
char dig = className.charAt(spIndex + 1);
return dig >= 48 && dig <= 57;
}
return false;
}
}

class MethodCV extends ClassVisitor implements Opcodes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public String getCookie(Object req, String key) {
public String getRequestURI(Object req) {
return null;
}
public String getRequestId(Object req) {
return null;
}
public String getRemoteAddr(Object req) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public interface IHttpTrace {
String getHeader(Object req, String key);
String getCookie(Object req, String key);
String getRequestURI(Object req);
String getRequestId(Object req);
String getRemoteAddr(Object req);
String getMethod(Object req);
String getQueryString(Object req);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public enum GetBy {
public boolean isReactiveStarted;
public boolean isReactiveTxidMarked;
public long exchangeHashCode;
public String serverReqId;
public boolean isCoroutineStarted;
public boolean isOnCoroutineIdUpdating;

Expand All @@ -77,8 +78,8 @@ public void initScannables() {
scannables.setMax(10000);
}

public Object req;
public Object res;
public Object _req;
public Object _res;
public IHttpTrace http;

public TraceContext parent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ public static void completeDeferred(TraceContext o) {
}

public static void clearAllContext(TraceContext o) {
o._req = null;
o._res = null;
local.set(null);
coroutineDebuggingLocal.clear(); //it should be prev of txidLocal clear

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,15 @@ public static void startReactiveHttpService(Object exchange) {
try {
Object req = AbstractPlugin.invokeMethod(exchange, "getRequest");
Object res = AbstractPlugin.invokeMethod(exchange, "getResponse");
if (reactiveHttp == null) {
initReactiveHttp(req);
}

String serverReqId = reactiveHttp.getRequestId(req);
TraceContext ctx = TraceContextManager.getContext();
if (ctx != null && serverReqId != null && ctx.serverReqId == serverReqId) {
return;
}
if (ctx != null && ctx.exchangeHashCode != exchange.hashCode()) {
//Logger.trace("exchange hash is different on context : " + exchange.hashCode() + " : " + ctx.exchangeHashCode);
ctx = null;
Expand Down Expand Up @@ -287,9 +294,6 @@ private static void addHttpServiceName(TraceContext ctx, Object req) {
private static Object lock = new Object();

private static Object startReactiveHttp(Object req, Object res, Object exchange) {
if (reactiveHttp == null) {
initReactiveHttp(req);
}
return startHttp(req, res, reactiveHttp, true, exchange);
}

Expand All @@ -307,6 +311,7 @@ private static Object startHttp(Object req, Object res, IHttpTrace http0, boolea
ctx.initScannables();
ctx.isReactiveStarted = true;
ctx.exchangeHashCode = exchange.hashCode();
ctx.serverReqId = reactiveHttp.getRequestId(req);
}
ctx.thread = Thread.currentThread();
ctx.threadId = ctx.thread.getId();
Expand All @@ -323,8 +328,8 @@ private static Object startHttp(Object req, Object res, IHttpTrace http0, boolea
ctx.profile.add(step);

http0.start(ctx, req, res);
ctx.req = req;
ctx.res = res;
ctx._req = req;
ctx._res = res;
ctx.http = http0;

if (ctx.isFullyDiscardService) {
Expand Down Expand Up @@ -382,7 +387,7 @@ public static void endReactiveHttpService() {
if (context == null) {
return;
}
Stat stat = new Stat(context, context.req, context.res);
Stat stat = new Stat(context, context._req, context._res);
endHttpService(stat, null);
}

Expand All @@ -396,7 +401,7 @@ public static void endCanceledHttpService(TraceContext traceContext) {
step.start_time = (int) (System.currentTimeMillis() - traceContext.startTime);
traceContext.profile.add(step);

endHttpService(new Stat(traceContext), null);
endHttpService(new Stat(traceContext, traceContext._req, traceContext._res), null);
}
}

Expand All @@ -418,7 +423,11 @@ public static void endHttpService(Object stat, Throwable thr) {

//wait on async servlet completion
if (!ctx.asyncServletStarted) {
endHttpServiceFinal(ctx, ctx.req, ctx.res, thr);
Object req = ctx._req;
Object res = ctx._res;
ctx._req = null;
ctx._res = null;
endHttpServiceFinal(ctx, req, res, thr);
} else {
HashedMessageStep step = new HashedMessageStep();
step.time = -1;
Expand Down
33 changes: 33 additions & 0 deletions scouter.agent.java/src/main/java/scouter/agent/util/Tuple.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package scouter.agent.util;
/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* Licensed 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.
*/

/**
* Created by Gun Lee([email protected]) on 2020/10/15
*/
public class Tuple {

public static class StringLongPair {
public String aString;
public long aLong;

public StringLongPair(String aString, long aLong) {
this.aString = aString;
this.aLong = aLong;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ public String getRequestURI(Object req) {
return getRequestURI(request);
}

@Override
public String getRequestId(Object req) {
return null;
}

@Override
public String getRemoteAddr(Object req) {
HttpServletRequest request = (HttpServletRequest) req;
Expand Down Expand Up @@ -302,7 +307,11 @@ public void start(TraceContext ctx, Object req, Object res) {
if (b3ModeValid) {
ctx.gxid = HexCodec.lowerHexToUnsignedLong(b3TraceId);
ctx.txid = HexCodec.lowerHexToUnsignedLong(request.getHeader(B3Constant.B3_HEADER_SPANID));
ctx.caller = HexCodec.lowerHexToUnsignedLong(request.getHeader(B3Constant.B3_HEADER_PARENTSPANID));
String caller = request.getHeader(B3Constant.B3_HEADER_PARENTSPANID);
if (caller != null) {
ctx.caller = HexCodec.lowerHexToUnsignedLong(caller);
ctx.is_child_tx = true;
}
ctx.b3Mode = true;
ctx.b3Traceid = b3TraceId;

Expand Down
Loading

0 comments on commit ec58f93

Please sign in to comment.