mirror of
https://github.com/alibaba/arthas.git
synced 2026-10-21 03:33:17 +00:00
feat: Add object-size-limit GlobalOptions for ObjectView (#3147)
This commit is contained in:
@@ -2,6 +2,7 @@ package com.taobao.arthas.core;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.taobao.arthas.common.ArthasConstants;
|
||||
import com.taobao.arthas.common.JavaVersionUtils;
|
||||
import com.taobao.arthas.common.UnsafeUtils;
|
||||
|
||||
@@ -66,6 +67,16 @@ public class GlobalOptions {
|
||||
)
|
||||
public static volatile boolean isUsingJson = false;
|
||||
|
||||
/**
|
||||
* ObjectView 输出大小限制(字节)
|
||||
*/
|
||||
@Option(level = 1,
|
||||
name = "object-size-limit",
|
||||
summary = "Option to control ObjectView output size limit",
|
||||
description = "Upper size limit in bytes for ObjectView output, must be greater than 0. Default value is 10 * 1024 * 1024."
|
||||
)
|
||||
public static volatile int objectSizeLimit = ArthasConstants.MAX_HTTP_CONTENT_LENGTH;
|
||||
|
||||
/**
|
||||
* 是否关闭子类
|
||||
*/
|
||||
|
||||
@@ -136,39 +136,55 @@ public class OptionsCommand extends AnnotatedCommand {
|
||||
try {
|
||||
// try to case string to type
|
||||
if (isIn(type, int.class, Integer.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Integer.valueOf(optionValue));
|
||||
afterValue = Integer.valueOf(optionValue);
|
||||
} else if (isIn(type, long.class, Long.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Long.valueOf(optionValue));
|
||||
afterValue = Long.valueOf(optionValue);
|
||||
} else if (isIn(type, boolean.class, Boolean.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Boolean.valueOf(optionValue));
|
||||
afterValue = Boolean.valueOf(optionValue);
|
||||
} else if (isIn(type, double.class, Double.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Double.valueOf(optionValue));
|
||||
afterValue = Double.valueOf(optionValue);
|
||||
} else if (isIn(type, float.class, Float.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Float.valueOf(optionValue));
|
||||
afterValue = Float.valueOf(optionValue);
|
||||
} else if (isIn(type, byte.class, Byte.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Byte.valueOf(optionValue));
|
||||
afterValue = Byte.valueOf(optionValue);
|
||||
} else if (isIn(type, short.class, Short.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = Short.valueOf(optionValue));
|
||||
afterValue = Short.valueOf(optionValue);
|
||||
} else if (isIn(type, short.class, String.class)) {
|
||||
FieldUtils.writeStaticField(field, afterValue = optionValue);
|
||||
afterValue = optionValue;
|
||||
} else {
|
||||
return ExitStatus.failure(-1, format("Options[%s] type[%s] was unsupported.", optionName, type.getSimpleName()));
|
||||
}
|
||||
|
||||
// FIXME hack for ongl strict
|
||||
if (field.getName().equals("strict")) {
|
||||
GlobalOptions.updateOnglStrict(Boolean.valueOf(optionValue));
|
||||
logger.info("update ongl strict to: {}", optionValue);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
return ExitStatus.failure(-1, format("Cannot cast option value[%s] to type[%s].", optionValue, type.getSimpleName()));
|
||||
}
|
||||
|
||||
String validateError = validateOptionValue(optionAnnotation.name(), afterValue);
|
||||
if (validateError != null) {
|
||||
return ExitStatus.failure(-1, validateError);
|
||||
}
|
||||
|
||||
FieldUtils.writeStaticField(field, afterValue);
|
||||
|
||||
// FIXME hack for ongl strict
|
||||
if (field.getName().equals("strict")) {
|
||||
GlobalOptions.updateOnglStrict(Boolean.valueOf(optionValue));
|
||||
logger.info("update ongl strict to: {}", optionValue);
|
||||
}
|
||||
|
||||
ChangeResultVO changeResultVO = new ChangeResultVO(optionAnnotation.name(), beforeValue, afterValue);
|
||||
process.appendResult(new OptionsModel(changeResultVO));
|
||||
return ExitStatus.success();
|
||||
}
|
||||
|
||||
static String validateOptionValue(String optionName, Object optionValue) {
|
||||
if ("object-size-limit".equals(optionName)
|
||||
&& optionValue instanceof Integer
|
||||
&& ((Integer) optionValue).intValue() <= 0) {
|
||||
return "options[object-size-limit] must be greater than 0.";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断当前动作是否需要展示整个options
|
||||
|
||||
+14
-2
@@ -68,7 +68,7 @@ public class TimeTunnelCommand extends EnhancerCommand {
|
||||
// expand of TimeTunnel
|
||||
private Integer expand = 1;
|
||||
// upper size limit
|
||||
private Integer sizeLimit = 10 * 1024 * 1024;
|
||||
private Integer sizeLimit;
|
||||
// watch the index TimeTunnel
|
||||
private String watchExpress = com.taobao.arthas.core.util.Constants.EMPTY_STRING;
|
||||
private String searchExpress = com.taobao.arthas.core.util.Constants.EMPTY_STRING;
|
||||
@@ -131,7 +131,7 @@ public class TimeTunnelCommand extends EnhancerCommand {
|
||||
}
|
||||
|
||||
@Option(shortName = "M", longName = "sizeLimit")
|
||||
@Description("Upper size limit in bytes for the result (10 * 1024 * 1024 by default)")
|
||||
@Description("Upper size limit in bytes for the result (must be greater than 0, default value comes from options object-size-limit)")
|
||||
public void setSizeLimit(Integer sizeLimit) {
|
||||
this.sizeLimit = sizeLimit;
|
||||
}
|
||||
@@ -234,10 +234,22 @@ public class TimeTunnelCommand extends EnhancerCommand {
|
||||
return !StringUtils.isEmpty(searchExpress);
|
||||
}
|
||||
|
||||
static String validateSizeLimit(Integer sizeLimit) {
|
||||
if (sizeLimit != null && sizeLimit.intValue() <= 0) {
|
||||
return "sizeLimit must be greater than 0.";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查参数是否合法
|
||||
*/
|
||||
private void checkArguments() {
|
||||
String validateError = validateSizeLimit(sizeLimit);
|
||||
if (validateError != null) {
|
||||
throw new IllegalArgumentException(validateError);
|
||||
}
|
||||
|
||||
// 检查d/p参数是否有i参数配套
|
||||
if ((isDelete || isPlay) && null == index) {
|
||||
throw new IllegalArgumentException("Time fragment index is expected, please type -i to specify");
|
||||
|
||||
@@ -43,7 +43,7 @@ public class WatchCommand extends EnhancerCommand {
|
||||
private boolean isException = false;
|
||||
private boolean isSuccess = false;
|
||||
private Integer expand = 1;
|
||||
private Integer sizeLimit = 10 * 1024 * 1024;
|
||||
private Integer sizeLimit;
|
||||
private boolean isRegEx = false;
|
||||
private int numberOfLimit = 100;
|
||||
|
||||
@@ -97,7 +97,7 @@ public class WatchCommand extends EnhancerCommand {
|
||||
}
|
||||
|
||||
@Option(shortName = "M", longName = "sizeLimit")
|
||||
@Description("Upper size limit in bytes for the result (10 * 1024 * 1024 by default)")
|
||||
@Description("Upper size limit in bytes for the result (must be greater than 0, default value comes from options object-size-limit)")
|
||||
public void setSizeLimit(Integer sizeLimit) {
|
||||
this.sizeLimit = sizeLimit;
|
||||
}
|
||||
@@ -199,6 +199,16 @@ public class WatchCommand extends EnhancerCommand {
|
||||
return methodNameMatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(CommandProcess process) {
|
||||
String validateError = validateSizeLimit(sizeLimit);
|
||||
if (validateError != null) {
|
||||
process.end(-1, validateError);
|
||||
return;
|
||||
}
|
||||
super.process(process);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AdviceListener getAdviceListener(CommandProcess process) {
|
||||
return new WatchAdviceListener(this, process, GlobalOptions.verbose || this.verbose);
|
||||
@@ -208,4 +218,11 @@ public class WatchCommand extends EnhancerCommand {
|
||||
protected void completeArgument3(Completion completion) {
|
||||
CompletionUtils.complete(completion, Arrays.asList(EXPRESS_EXAMPLES));
|
||||
}
|
||||
|
||||
static String validateSizeLimit(Integer sizeLimit) {
|
||||
if (sizeLimit != null && sizeLimit.intValue() <= 0) {
|
||||
return "sizeLimit must be greater than 0.";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class TimeTunnelView extends ResultView<TimeTunnelModel> {
|
||||
|
||||
@Override
|
||||
public void draw(CommandProcess process, TimeTunnelModel timeTunnelModel) {
|
||||
Integer sizeLimit = timeTunnelModel.getSizeLimit();
|
||||
int sizeLimitValue = ObjectView.normalizeMaxObjectLength(timeTunnelModel.getSizeLimit());
|
||||
|
||||
if (timeTunnelModel.getTimeFragmentList() != null) {
|
||||
//show list table: tt -l / tt -t
|
||||
@@ -35,7 +35,7 @@ public class TimeTunnelView extends ResultView<TimeTunnelModel> {
|
||||
TableElement table = TimeTunnelTable.createDefaultTable();
|
||||
TimeTunnelTable.drawTimeTunnel(table, tf);
|
||||
TimeTunnelTable.drawParameters(table, tf.getParams());
|
||||
TimeTunnelTable.drawReturnObj(table, tf, sizeLimit);
|
||||
TimeTunnelTable.drawReturnObj(table, tf, sizeLimitValue);
|
||||
TimeTunnelTable.drawThrowException(table, tf);
|
||||
process.write(RenderUtil.render(table, process.width()));
|
||||
|
||||
@@ -43,7 +43,7 @@ public class TimeTunnelView extends ResultView<TimeTunnelModel> {
|
||||
//watch single TimeFragment: tt -i 1000 -w 'params'
|
||||
ObjectVO valueVO = timeTunnelModel.getWatchValue();
|
||||
if (valueVO.needExpand()) {
|
||||
process.write(new ObjectView(sizeLimit, valueVO).draw()).write("\n");
|
||||
process.write(new ObjectView(sizeLimitValue, valueVO).draw()).write("\n");
|
||||
} else {
|
||||
process.write(StringUtils.objectToString(valueVO.getObject())).write("\n");
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class TimeTunnelView extends ResultView<TimeTunnelModel> {
|
||||
//search & watch: tt -s 'returnObj!=null' -w 'returnObj'
|
||||
TableElement table = TimeTunnelTable.createDefaultTable();
|
||||
TimeTunnelTable.drawWatchTableHeader(table);
|
||||
TimeTunnelTable.drawWatchResults(table, timeTunnelModel.getWatchResults(), sizeLimit);
|
||||
TimeTunnelTable.drawWatchResults(table, timeTunnelModel.getWatchResults(), sizeLimitValue);
|
||||
process.write(RenderUtil.render(table, process.width()));
|
||||
|
||||
} else if (timeTunnelModel.getReplayResult() != null) {
|
||||
@@ -63,7 +63,7 @@ public class TimeTunnelView extends ResultView<TimeTunnelModel> {
|
||||
TimeTunnelTable.drawPlayHeader(replayResult.getClassName(), replayResult.getMethodName(), replayResult.getObject(), replayResult.getIndex(), table);
|
||||
TimeTunnelTable.drawParameters(table, replayResult.getParams());
|
||||
if (replayResult.isReturn()) {
|
||||
TimeTunnelTable.drawPlayResult(table, replayResult.getReturnObj(), sizeLimit, replayResult.getCost());
|
||||
TimeTunnelTable.drawPlayResult(table, replayResult.getReturnObj(), sizeLimitValue, replayResult.getCost());
|
||||
} else {
|
||||
TimeTunnelTable.drawPlayException(table, replayResult.getThrowExp());
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@ public class WatchView extends ResultView<WatchModel> {
|
||||
@Override
|
||||
public void draw(CommandProcess process, WatchModel model) {
|
||||
ObjectVO objectVO = model.getValue();
|
||||
int sizeLimit = ObjectView.normalizeMaxObjectLength(model.getSizeLimit());
|
||||
String result = StringUtils.objectToString(
|
||||
objectVO.needExpand() ? new ObjectView(model.getSizeLimit(), objectVO).draw() : objectVO.getObject());
|
||||
objectVO.needExpand() ? new ObjectView(sizeLimit, objectVO).draw() : objectVO.getObject());
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("method=").append(model.getClassName()).append(".").append(model.getMethodName())
|
||||
|
||||
@@ -27,7 +27,6 @@ import static java.lang.String.format;
|
||||
public class ObjectView implements View {
|
||||
public static final int MAX_DEEP = 4;
|
||||
private static final Logger logger = LoggerFactory.getLogger(ObjectView.class);
|
||||
private final static int MAX_OBJECT_LENGTH = ArthasConstants.MAX_HTTP_CONTENT_LENGTH;
|
||||
private static final ObjectWriterProvider JSON_OBJECT_WRITER_PROVIDER = new ObjectWriterProvider(
|
||||
new ObjectWriterCreator() {
|
||||
@Override
|
||||
@@ -53,7 +52,7 @@ public class ObjectView implements View {
|
||||
private final int maxObjectLength;
|
||||
|
||||
public ObjectView(ObjectVO objectVO) {
|
||||
this(MAX_OBJECT_LENGTH, objectVO);
|
||||
this(defaultMaxObjectLength(), objectVO);
|
||||
}
|
||||
|
||||
// int参数在前面,防止构造函数二义性
|
||||
@@ -62,7 +61,7 @@ public class ObjectView implements View {
|
||||
}
|
||||
|
||||
public ObjectView(Object object, int deep) {
|
||||
this(object, deep, MAX_OBJECT_LENGTH);
|
||||
this(object, deep, defaultMaxObjectLength());
|
||||
}
|
||||
|
||||
public ObjectView(Object object, int deep, int maxObjectLength) {
|
||||
@@ -83,7 +82,7 @@ public class ObjectView implements View {
|
||||
} catch (ObjectTooLargeException e) {
|
||||
buf.append(" Object size exceeds size limit: ")
|
||||
.append(maxObjectLength)
|
||||
.append(", try to specify -M size_limit in your command, check the help command for more.");
|
||||
.append(", try to use `options object-size-limit <bytes>` to increase the limit.");
|
||||
return buf.toString();
|
||||
} catch (Throwable t) {
|
||||
logger.error("ObjectView draw error, object class: {}", object.getClass(), t);
|
||||
@@ -699,5 +698,19 @@ public class ObjectView implements View {
|
||||
}
|
||||
}
|
||||
|
||||
public static int normalizeMaxObjectLength(Integer limit) {
|
||||
if (limit != null && limit > 0) {
|
||||
return limit;
|
||||
}
|
||||
int globalLimit = GlobalOptions.objectSizeLimit;
|
||||
if (globalLimit > 0) {
|
||||
return globalLimit;
|
||||
}
|
||||
return ArthasConstants.MAX_HTTP_CONTENT_LENGTH;
|
||||
}
|
||||
|
||||
private static int defaultMaxObjectLength() {
|
||||
return normalizeMaxObjectLength(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.taobao.arthas.core.command.basic1000;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class OptionsCommandTest {
|
||||
|
||||
@Test
|
||||
public void testValidateObjectSizeLimitOptionValue() {
|
||||
Assert.assertEquals("options[object-size-limit] must be greater than 0.",
|
||||
OptionsCommand.validateOptionValue("object-size-limit", Integer.valueOf(0)));
|
||||
Assert.assertEquals("options[object-size-limit] must be greater than 0.",
|
||||
OptionsCommand.validateOptionValue("object-size-limit", Integer.valueOf(-1)));
|
||||
Assert.assertNull(OptionsCommand.validateOptionValue("object-size-limit", Integer.valueOf(1)));
|
||||
Assert.assertNull(OptionsCommand.validateOptionValue("json-format", Boolean.TRUE));
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.taobao.arthas.core.command.monitor200;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SizeLimitValidationTest {
|
||||
|
||||
@Test
|
||||
public void testWatchSizeLimitValidation() {
|
||||
Assert.assertEquals("sizeLimit must be greater than 0.", WatchCommand.validateSizeLimit(Integer.valueOf(0)));
|
||||
Assert.assertEquals("sizeLimit must be greater than 0.", WatchCommand.validateSizeLimit(Integer.valueOf(-1)));
|
||||
Assert.assertNull(WatchCommand.validateSizeLimit(Integer.valueOf(1)));
|
||||
Assert.assertNull(WatchCommand.validateSizeLimit(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeTunnelSizeLimitValidation() {
|
||||
Assert.assertEquals("sizeLimit must be greater than 0.", TimeTunnelCommand.validateSizeLimit(Integer.valueOf(0)));
|
||||
Assert.assertEquals("sizeLimit must be greater than 0.", TimeTunnelCommand.validateSizeLimit(Integer.valueOf(-1)));
|
||||
Assert.assertNull(TimeTunnelCommand.validateSizeLimit(Integer.valueOf(1)));
|
||||
Assert.assertNull(TimeTunnelCommand.validateSizeLimit(null));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.taobao.arthas.core.view;
|
||||
|
||||
import com.taobao.arthas.common.ArthasConstants;
|
||||
import com.taobao.arthas.core.GlobalOptions;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -223,6 +224,37 @@ public class ObjectViewTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSizeLimitFromGlobalOptions() {
|
||||
int old = GlobalOptions.objectSizeLimit;
|
||||
try {
|
||||
GlobalOptions.objectSizeLimit = 5;
|
||||
ObjectView objectView = new ObjectView("123456", 1);
|
||||
String output = objectView.draw();
|
||||
Assert.assertTrue(output.contains("Object size exceeds size limit: 5"));
|
||||
} finally {
|
||||
GlobalOptions.objectSizeLimit = old;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormalizeMaxObjectLength() {
|
||||
int old = GlobalOptions.objectSizeLimit;
|
||||
try {
|
||||
GlobalOptions.objectSizeLimit = 9;
|
||||
Assert.assertEquals(9, ObjectView.normalizeMaxObjectLength(null));
|
||||
Assert.assertEquals(9, ObjectView.normalizeMaxObjectLength(0));
|
||||
Assert.assertEquals(9, ObjectView.normalizeMaxObjectLength(-1));
|
||||
Assert.assertEquals(8, ObjectView.normalizeMaxObjectLength(8));
|
||||
|
||||
GlobalOptions.objectSizeLimit = 0;
|
||||
Assert.assertEquals(ArthasConstants.MAX_HTTP_CONTENT_LENGTH, ObjectView.normalizeMaxObjectLength(null));
|
||||
Assert.assertEquals(ArthasConstants.MAX_HTTP_CONTENT_LENGTH, ObjectView.normalizeMaxObjectLength(-1));
|
||||
} finally {
|
||||
GlobalOptions.objectSizeLimit = old;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDate() {
|
||||
Date d = new Date(1531204354961L - TimeZone.getDefault().getRawOffset()
|
||||
@@ -276,7 +308,7 @@ public class ObjectViewTest {
|
||||
" c1=@NestedClass[\n" +
|
||||
" code=@Integer[1],\n" +
|
||||
" c1=...\n" +
|
||||
"... Object size exceeds size limit: 100, try to specify -M size_limit in your command, check the help command for more.";
|
||||
"... Object size exceeds size limit: 100, try to use `options object-size-limit <bytes>` to increase the limit.";
|
||||
Assert.assertEquals(expected, objectView.draw());
|
||||
}
|
||||
|
||||
|
||||
+17
-13
@@ -6,19 +6,20 @@
|
||||
全局开关
|
||||
:::
|
||||
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| ---------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| unsafe | false | 是否支持对系统级别的类进行增强,打开该开关可能导致把 JVM 搞挂,请慎重选择! |
|
||||
| dump | false | 是否支持被增强了的类 dump 到外部文件中,如果打开开关,class 文件会被 dump 到`/${application working dir}/arthas-class-dump/`目录下,具体位置详见控制台输出 |
|
||||
| batch-re-transform | true | 是否支持批量对匹配到的类执行 retransform 操作 |
|
||||
| json-format | false | 是否支持 json 化的输出 |
|
||||
| disable-sub-class | false | 是否禁用子类匹配,默认在匹配目标类的时候会默认匹配到其子类,如果想精确匹配,可以关闭此开关 |
|
||||
| support-default-method | true | 是否支持匹配到 default method, 默认会查找 interface,匹配里面的 default method。参考 [#1105](https://github.com/alibaba/arthas/issues/1105) |
|
||||
| save-result | false | 是否打开执行结果存日志功能,打开之后所有命令的运行结果都将保存到`~/logs/arthas-cache/result.log`中 |
|
||||
| job-timeout | 1d | 异步后台任务的默认超时时间,超过这个时间,任务自动停止;比如设置 1d, 2h, 3m, 25s,分别代表天、小时、分、秒 |
|
||||
| print-parent-fields | true | 是否打印在 parent class 里的 filed |
|
||||
| verbose | false | 是否打印更多详细信息 |
|
||||
| strict | true | 是否启用 strict 模式 |
|
||||
| 名称 | 默认值 | 描述 |
|
||||
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| unsafe | false | 是否支持对系统级别的类进行增强,打开该开关可能导致把 JVM 搞挂,请慎重选择! |
|
||||
| dump | false | 是否支持被增强了的类 dump 到外部文件中,如果打开开关,class 文件会被 dump 到`/${application working dir}/arthas-class-dump/`目录下,具体位置详见控制台输出 |
|
||||
| batch-re-transform | true | 是否支持批量对匹配到的类执行 retransform 操作 |
|
||||
| json-format | false | 是否支持 json 化的输出 |
|
||||
| object-size-limit | 10485760 | ObjectView 输出大小上限(字节),必须大于 0,默认 `10 * 1024 * 1024` |
|
||||
| disable-sub-class | false | 是否禁用子类匹配,默认在匹配目标类的时候会默认匹配到其子类,如果想精确匹配,可以关闭此开关 |
|
||||
| support-default-method | true | 是否支持匹配到 default method, 默认会查找 interface,匹配里面的 default method。参考 [#1105](https://github.com/alibaba/arthas/issues/1105) |
|
||||
| save-result | false | 是否打开执行结果存日志功能,打开之后所有命令的运行结果都将保存到`~/logs/arthas-cache/result.log`中 |
|
||||
| job-timeout | 1d | 异步后台任务的默认超时时间,超过这个时间,任务自动停止;比如设置 1d, 2h, 3m, 25s,分别代表天、小时、分、秒 |
|
||||
| print-parent-fields | true | 是否打印在 parent class 里的 filed |
|
||||
| verbose | false | 是否打印更多详细信息 |
|
||||
| strict | true | 是否启用 strict 模式 |
|
||||
|
||||
## 查看所有的 options
|
||||
|
||||
@@ -40,6 +41,9 @@ $ options
|
||||
2 boolea json-format false Option to support JS This option enables to format object outpu
|
||||
n ON format of object t with JSON when -x option selected.
|
||||
output
|
||||
1 int object-size- 10485760 Option to control O Upper size limit in bytes for ObjectView o
|
||||
limit bjectView output utput, must be greater than 0. Default val
|
||||
ue is 10 * 1024 * 1024.
|
||||
1 boolea disable-sub- false Option to control in This option disable to include sub class w
|
||||
n class clude sub class when hen matching class.
|
||||
class matching
|
||||
|
||||
@@ -12,6 +12,7 @@ Global options
|
||||
| dump | false | whether to dump enhanced class to the external files. If it's on, enhanced class will be dumped into `/${application dir}/arthas-class-dump/`, the specific output path will be output in the console |
|
||||
| batch-re-transform | true | whether to re-transform matched classes in batch |
|
||||
| json-format | false | whether to output in JSON format |
|
||||
| object-size-limit | 10485760 | upper size limit in bytes for ObjectView output (must be greater than 0, default is `10 * 1024 * 1024`) |
|
||||
| disable-sub-class | false | whether to enable matching child classes. The default value is `true`. If exact match is desire, turn off this flag |
|
||||
| support-default-method | true | whether to enable matching default method in interface. The default value is `true`. Refer to [#1105](https://github.com/alibaba/arthas/issues/1105) |
|
||||
| save-result | false | whether to save execution result. All execution results will be saved to `~/logs/arthas-cache/result.log` when it's turned on |
|
||||
@@ -40,6 +41,9 @@ $ options
|
||||
2 boolea json-format false Option to support JS This option enables to format object outpu
|
||||
n ON format of object t with JSON when -x option selected.
|
||||
output
|
||||
1 int object-size- 10485760 Option to control O Upper size limit in bytes for ObjectView o
|
||||
limit bjectView output utput, must be greater than 0. Default val
|
||||
ue is 10 * 1024 * 1024.
|
||||
1 boolea disable-sub- false Option to control in This option disable to include sub class w
|
||||
n class clude sub class when hen matching class.
|
||||
class matching
|
||||
|
||||
Reference in New Issue
Block a user