Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
Arthas
Commits
5d7c4150
Commit
5d7c4150
authored
Dec 21, 2023
by
shengnan hu
Browse files
init
parents
Pipeline
#4715
failed with stage
in 30 seconds
Changes
457
Pipelines
620
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1882 additions
and
0 deletions
+1882
-0
core/src/main/java/com/taobao/arthas/core/command/monitor200/TraceEntity.java
...om/taobao/arthas/core/command/monitor200/TraceEntity.java
+29
-0
core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java
.../taobao/arthas/core/command/monitor200/VmToolCommand.java
+330
-0
core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java
...o/arthas/core/command/monitor200/WatchAdviceListener.java
+117
-0
core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java
...m/taobao/arthas/core/command/monitor200/WatchCommand.java
+203
-0
core/src/main/java/com/taobao/arthas/core/command/view/Base64View.java
.../java/com/taobao/arthas/core/command/view/Base64View.java
+22
-0
core/src/main/java/com/taobao/arthas/core/command/view/CatView.java
...ain/java/com/taobao/arthas/core/command/view/CatView.java
+17
-0
core/src/main/java/com/taobao/arthas/core/command/view/ClassLoaderView.java
.../com/taobao/arthas/core/command/view/ClassLoaderView.java
+180
-0
core/src/main/java/com/taobao/arthas/core/command/view/DashboardView.java
...va/com/taobao/arthas/core/command/view/DashboardView.java
+170
-0
core/src/main/java/com/taobao/arthas/core/command/view/DumpClassView.java
...va/com/taobao/arthas/core/command/view/DumpClassView.java
+57
-0
core/src/main/java/com/taobao/arthas/core/command/view/EchoView.java
...in/java/com/taobao/arthas/core/command/view/EchoView.java
+14
-0
core/src/main/java/com/taobao/arthas/core/command/view/EnhancerView.java
...ava/com/taobao/arthas/core/command/view/EnhancerView.java
+18
-0
core/src/main/java/com/taobao/arthas/core/command/view/GetStaticView.java
...va/com/taobao/arthas/core/command/view/GetStaticView.java
+34
-0
core/src/main/java/com/taobao/arthas/core/command/view/HelpView.java
...in/java/com/taobao/arthas/core/command/view/HelpView.java
+48
-0
core/src/main/java/com/taobao/arthas/core/command/view/JadView.java
...ain/java/com/taobao/arthas/core/command/view/JadView.java
+49
-0
core/src/main/java/com/taobao/arthas/core/command/view/JvmView.java
...ain/java/com/taobao/arthas/core/command/view/JvmView.java
+120
-0
core/src/main/java/com/taobao/arthas/core/command/view/LoggerView.java
.../java/com/taobao/arthas/core/command/view/LoggerView.java
+103
-0
core/src/main/java/com/taobao/arthas/core/command/view/MBeanView.java
...n/java/com/taobao/arthas/core/command/view/MBeanView.java
+211
-0
core/src/main/java/com/taobao/arthas/core/command/view/MemoryCompilerView.java
...m/taobao/arthas/core/command/view/MemoryCompilerView.java
+23
-0
core/src/main/java/com/taobao/arthas/core/command/view/MemoryView.java
.../java/com/taobao/arthas/core/command/view/MemoryView.java
+123
-0
core/src/main/java/com/taobao/arthas/core/command/view/MessageView.java
...java/com/taobao/arthas/core/command/view/MessageView.java
+14
-0
No files found.
Too many changes to show.
To preserve performance only
457 of 457+
files are displayed.
Plain diff
Email patch
core/src/main/java/com/taobao/arthas/core/command/monitor200/TraceEntity.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.monitor200
;
import
com.taobao.arthas.core.command.model.TraceModel
;
import
com.taobao.arthas.core.command.model.TraceTree
;
import
com.taobao.arthas.core.util.ThreadUtil
;
/**
* 用于在ThreadLocal中传递的实体
* @author ralf0131 2017-01-05 14:05.
*/
public
class
TraceEntity
{
protected
TraceTree
tree
;
protected
int
deep
;
public
TraceEntity
(
ClassLoader
loader
)
{
this
.
tree
=
createTraceTree
(
loader
);
this
.
deep
=
0
;
}
private
TraceTree
createTraceTree
(
ClassLoader
loader
)
{
return
new
TraceTree
(
ThreadUtil
.
getThreadNode
(
loader
,
Thread
.
currentThread
()));
}
public
TraceModel
getModel
()
{
tree
.
trim
();
return
new
TraceModel
(
tree
.
getRoot
(),
tree
.
getNodeCount
());
}
}
core/src/main/java/com/taobao/arthas/core/command/monitor200/VmToolCommand.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.monitor200
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.lang.instrument.Instrumentation
;
import
java.security.CodeSource
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.taobao.arthas.common.IOUtils
;
import
com.taobao.arthas.common.VmToolUtils
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.command.express.Express
;
import
com.taobao.arthas.core.command.express.ExpressException
;
import
com.taobao.arthas.core.command.express.ExpressFactory
;
import
com.taobao.arthas.core.command.model.ClassLoaderVO
;
import
com.taobao.arthas.core.command.model.ObjectVO
;
import
com.taobao.arthas.core.command.model.VmToolModel
;
import
com.taobao.arthas.core.shell.cli.Completion
;
import
com.taobao.arthas.core.shell.cli.CompletionUtils
;
import
com.taobao.arthas.core.shell.cli.OptionCompleteHandler
;
import
com.taobao.arthas.core.shell.command.AnnotatedCommand
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ClassLoaderUtils
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.arthas.core.util.SearchUtils
;
import
com.taobao.middleware.cli.annotations.DefaultValue
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Option
;
import
com.taobao.middleware.cli.annotations.Summary
;
import
arthas.VmTool
;
/**
*
* @author hengyunabc 2021-04-27
* @author ZhangZiCheng 2021-04-29
*
*/
//@formatter:off
@Name
(
"vmtool"
)
@Summary
(
"jvm tool"
)
@Description
(
Constants
.
EXAMPLE
+
" vmtool --action getInstances --className demo.MathGame\n"
+
" vmtool --action getInstances --className demo.MathGame --express 'instances.length'\n"
+
" vmtool --action getInstances --className demo.MathGame --express 'instances[0]'\n"
+
" vmtool --action getInstances --className demo.MathGame -x 2\n"
+
" vmtool --action getInstances --className java.lang.String --limit 10\n"
+
" vmtool --action getInstances --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --className org.springframework.context.ApplicationContext\n"
+
" vmtool --action forceGc\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"vmtool"
)
//@formatter:on
public
class
VmToolCommand
extends
AnnotatedCommand
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
VmToolCommand
.
class
);
private
VmToolAction
action
;
private
String
className
;
private
String
express
;
private
String
hashCode
=
null
;
private
String
classLoaderClass
;
/**
* default value 1
*/
private
int
expand
;
/**
* default value 10
*/
private
int
limit
;
private
String
libPath
;
private
static
String
defaultLibPath
;
private
static
VmTool
vmTool
=
null
;
static
{
String
libName
=
VmToolUtils
.
detectLibName
();
if
(
libName
!=
null
)
{
CodeSource
codeSource
=
VmToolCommand
.
class
.
getProtectionDomain
().
getCodeSource
();
if
(
codeSource
!=
null
)
{
try
{
File
bootJarPath
=
new
File
(
codeSource
.
getLocation
().
toURI
().
getSchemeSpecificPart
());
File
soFile
=
new
File
(
bootJarPath
.
getParentFile
(),
"lib"
+
File
.
separator
+
libName
);
if
(
soFile
.
exists
())
{
defaultLibPath
=
soFile
.
getAbsolutePath
();
}
}
catch
(
Throwable
e
)
{
logger
.
error
(
"can not find VmTool so"
,
e
);
}
}
}
}
@Option
(
shortName
=
"a"
,
longName
=
"action"
,
required
=
true
)
@Description
(
"Action to execute"
)
public
void
setAction
(
VmToolAction
action
)
{
this
.
action
=
action
;
}
@Option
(
longName
=
"className"
)
@Description
(
"The class name"
)
public
void
setClassName
(
String
className
)
{
this
.
className
=
className
;
}
@Option
(
shortName
=
"x"
,
longName
=
"expand"
)
@Description
(
"Expand level of object (1 by default)"
)
@DefaultValue
(
"1"
)
public
void
setExpand
(
int
expand
)
{
this
.
expand
=
expand
;
}
@Option
(
shortName
=
"c"
,
longName
=
"classloader"
)
@Description
(
"The hash code of the special class's classLoader"
)
public
void
setHashCode
(
String
hashCode
)
{
this
.
hashCode
=
hashCode
;
}
@Option
(
longName
=
"classLoaderClass"
)
@Description
(
"The class name of the special class's classLoader."
)
public
void
setClassLoaderClass
(
String
classLoaderClass
)
{
this
.
classLoaderClass
=
classLoaderClass
;
}
@Option
(
shortName
=
"l"
,
longName
=
"limit"
)
@Description
(
"Set the limit value of the getInstances action, default value is 10, set to -1 is unlimited"
)
@DefaultValue
(
"10"
)
public
void
setLimit
(
int
limit
)
{
this
.
limit
=
limit
;
}
@Option
(
longName
=
"libPath"
)
@Description
(
"The specify lib path."
)
public
void
setLibPath
(
String
path
)
{
libPath
=
path
;
}
@Option
(
longName
=
"express"
,
required
=
false
)
@Description
(
"The ognl expression, default valueis `instances`."
)
public
void
setExpress
(
String
express
)
{
this
.
express
=
express
;
}
public
enum
VmToolAction
{
getInstances
,
forceGc
}
@Override
public
void
process
(
final
CommandProcess
process
)
{
try
{
Instrumentation
inst
=
process
.
session
().
getInstrumentation
();
if
(
VmToolAction
.
getInstances
.
equals
(
action
))
{
if
(
className
==
null
)
{
process
.
end
(-
1
,
"The className option cannot be empty!"
);
return
;
}
ClassLoader
classLoader
=
null
;
if
(
hashCode
!=
null
)
{
classLoader
=
ClassLoaderUtils
.
getClassLoader
(
inst
,
hashCode
);
if
(
classLoader
==
null
)
{
process
.
end
(-
1
,
"Can not find classloader with hashCode: "
+
hashCode
+
"."
);
return
;
}
}
else
if
(
classLoaderClass
!=
null
)
{
List
<
ClassLoader
>
matchedClassLoaders
=
ClassLoaderUtils
.
getClassLoaderByClassName
(
inst
,
classLoaderClass
);
if
(
matchedClassLoaders
.
size
()
==
1
)
{
classLoader
=
matchedClassLoaders
.
get
(
0
);
hashCode
=
Integer
.
toHexString
(
matchedClassLoaders
.
get
(
0
).
hashCode
());
}
else
if
(
matchedClassLoaders
.
size
()
>
1
)
{
Collection
<
ClassLoaderVO
>
classLoaderVOList
=
ClassUtils
.
createClassLoaderVOList
(
matchedClassLoaders
);
VmToolModel
vmToolModel
=
new
VmToolModel
().
setClassLoaderClass
(
classLoaderClass
)
.
setMatchedClassLoaders
(
classLoaderVOList
);
process
.
appendResult
(
vmToolModel
);
process
.
end
(-
1
,
"Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'"
);
return
;
}
else
{
process
.
end
(-
1
,
"Can not find classloader by class name: "
+
classLoaderClass
+
"."
);
return
;
}
}
else
{
classLoader
=
ClassLoader
.
getSystemClassLoader
();
}
List
<
Class
<?>>
matchedClasses
=
new
ArrayList
<
Class
<?>>(
SearchUtils
.
searchClassOnly
(
inst
,
className
,
false
,
hashCode
));
int
matchedClassSize
=
matchedClasses
.
size
();
if
(
matchedClassSize
==
0
)
{
process
.
end
(-
1
,
"Can not find class by class name: "
+
className
+
"."
);
return
;
}
else
if
(
matchedClassSize
>
1
)
{
process
.
end
(-
1
,
"Found more than one class: "
+
matchedClasses
+
", please specify classloader with '-c <classloader hash>'"
);
return
;
}
else
{
Object
[]
instances
=
vmToolInstance
().
getInstances
(
matchedClasses
.
get
(
0
),
limit
);
Object
value
=
instances
;
if
(
express
!=
null
)
{
Express
unpooledExpress
=
ExpressFactory
.
unpooledExpress
(
classLoader
);
try
{
value
=
unpooledExpress
.
bind
(
new
InstancesWrapper
(
instances
)).
get
(
express
);
}
catch
(
ExpressException
e
)
{
logger
.
warn
(
"ognl: failed execute express: "
+
express
,
e
);
process
.
end
(-
1
,
"Failed to execute ognl, exception message: "
+
e
.
getMessage
()
+
", please check $HOME/logs/arthas/arthas.log for more details. "
);
}
}
VmToolModel
vmToolModel
=
new
VmToolModel
().
setValue
(
new
ObjectVO
(
value
,
expand
));
process
.
appendResult
(
vmToolModel
);
process
.
end
();
}
}
else
if
(
VmToolAction
.
forceGc
.
equals
(
action
))
{
vmToolInstance
().
forceGc
();
process
.
write
(
"\n"
);
process
.
end
();
return
;
}
process
.
end
();
}
catch
(
Throwable
e
)
{
logger
.
error
(
"vmtool error"
,
e
);
process
.
end
(
1
,
"vmtool error: "
+
e
.
getMessage
());
}
}
static
class
InstancesWrapper
{
Object
instances
;
public
InstancesWrapper
(
Object
instances
)
{
this
.
instances
=
instances
;
}
public
Object
getInstances
()
{
return
instances
;
}
public
void
setInstances
(
Object
instances
)
{
this
.
instances
=
instances
;
}
}
private
VmTool
vmToolInstance
()
{
if
(
vmTool
!=
null
)
{
return
vmTool
;
}
else
{
if
(
libPath
==
null
)
{
libPath
=
defaultLibPath
;
}
// 尝试把lib文件复制到临时文件里,避免多次attach时出现 Native Library already loaded in another classloader
FileOutputStream
tmpLibOutputStream
=
null
;
FileInputStream
libInputStream
=
null
;
try
{
File
tmpLibFile
=
File
.
createTempFile
(
VmTool
.
JNI_LIBRARY_NAME
,
null
);
tmpLibOutputStream
=
new
FileOutputStream
(
tmpLibFile
);
libInputStream
=
new
FileInputStream
(
libPath
);
IOUtils
.
copy
(
libInputStream
,
tmpLibOutputStream
);
libPath
=
tmpLibFile
.
getAbsolutePath
();
logger
.
debug
(
"copy {} to {}"
,
libPath
,
tmpLibFile
);
}
catch
(
Throwable
e
)
{
logger
.
error
(
"try to copy lib error! libPath: {}"
,
libPath
,
e
);
}
finally
{
IOUtils
.
close
(
libInputStream
);
IOUtils
.
close
(
tmpLibOutputStream
);
}
vmTool
=
VmTool
.
getInstance
(
libPath
);
}
return
vmTool
;
}
private
Set
<
String
>
actions
()
{
Set
<
String
>
values
=
new
HashSet
<
String
>();
for
(
VmToolAction
action
:
VmToolAction
.
values
())
{
values
.
add
(
action
.
toString
());
}
return
values
;
}
@Override
public
void
complete
(
Completion
completion
)
{
List
<
OptionCompleteHandler
>
handlers
=
new
ArrayList
<
OptionCompleteHandler
>();
handlers
.
add
(
new
OptionCompleteHandler
()
{
@Override
public
boolean
matchName
(
String
token
)
{
return
"-a"
.
equals
(
token
)
||
"--action"
.
equals
(
token
);
}
@Override
public
boolean
complete
(
Completion
completion
)
{
return
CompletionUtils
.
complete
(
completion
,
actions
());
}
});
handlers
.
add
(
new
OptionCompleteHandler
()
{
@Override
public
boolean
matchName
(
String
token
)
{
return
"--className"
.
equals
(
token
);
}
@Override
public
boolean
complete
(
Completion
completion
)
{
return
CompletionUtils
.
completeClassName
(
completion
);
}
});
if
(
CompletionUtils
.
completeOptions
(
completion
,
handlers
))
{
return
;
}
super
.
complete
(
completion
);
}
}
core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchAdviceListener.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.monitor200
;
import
com.alibaba.arthas.deps.org.slf4j.Logger
;
import
com.alibaba.arthas.deps.org.slf4j.LoggerFactory
;
import
com.taobao.arthas.core.advisor.AccessPoint
;
import
com.taobao.arthas.core.advisor.Advice
;
import
com.taobao.arthas.core.advisor.AdviceListenerAdapter
;
import
com.taobao.arthas.core.advisor.ArthasMethod
;
import
com.taobao.arthas.core.command.model.ObjectVO
;
import
com.taobao.arthas.core.command.model.WatchModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.LogUtil
;
import
com.taobao.arthas.core.util.ThreadLocalWatch
;
import
java.util.Date
;
/**
* @author beiwei30 on 29/11/2016.
*/
class
WatchAdviceListener
extends
AdviceListenerAdapter
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
WatchAdviceListener
.
class
);
private
final
ThreadLocalWatch
threadLocalWatch
=
new
ThreadLocalWatch
();
private
WatchCommand
command
;
private
CommandProcess
process
;
public
WatchAdviceListener
(
WatchCommand
command
,
CommandProcess
process
,
boolean
verbose
)
{
this
.
command
=
command
;
this
.
process
=
process
;
super
.
setVerbose
(
verbose
);
}
private
boolean
isFinish
()
{
return
command
.
isFinish
()
||
!
command
.
isBefore
()
&&
!
command
.
isException
()
&&
!
command
.
isSuccess
();
}
@Override
public
void
before
(
ClassLoader
loader
,
Class
<?>
clazz
,
ArthasMethod
method
,
Object
target
,
Object
[]
args
)
throws
Throwable
{
// 开始计算本次方法调用耗时
threadLocalWatch
.
start
();
if
(
command
.
isBefore
())
{
watching
(
Advice
.
newForBefore
(
loader
,
clazz
,
method
,
target
,
args
));
}
}
@Override
public
void
afterReturning
(
ClassLoader
loader
,
Class
<?>
clazz
,
ArthasMethod
method
,
Object
target
,
Object
[]
args
,
Object
returnObject
)
throws
Throwable
{
Advice
advice
=
Advice
.
newForAfterReturning
(
loader
,
clazz
,
method
,
target
,
args
,
returnObject
);
if
(
command
.
isSuccess
())
{
watching
(
advice
);
}
finishing
(
advice
);
}
@Override
public
void
afterThrowing
(
ClassLoader
loader
,
Class
<?>
clazz
,
ArthasMethod
method
,
Object
target
,
Object
[]
args
,
Throwable
throwable
)
{
Advice
advice
=
Advice
.
newForAfterThrowing
(
loader
,
clazz
,
method
,
target
,
args
,
throwable
);
if
(
command
.
isException
())
{
watching
(
advice
);
}
finishing
(
advice
);
}
private
void
finishing
(
Advice
advice
)
{
if
(
isFinish
())
{
watching
(
advice
);
}
}
private
void
watching
(
Advice
advice
)
{
try
{
// 本次调用的耗时
double
cost
=
threadLocalWatch
.
costInMillis
();
boolean
conditionResult
=
isConditionMet
(
command
.
getConditionExpress
(),
advice
,
cost
);
if
(
this
.
isVerbose
())
{
process
.
write
(
"Condition express: "
+
command
.
getConditionExpress
()
+
" , result: "
+
conditionResult
+
"\n"
);
}
if
(
conditionResult
)
{
// TODO: concurrency issues for process.write
Object
value
=
getExpressionResult
(
command
.
getExpress
(),
advice
,
cost
);
WatchModel
model
=
new
WatchModel
();
model
.
setTs
(
new
Date
());
model
.
setCost
(
cost
);
model
.
setValue
(
new
ObjectVO
(
value
,
command
.
getExpand
()));
model
.
setSizeLimit
(
command
.
getSizeLimit
());
model
.
setClassName
(
advice
.
getClazz
().
getName
());
model
.
setMethodName
(
advice
.
getMethod
().
getName
());
if
(
advice
.
isBefore
())
{
model
.
setAccessPoint
(
AccessPoint
.
ACCESS_BEFORE
.
getKey
());
}
else
if
(
advice
.
isAfterReturning
())
{
model
.
setAccessPoint
(
AccessPoint
.
ACCESS_AFTER_RETUNING
.
getKey
());
}
else
if
(
advice
.
isAfterThrowing
())
{
model
.
setAccessPoint
(
AccessPoint
.
ACCESS_AFTER_THROWING
.
getKey
());
}
process
.
appendResult
(
model
);
process
.
times
().
incrementAndGet
();
if
(
isLimitExceeded
(
command
.
getNumberOfLimit
(),
process
.
times
().
get
()))
{
abortProcess
(
process
,
command
.
getNumberOfLimit
());
}
}
}
catch
(
Throwable
e
)
{
logger
.
warn
(
"watch failed."
,
e
);
process
.
end
(-
1
,
"watch failed, condition is: "
+
command
.
getConditionExpress
()
+
", express is: "
+
command
.
getExpress
()
+
", "
+
e
.
getMessage
()
+
", visit "
+
LogUtil
.
loggingFile
()
+
" for more details."
);
}
}
}
core/src/main/java/com/taobao/arthas/core/command/monitor200/WatchCommand.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.monitor200
;
import
java.util.Arrays
;
import
com.taobao.arthas.core.GlobalOptions
;
import
com.taobao.arthas.core.advisor.AdviceListener
;
import
com.taobao.arthas.core.command.Constants
;
import
com.taobao.arthas.core.shell.cli.Completion
;
import
com.taobao.arthas.core.shell.cli.CompletionUtils
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.SearchUtils
;
import
com.taobao.arthas.core.util.matcher.Matcher
;
import
com.taobao.arthas.core.view.ObjectView
;
import
com.taobao.middleware.cli.annotations.Argument
;
import
com.taobao.middleware.cli.annotations.DefaultValue
;
import
com.taobao.middleware.cli.annotations.Description
;
import
com.taobao.middleware.cli.annotations.Name
;
import
com.taobao.middleware.cli.annotations.Option
;
import
com.taobao.middleware.cli.annotations.Summary
;
@Name
(
"watch"
)
@Summary
(
"Display the input/output parameter, return object, and thrown exception of specified method invocation"
)
@Description
(
Constants
.
EXPRESS_DESCRIPTION
+
"\nExamples:\n"
+
" watch org.apache.commons.lang.StringUtils isBlank\n"
+
" watch org.apache.commons.lang.StringUtils isBlank '{params, target, returnObj, throwExp}' -x 2\n"
+
" watch *StringUtils isBlank params[0] params[0].length==1\n"
+
" watch *StringUtils isBlank params '#cost>100'\n"
+
" watch -f *StringUtils isBlank params\n"
+
" watch *StringUtils isBlank params[0]\n"
+
" watch -E -b org\\.apache\\.commons\\.lang\\.StringUtils isBlank params[0]\n"
+
" watch javax.servlet.Filter * --exclude-class-pattern com.demo.TestFilter\n"
+
" watch OuterClass$InnerClass\n"
+
Constants
.
WIKI
+
Constants
.
WIKI_HOME
+
"watch"
)
public
class
WatchCommand
extends
EnhancerCommand
{
private
String
classPattern
;
private
String
methodPattern
;
private
String
express
;
private
String
conditionExpress
;
private
boolean
isBefore
=
false
;
private
boolean
isFinish
=
false
;
private
boolean
isException
=
false
;
private
boolean
isSuccess
=
false
;
private
Integer
expand
=
1
;
private
Integer
sizeLimit
=
10
*
1024
*
1024
;
private
boolean
isRegEx
=
false
;
private
int
numberOfLimit
=
100
;
@Argument
(
index
=
0
,
argName
=
"class-pattern"
)
@Description
(
"The full qualified class name you want to watch"
)
public
void
setClassPattern
(
String
classPattern
)
{
this
.
classPattern
=
classPattern
;
}
@Argument
(
index
=
1
,
argName
=
"method-pattern"
)
@Description
(
"The method name you want to watch"
)
public
void
setMethodPattern
(
String
methodPattern
)
{
this
.
methodPattern
=
methodPattern
;
}
@Argument
(
index
=
2
,
argName
=
"express"
,
required
=
false
)
@DefaultValue
(
"{params, target, returnObj}"
)
@Description
(
"The content you want to watch, written by ognl. Default value is '{params, target, returnObj}'\n"
+
Constants
.
EXPRESS_EXAMPLES
)
public
void
setExpress
(
String
express
)
{
this
.
express
=
express
;
}
@Argument
(
index
=
3
,
argName
=
"condition-express"
,
required
=
false
)
@Description
(
Constants
.
CONDITION_EXPRESS
)
public
void
setConditionExpress
(
String
conditionExpress
)
{
this
.
conditionExpress
=
conditionExpress
;
}
@Option
(
shortName
=
"b"
,
longName
=
"before"
,
flag
=
true
)
@Description
(
"Watch before invocation"
)
public
void
setBefore
(
boolean
before
)
{
isBefore
=
before
;
}
@Option
(
shortName
=
"f"
,
longName
=
"finish"
,
flag
=
true
)
@Description
(
"Watch after invocation, enable by default"
)
public
void
setFinish
(
boolean
finish
)
{
isFinish
=
finish
;
}
@Option
(
shortName
=
"e"
,
longName
=
"exception"
,
flag
=
true
)
@Description
(
"Watch after throw exception"
)
public
void
setException
(
boolean
exception
)
{
isException
=
exception
;
}
@Option
(
shortName
=
"s"
,
longName
=
"success"
,
flag
=
true
)
@Description
(
"Watch after successful invocation"
)
public
void
setSuccess
(
boolean
success
)
{
isSuccess
=
success
;
}
@Option
(
shortName
=
"M"
,
longName
=
"sizeLimit"
)
@Description
(
"Upper size limit in bytes for the result (10 * 1024 * 1024 by default)"
)
public
void
setSizeLimit
(
Integer
sizeLimit
)
{
this
.
sizeLimit
=
sizeLimit
;
}
@Option
(
shortName
=
"x"
,
longName
=
"expand"
)
@Description
(
"Expand level of object (1 by default), the max value is "
+
ObjectView
.
MAX_DEEP
)
public
void
setExpand
(
Integer
expand
)
{
this
.
expand
=
expand
;
}
@Option
(
shortName
=
"E"
,
longName
=
"regex"
,
flag
=
true
)
@Description
(
"Enable regular expression to match (wildcard matching by default)"
)
public
void
setRegEx
(
boolean
regEx
)
{
isRegEx
=
regEx
;
}
@Option
(
shortName
=
"n"
,
longName
=
"limits"
)
@Description
(
"Threshold of execution times"
)
public
void
setNumberOfLimit
(
int
numberOfLimit
)
{
this
.
numberOfLimit
=
numberOfLimit
;
}
public
String
getClassPattern
()
{
return
classPattern
;
}
public
String
getMethodPattern
()
{
return
methodPattern
;
}
public
String
getExpress
()
{
return
express
;
}
public
String
getConditionExpress
()
{
return
conditionExpress
;
}
public
boolean
isBefore
()
{
return
isBefore
;
}
public
boolean
isFinish
()
{
return
isFinish
;
}
public
boolean
isException
()
{
return
isException
;
}
public
boolean
isSuccess
()
{
return
isSuccess
;
}
public
Integer
getExpand
()
{
return
expand
;
}
public
Integer
getSizeLimit
()
{
return
sizeLimit
;
}
public
boolean
isRegEx
()
{
return
isRegEx
;
}
public
int
getNumberOfLimit
()
{
return
numberOfLimit
;
}
@Override
protected
Matcher
getClassNameMatcher
()
{
if
(
classNameMatcher
==
null
)
{
classNameMatcher
=
SearchUtils
.
classNameMatcher
(
getClassPattern
(),
isRegEx
());
}
return
classNameMatcher
;
}
@Override
protected
Matcher
getClassNameExcludeMatcher
()
{
if
(
classNameExcludeMatcher
==
null
&&
getExcludeClassPattern
()
!=
null
)
{
classNameExcludeMatcher
=
SearchUtils
.
classNameMatcher
(
getExcludeClassPattern
(),
isRegEx
());
}
return
classNameExcludeMatcher
;
}
@Override
protected
Matcher
getMethodNameMatcher
()
{
if
(
methodNameMatcher
==
null
)
{
methodNameMatcher
=
SearchUtils
.
classNameMatcher
(
getMethodPattern
(),
isRegEx
());
}
return
methodNameMatcher
;
}
@Override
protected
AdviceListener
getAdviceListener
(
CommandProcess
process
)
{
return
new
WatchAdviceListener
(
this
,
process
,
GlobalOptions
.
verbose
||
this
.
verbose
);
}
@Override
protected
void
completeArgument3
(
Completion
completion
)
{
CompletionUtils
.
complete
(
completion
,
Arrays
.
asList
(
EXPRESS_EXAMPLES
));
}
}
core/src/main/java/com/taobao/arthas/core/command/view/Base64View.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.Base64Model
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
/**
*
* @author hengyunabc 2021-01-05
*
*/
public
class
Base64View
extends
ResultView
<
Base64Model
>
{
@Override
public
void
draw
(
CommandProcess
process
,
Base64Model
result
)
{
String
content
=
result
.
getContent
();
if
(
content
!=
null
)
{
process
.
write
(
content
);
}
process
.
write
(
"\n"
);
}
}
core/src/main/java/com/taobao/arthas/core/command/view/CatView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.CatModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
/**
* Result view for CatCommand
* @author gongdewei 2020/5/11
*/
public
class
CatView
extends
ResultView
<
CatModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
CatModel
result
)
{
process
.
write
(
result
.
getContent
()).
write
(
"\n"
);
}
}
core/src/main/java/com/taobao/arthas/core/command/view/ClassLoaderView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderStat
;
import
com.taobao.arthas.core.command.klass100.ClassLoaderCommand.ClassLoaderUrlStat
;
import
com.taobao.arthas.core.command.model.ClassDetailVO
;
import
com.taobao.arthas.core.command.model.ClassLoaderModel
;
import
com.taobao.arthas.core.command.model.ClassLoaderVO
;
import
com.taobao.arthas.core.command.model.ClassSetVO
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.ui.*
;
import
com.taobao.text.util.RenderUtil
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
/**
* @author gongdewei 2020/4/21
*/
public
class
ClassLoaderView
extends
ResultView
<
ClassLoaderModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
ClassLoaderModel
result
)
{
if
(
result
.
getMatchedClassLoaders
()
!=
null
)
{
process
.
write
(
"Matched classloaders: \n"
);
drawClassLoaders
(
process
,
result
.
getMatchedClassLoaders
(),
false
);
process
.
write
(
"\n"
);
return
;
}
if
(
result
.
getClassSet
()
!=
null
)
{
drawAllClasses
(
process
,
result
.
getClassSet
());
}
if
(
result
.
getResources
()
!=
null
)
{
drawResources
(
process
,
result
.
getResources
());
}
if
(
result
.
getLoadClass
()
!=
null
)
{
drawLoadClass
(
process
,
result
.
getLoadClass
());
}
if
(
result
.
getUrls
()
!=
null
)
{
drawClassLoaderUrls
(
process
,
result
.
getUrls
());
}
if
(
result
.
getClassLoaders
()
!=
null
){
drawClassLoaders
(
process
,
result
.
getClassLoaders
(),
result
.
getTree
());
}
if
(
result
.
getClassLoaderStats
()
!=
null
){
drawClassLoaderStats
(
process
,
result
.
getClassLoaderStats
());
}
if
(
result
.
getUrlStats
()
!=
null
)
{
drawUrlStats
(
process
,
result
.
getUrlStats
());
}
}
private
void
drawUrlStats
(
CommandProcess
process
,
Map
<
ClassLoaderVO
,
ClassLoaderUrlStat
>
urlStats
)
{
for
(
Entry
<
ClassLoaderVO
,
ClassLoaderUrlStat
>
entry
:
urlStats
.
entrySet
())
{
ClassLoaderVO
classLoaderVO
=
entry
.
getKey
();
ClassLoaderUrlStat
urlStat
=
entry
.
getValue
();
// 忽略 sun.reflect.DelegatingClassLoader 等动态ClassLoader
if
(
urlStat
.
getUsedUrls
().
isEmpty
()
&&
urlStat
.
getUnUsedUrls
().
isEmpty
())
{
continue
;
}
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
row
(
new
LabelElement
(
classLoaderVO
.
getName
()
+
", hash:"
+
classLoaderVO
.
getHash
())
.
style
(
Decoration
.
bold
.
bold
()));
Collection
<
String
>
usedUrls
=
urlStat
.
getUsedUrls
();
table
.
row
(
new
LabelElement
(
"Used URLs:"
).
style
(
Decoration
.
bold
.
bold
()));
for
(
String
url
:
usedUrls
)
{
table
.
row
(
url
);
}
Collection
<
String
>
UnnsedUrls
=
urlStat
.
getUnUsedUrls
();
table
.
row
(
new
LabelElement
(
"Unused URLs:"
).
style
(
Decoration
.
bold
.
bold
()));
for
(
String
url
:
UnnsedUrls
)
{
table
.
row
(
url
);
}
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
()))
.
write
(
"\n"
);
}
}
private
void
drawClassLoaderStats
(
CommandProcess
process
,
Map
<
String
,
ClassLoaderStat
>
classLoaderStats
)
{
Element
element
=
renderStat
(
classLoaderStats
);
process
.
write
(
RenderUtil
.
render
(
element
,
process
.
width
()))
.
write
(
com
.
taobao
.
arthas
.
core
.
util
.
Constants
.
EMPTY_STRING
);
}
private
static
TableElement
renderStat
(
Map
<
String
,
ClassLoaderStat
>
classLoaderStats
)
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
bold
()).
add
(
"name"
,
"numberOfInstances"
,
"loadedCountTotal"
));
for
(
Map
.
Entry
<
String
,
ClassLoaderStat
>
entry
:
classLoaderStats
.
entrySet
())
{
table
.
row
(
entry
.
getKey
(),
""
+
entry
.
getValue
().
getNumberOfInstance
(),
""
+
entry
.
getValue
().
getLoadedCount
());
}
return
table
;
}
public
static
void
drawClassLoaders
(
CommandProcess
process
,
Collection
<
ClassLoaderVO
>
classLoaders
,
boolean
isTree
)
{
Element
element
=
isTree
?
renderTree
(
classLoaders
)
:
renderTable
(
classLoaders
);
process
.
write
(
RenderUtil
.
render
(
element
,
process
.
width
()))
.
write
(
com
.
taobao
.
arthas
.
core
.
util
.
Constants
.
EMPTY_STRING
);
}
private
void
drawClassLoaderUrls
(
CommandProcess
process
,
List
<
String
>
urls
)
{
process
.
write
(
RenderUtil
.
render
(
renderClassLoaderUrls
(
urls
),
process
.
width
()));
process
.
write
(
com
.
taobao
.
arthas
.
core
.
util
.
Constants
.
EMPTY_STRING
);
}
private
void
drawLoadClass
(
CommandProcess
process
,
ClassDetailVO
loadClass
)
{
process
.
write
(
RenderUtil
.
render
(
ClassUtils
.
renderClassInfo
(
loadClass
),
process
.
width
())
+
"\n"
);
}
private
void
drawAllClasses
(
CommandProcess
process
,
ClassSetVO
classSetVO
)
{
process
.
write
(
RenderUtil
.
render
(
renderClasses
(
classSetVO
),
process
.
width
()));
process
.
write
(
"\n"
);
}
private
void
drawResources
(
CommandProcess
process
,
List
<
String
>
resources
)
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
for
(
String
resource
:
resources
)
{
table
.
row
(
resource
);
}
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
())
+
"\n"
);
process
.
write
(
com
.
taobao
.
arthas
.
core
.
util
.
Constants
.
EMPTY_STRING
);
}
private
Element
renderClasses
(
ClassSetVO
classSetVO
)
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
if
(
classSetVO
.
getSegment
()
==
0
)
{
table
.
row
(
new
LabelElement
(
"hash:"
+
classSetVO
.
getClassloader
().
getHash
()
+
", "
+
classSetVO
.
getClassloader
().
getName
())
.
style
(
Decoration
.
bold
.
bold
()));
}
for
(
String
className
:
classSetVO
.
getClasses
())
{
table
.
row
(
new
LabelElement
(
className
));
}
return
table
;
}
private
static
Element
renderClassLoaderUrls
(
List
<
String
>
urls
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
String
url
:
urls
)
{
sb
.
append
(
url
).
append
(
"\n"
);
}
return
new
LabelElement
(
sb
.
toString
());
}
// 统计所有的ClassLoader的信息
private
static
TableElement
renderTable
(
Collection
<
ClassLoaderVO
>
classLoaderInfos
)
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
bold
()).
add
(
"name"
,
"loadedCount"
,
"hash"
,
"parent"
));
for
(
ClassLoaderVO
classLoaderVO
:
classLoaderInfos
)
{
table
.
row
(
classLoaderVO
.
getName
(),
""
+
classLoaderVO
.
getLoadedCount
(),
classLoaderVO
.
getHash
(),
classLoaderVO
.
getParent
());
}
return
table
;
}
// 以树状列出ClassLoader的继承结构
private
static
Element
renderTree
(
Collection
<
ClassLoaderVO
>
classLoaderInfos
)
{
TreeElement
root
=
new
TreeElement
();
for
(
ClassLoaderVO
classLoader
:
classLoaderInfos
)
{
TreeElement
child
=
new
TreeElement
(
classLoader
.
getName
());
root
.
addChild
(
child
);
renderSubtree
(
child
,
classLoader
);
}
return
root
;
}
private
static
void
renderSubtree
(
TreeElement
parent
,
ClassLoaderVO
parentClassLoader
)
{
if
(
parentClassLoader
.
getChildren
()
==
null
){
return
;
}
for
(
ClassLoaderVO
childClassLoader
:
parentClassLoader
.
getChildren
())
{
TreeElement
child
=
new
TreeElement
(
childClassLoader
.
getName
());
parent
.
addChild
(
child
);
renderSubtree
(
child
,
childClassLoader
);
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/DashboardView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.*
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.text.Color
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.ui.RowElement
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
/**
* View of 'dashboard' command
*
* @author gongdewei 2020/4/22
*/
public
class
DashboardView
extends
ResultView
<
DashboardModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
DashboardModel
result
)
{
int
width
=
process
.
width
();
int
height
=
process
.
height
();
// 上半部分放thread top。下半部分再切分为田字格,其中上面两格放memory, gc的信息。下面两格放tomcat,
// runtime的信息
int
totalHeight
=
height
-
1
;
int
threadTopHeight
;
if
(
totalHeight
<=
24
)
{
//总高度较小时取1/2
threadTopHeight
=
totalHeight
/
2
;
}
else
{
//总高度较大时取1/3,但不少于上面的值(24/2=12)
threadTopHeight
=
totalHeight
/
3
;
if
(
threadTopHeight
<
12
)
{
threadTopHeight
=
12
;
}
}
int
lowerHalf
=
totalHeight
-
threadTopHeight
;
//Memory至少保留8行, 显示metaspace信息
int
memoryInfoHeight
=
lowerHalf
/
2
;
if
(
memoryInfoHeight
<
8
)
{
memoryInfoHeight
=
Math
.
min
(
8
,
lowerHalf
);
}
//runtime
TableElement
runtimeInfoTable
=
drawRuntimeInfo
(
result
.
getRuntimeInfo
());
//tomcat
TableElement
tomcatInfoTable
=
drawTomcatInfo
(
result
.
getTomcatInfo
());
int
runtimeInfoHeight
=
Math
.
max
(
runtimeInfoTable
.
getRows
().
size
(),
tomcatInfoTable
==
null
?
0
:
tomcatInfoTable
.
getRows
().
size
());
if
(
runtimeInfoHeight
<
lowerHalf
-
memoryInfoHeight
)
{
//如果runtimeInfo高度有剩余,则增大MemoryInfo的高度
memoryInfoHeight
=
lowerHalf
-
runtimeInfoHeight
;
}
else
{
runtimeInfoHeight
=
lowerHalf
-
memoryInfoHeight
;
}
//如果MemoryInfo高度有剩余,则增大ThreadHeight
int
maxMemoryInfoHeight
=
getMemoryInfoHeight
(
result
.
getMemoryInfo
());
memoryInfoHeight
=
Math
.
min
(
memoryInfoHeight
,
maxMemoryInfoHeight
);
threadTopHeight
=
totalHeight
-
memoryInfoHeight
-
runtimeInfoHeight
;
String
threadInfo
=
ViewRenderUtil
.
drawThreadInfo
(
result
.
getThreads
(),
width
,
threadTopHeight
);
String
memoryAndGc
=
drawMemoryInfoAndGcInfo
(
result
.
getMemoryInfo
(),
result
.
getGcInfos
(),
width
,
memoryInfoHeight
);
String
runTimeAndTomcat
=
drawRuntimeInfoAndTomcatInfo
(
runtimeInfoTable
,
tomcatInfoTable
,
width
,
runtimeInfoHeight
);
process
.
write
(
threadInfo
+
memoryAndGc
+
runTimeAndTomcat
);
}
static
String
drawMemoryInfoAndGcInfo
(
Map
<
String
,
List
<
MemoryEntryVO
>>
memoryInfo
,
List
<
GcInfoVO
>
gcInfos
,
int
width
,
int
height
)
{
TableElement
table
=
new
TableElement
(
1
,
1
);
TableElement
memoryInfoTable
=
MemoryView
.
drawMemoryInfo
(
memoryInfo
);
TableElement
gcInfoTable
=
drawGcInfo
(
gcInfos
);
table
.
row
(
memoryInfoTable
,
gcInfoTable
);
return
RenderUtil
.
render
(
table
,
width
,
height
);
}
private
static
int
getMemoryInfoHeight
(
Map
<
String
,
List
<
MemoryEntryVO
>>
memoryInfo
)
{
int
height
=
1
;
for
(
List
<
MemoryEntryVO
>
memoryEntryVOS
:
memoryInfo
.
values
())
{
height
+=
memoryEntryVOS
.
size
();
}
return
height
;
}
private
static
TableElement
drawGcInfo
(
List
<
GcInfoVO
>
gcInfos
)
{
TableElement
table
=
new
TableElement
(
1
,
1
).
rightCellPadding
(
1
);
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
fg
(
Color
.
black
).
bg
(
Color
.
white
)).
add
(
"GC"
,
""
));
for
(
GcInfoVO
gcInfo
:
gcInfos
)
{
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
bold
()).
add
(
"gc."
+
gcInfo
.
getName
()
+
".count"
,
""
+
gcInfo
.
getCollectionCount
()));
table
.
row
(
"gc."
+
gcInfo
.
getName
()
+
".time(ms)"
,
""
+
gcInfo
.
getCollectionTime
());
}
return
table
;
}
String
drawRuntimeInfoAndTomcatInfo
(
TableElement
runtimeInfoTable
,
TableElement
tomcatInfoTable
,
int
width
,
int
height
)
{
if
(
height
<=
0
)
{
return
""
;
}
TableElement
resultTable
=
new
TableElement
(
1
,
1
);
if
(
tomcatInfoTable
!=
null
)
{
resultTable
.
row
(
runtimeInfoTable
,
tomcatInfoTable
);
}
else
{
resultTable
=
runtimeInfoTable
;
}
return
RenderUtil
.
render
(
resultTable
,
width
,
height
);
}
private
static
TableElement
drawRuntimeInfo
(
RuntimeInfoVO
runtimeInfo
)
{
TableElement
table
=
new
TableElement
(
1
,
1
).
rightCellPadding
(
1
);
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
fg
(
Color
.
black
).
bg
(
Color
.
white
)).
add
(
"Runtime"
,
""
));
table
.
row
(
"os.name"
,
runtimeInfo
.
getOsName
());
table
.
row
(
"os.version"
,
runtimeInfo
.
getOsVersion
());
table
.
row
(
"java.version"
,
runtimeInfo
.
getJavaVersion
());
table
.
row
(
"java.home"
,
runtimeInfo
.
getJavaHome
());
table
.
row
(
"systemload.average"
,
String
.
format
(
"%.2f"
,
runtimeInfo
.
getSystemLoadAverage
()));
table
.
row
(
"processors"
,
""
+
runtimeInfo
.
getProcessors
());
table
.
row
(
"timestamp/uptime"
,
new
Date
(
runtimeInfo
.
getTimestamp
()).
toString
()
+
"/"
+
runtimeInfo
.
getUptime
()
+
"s"
);
return
table
;
}
private
static
String
formatBytes
(
long
size
)
{
int
unit
=
1
;
String
unitStr
=
"B"
;
if
(
size
/
1024
>
0
)
{
unit
=
1024
;
unitStr
=
"K"
;
}
else
if
(
size
/
1024
/
1024
>
0
)
{
unit
=
1024
*
1024
;
unitStr
=
"M"
;
}
return
String
.
format
(
"%d%s"
,
size
/
unit
,
unitStr
);
}
private
TableElement
drawTomcatInfo
(
TomcatInfoVO
tomcatInfo
)
{
if
(
tomcatInfo
==
null
)
{
return
null
;
}
//header
TableElement
table
=
new
TableElement
(
1
,
1
).
rightCellPadding
(
1
);
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
fg
(
Color
.
black
).
bg
(
Color
.
white
)).
add
(
"Tomcat"
,
""
));
if
(
tomcatInfo
.
getConnectorStats
()
!=
null
)
{
for
(
TomcatInfoVO
.
ConnectorStats
connectorStat
:
tomcatInfo
.
getConnectorStats
())
{
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
bold
()).
add
(
"connector"
,
connectorStat
.
getName
()));
table
.
row
(
"QPS"
,
String
.
format
(
"%.2f"
,
connectorStat
.
getQps
()));
table
.
row
(
"RT(ms)"
,
String
.
format
(
"%.2f"
,
connectorStat
.
getRt
()));
table
.
row
(
"error/s"
,
String
.
format
(
"%.2f"
,
connectorStat
.
getError
()));
table
.
row
(
"received/s"
,
formatBytes
(
connectorStat
.
getReceived
()));
table
.
row
(
"sent/s"
,
formatBytes
(
connectorStat
.
getSent
()));
}
}
if
(
tomcatInfo
.
getThreadPools
()
!=
null
)
{
for
(
TomcatInfoVO
.
ThreadPool
threadPool
:
tomcatInfo
.
getThreadPools
())
{
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
bold
()).
add
(
"threadpool"
,
threadPool
.
getName
()));
table
.
row
(
"busy"
,
""
+
threadPool
.
getBusy
());
table
.
row
(
"total"
,
""
+
threadPool
.
getTotal
());
}
}
return
table
;
}
}
core/src/main/java/com/taobao/arthas/core/command/view/DumpClassView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.DumpClassModel
;
import
com.taobao.arthas.core.command.model.DumpClassVO
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.arthas.core.util.TypeRenderUtils
;
import
com.taobao.text.Color
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.ui.Element
;
import
com.taobao.text.ui.LabelElement
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
import
java.util.List
;
import
static
com
.
taobao
.
text
.
ui
.
Element
.
label
;
/**
* @author gongdewei 2020/4/21
*/
public
class
DumpClassView
extends
ResultView
<
DumpClassModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
DumpClassModel
result
)
{
if
(
result
.
getMatchedClassLoaders
()
!=
null
)
{
process
.
write
(
"Matched classloaders: \n"
);
ClassLoaderView
.
drawClassLoaders
(
process
,
result
.
getMatchedClassLoaders
(),
false
);
process
.
write
(
"\n"
);
return
;
}
if
(
result
.
getDumpedClasses
()
!=
null
)
{
drawDumpedClasses
(
process
,
result
.
getDumpedClasses
());
}
else
if
(
result
.
getMatchedClasses
()
!=
null
)
{
Element
table
=
ClassUtils
.
renderMatchedClasses
(
result
.
getMatchedClasses
());
process
.
write
(
RenderUtil
.
render
(
table
)).
write
(
"\n"
);
}
}
private
void
drawDumpedClasses
(
CommandProcess
process
,
List
<
DumpClassVO
>
classVOs
)
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
row
(
new
LabelElement
(
"HASHCODE"
).
style
(
Decoration
.
bold
.
bold
()),
new
LabelElement
(
"CLASSLOADER"
).
style
(
Decoration
.
bold
.
bold
()),
new
LabelElement
(
"LOCATION"
).
style
(
Decoration
.
bold
.
bold
()));
for
(
DumpClassVO
clazz
:
classVOs
)
{
table
.
row
(
label
(
clazz
.
getClassLoaderHash
()).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)),
TypeRenderUtils
.
drawClassLoader
(
clazz
),
label
(
clazz
.
getLocation
()).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)));
}
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
()))
.
write
(
com
.
taobao
.
arthas
.
core
.
util
.
Constants
.
EMPTY_STRING
);
}
}
core/src/main/java/com/taobao/arthas/core/command/view/EchoView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.EchoModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
/**
* @author gongdewei 2020/5/11
*/
public
class
EchoView
extends
ResultView
<
EchoModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
EchoModel
result
)
{
process
.
write
(
result
.
getContent
()).
write
(
"\n"
);
}
}
core/src/main/java/com/taobao/arthas/core/command/view/EnhancerView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.EnhancerModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
/**
* Term view for EnhancerModel
* @author gongdewei 2020/7/21
*/
public
class
EnhancerView
extends
ResultView
<
EnhancerModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
EnhancerModel
result
)
{
// ignore enhance result status, judge by the following output
if
(
result
.
getEffect
()
!=
null
)
{
process
.
write
(
ViewRenderUtil
.
renderEnhancerAffect
(
result
.
getEffect
()));
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/GetStaticView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.GetStaticModel
;
import
com.taobao.arthas.core.command.model.ObjectVO
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.arthas.core.util.StringUtils
;
import
com.taobao.arthas.core.view.ObjectView
;
import
com.taobao.text.ui.Element
;
import
com.taobao.text.util.RenderUtil
;
/**
* @author gongdewei 2020/4/20
*/
public
class
GetStaticView
extends
ResultView
<
GetStaticModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
GetStaticModel
result
)
{
if
(
result
.
getMatchedClassLoaders
()
!=
null
)
{
process
.
write
(
"Matched classloaders: \n"
);
ClassLoaderView
.
drawClassLoaders
(
process
,
result
.
getMatchedClassLoaders
(),
false
);
process
.
write
(
"\n"
);
return
;
}
if
(
result
.
getField
()
!=
null
)
{
ObjectVO
field
=
result
.
getField
();
String
valueStr
=
StringUtils
.
objectToString
(
field
.
needExpand
()
?
new
ObjectView
(
field
).
draw
()
:
field
.
getObject
());
process
.
write
(
"field: "
+
result
.
getFieldName
()
+
"\n"
+
valueStr
+
"\n"
);
}
else
if
(
result
.
getMatchedClasses
()
!=
null
)
{
Element
table
=
ClassUtils
.
renderMatchedClasses
(
result
.
getMatchedClasses
());
process
.
write
(
RenderUtil
.
render
(
table
)).
write
(
"\n"
);
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/HelpView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.CommandVO
;
import
com.taobao.arthas.core.command.model.HelpModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.usage.StyledUsageFormatter
;
import
com.taobao.middleware.cli.CLI
;
import
com.taobao.text.Color
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.Style
;
import
com.taobao.text.ui.Element
;
import
com.taobao.text.ui.LabelElement
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
import
java.util.List
;
import
static
com
.
taobao
.
text
.
ui
.
Element
.
label
;
import
static
com
.
taobao
.
text
.
ui
.
Element
.
row
;
/**
* @author gongdewei 2020/4/3
*/
public
class
HelpView
extends
ResultView
<
HelpModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
HelpModel
result
)
{
if
(
result
.
getCommands
()
!=
null
)
{
String
message
=
RenderUtil
.
render
(
mainHelp
(
result
.
getCommands
()),
process
.
width
());
process
.
write
(
message
);
}
else
if
(
result
.
getDetailCommand
()
!=
null
)
{
process
.
write
(
commandHelp
(
result
.
getDetailCommand
().
cli
(),
process
.
width
()));
}
}
private
static
Element
mainHelp
(
List
<
CommandVO
>
commands
)
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
row
(
new
LabelElement
(
"NAME"
).
style
(
Style
.
style
(
Decoration
.
bold
)),
new
LabelElement
(
"DESCRIPTION"
));
for
(
CommandVO
commandVO
:
commands
)
{
table
.
add
(
row
().
add
(
label
(
commandVO
.
getName
()).
style
(
Style
.
style
(
Color
.
green
))).
add
(
label
(
commandVO
.
getSummary
())));
}
return
table
;
}
private
static
String
commandHelp
(
CLI
command
,
int
width
)
{
return
StyledUsageFormatter
.
styledUsage
(
command
,
width
);
}
}
core/src/main/java/com/taobao/arthas/core/command/view/JadView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.ClassVO
;
import
com.taobao.arthas.core.command.model.JadModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.ClassUtils
;
import
com.taobao.arthas.core.util.TypeRenderUtils
;
import
com.taobao.text.Color
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.lang.LangRenderUtil
;
import
com.taobao.text.ui.Element
;
import
com.taobao.text.ui.LabelElement
;
import
com.taobao.text.util.RenderUtil
;
/**
* @author gongdewei 2020/4/22
*/
public
class
JadView
extends
ResultView
<
JadModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
JadModel
result
)
{
if
(
result
.
getMatchedClassLoaders
()
!=
null
)
{
process
.
write
(
"Matched classloaders: \n"
);
ClassLoaderView
.
drawClassLoaders
(
process
,
result
.
getMatchedClassLoaders
(),
false
);
process
.
write
(
"\n"
);
return
;
}
int
width
=
process
.
width
();
if
(
result
.
getMatchedClasses
()
!=
null
)
{
Element
table
=
ClassUtils
.
renderMatchedClasses
(
result
.
getMatchedClasses
());
process
.
write
(
RenderUtil
.
render
(
table
,
width
)).
write
(
"\n"
);
}
else
{
ClassVO
classInfo
=
result
.
getClassInfo
();
if
(
classInfo
!=
null
)
{
process
.
write
(
"\n"
);
process
.
write
(
RenderUtil
.
render
(
new
LabelElement
(
"ClassLoader: "
).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)),
width
));
process
.
write
(
RenderUtil
.
render
(
TypeRenderUtils
.
drawClassLoader
(
classInfo
),
width
)
+
"\n"
);
}
if
(
result
.
getLocation
()
!=
null
)
{
process
.
write
(
RenderUtil
.
render
(
new
LabelElement
(
"Location: "
).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)),
width
));
process
.
write
(
RenderUtil
.
render
(
new
LabelElement
(
result
.
getLocation
()).
style
(
Decoration
.
bold
.
fg
(
Color
.
blue
)),
width
)
+
"\n"
);
}
process
.
write
(
LangRenderUtil
.
render
(
result
.
getSource
())
+
"\n"
);
process
.
write
(
com
.
taobao
.
arthas
.
core
.
util
.
Constants
.
EMPTY_STRING
);
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/JvmView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.JvmModel
;
import
com.taobao.arthas.core.command.model.JvmItemVO
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.arthas.core.util.StringUtils
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
import
static
com
.
taobao
.
text
.
ui
.
Element
.
label
;
/**
* View of 'jvm' command
*
* @author gongdewei 2020/4/24
*/
public
class
JvmView
extends
ResultView
<
JvmModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
JvmModel
result
)
{
TableElement
table
=
new
TableElement
(
2
,
5
).
leftCellPadding
(
1
).
rightCellPadding
(
1
);
for
(
Map
.
Entry
<
String
,
List
<
JvmItemVO
>>
entry
:
result
.
getJvmInfo
().
entrySet
())
{
String
group
=
entry
.
getKey
();
List
<
JvmItemVO
>
items
=
entry
.
getValue
();
table
.
row
(
true
,
label
(
group
).
style
(
Decoration
.
bold
.
bold
()));
for
(
JvmItemVO
item
:
items
)
{
String
valueStr
;
if
(
item
.
getValue
()
instanceof
Map
&&
item
.
getName
().
endsWith
(
"MEMORY-USAGE"
))
{
valueStr
=
renderMemoryUsage
((
Map
<
String
,
Object
>)
item
.
getValue
());
}
else
{
valueStr
=
renderItemValue
(
item
.
getValue
());
}
if
(
item
.
getDesc
()
!=
null
)
{
table
.
row
(
item
.
getName
()
+
"\n["
+
item
.
getDesc
()
+
"]"
,
valueStr
);
}
else
{
table
.
row
(
item
.
getName
(),
valueStr
);
}
}
table
.
row
(
""
,
""
);
}
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
()));
}
private
String
renderCountTime
(
long
[]
value
)
{
//count/time
return
value
[
0
]
+
"/"
+
value
[
1
];
}
private
String
renderItemValue
(
Object
value
)
{
if
(
value
==
null
)
{
return
"null"
;
}
if
(
value
instanceof
Collection
)
{
return
renderCollectionValue
((
Collection
)
value
);
}
else
if
(
value
instanceof
String
[])
{
return
renderArrayValue
((
String
[])
value
);
}
else
if
(
value
instanceof
Map
)
{
return
renderMapValue
((
Map
)
value
);
}
return
String
.
valueOf
(
value
);
}
private
String
renderCollectionValue
(
Collection
<
String
>
strings
)
{
final
StringBuilder
colSB
=
new
StringBuilder
();
if
(
strings
.
isEmpty
())
{
colSB
.
append
(
"[]"
);
}
else
{
for
(
String
str
:
strings
)
{
colSB
.
append
(
str
).
append
(
"\n"
);
}
}
return
colSB
.
toString
();
}
private
String
renderArrayValue
(
String
...
stringArray
)
{
final
StringBuilder
colSB
=
new
StringBuilder
();
if
(
null
==
stringArray
||
stringArray
.
length
==
0
)
{
colSB
.
append
(
"[]"
);
}
else
{
for
(
String
str
:
stringArray
)
{
colSB
.
append
(
str
).
append
(
"\n"
);
}
}
return
colSB
.
toString
();
}
private
String
renderMapValue
(
Map
<
String
,
Object
>
valueMap
)
{
final
StringBuilder
colSB
=
new
StringBuilder
();
if
(
valueMap
!=
null
)
{
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
valueMap
.
entrySet
())
{
colSB
.
append
(
entry
.
getKey
()).
append
(
" : "
).
append
(
entry
.
getValue
()).
append
(
"\n"
);
}
}
return
colSB
.
toString
();
}
private
String
renderMemoryUsage
(
Map
<
String
,
Object
>
valueMap
)
{
final
StringBuilder
colSB
=
new
StringBuilder
();
String
[]
keys
=
new
String
[]{
"init"
,
"used"
,
"committed"
,
"max"
};
for
(
String
key
:
keys
)
{
Object
value
=
valueMap
.
get
(
key
);
String
valueStr
=
value
!=
null
?
formatMemoryByte
((
Long
)
value
)
:
""
;
colSB
.
append
(
key
).
append
(
" : "
).
append
(
valueStr
).
append
(
"\n"
);
}
return
colSB
.
toString
();
}
private
String
formatMemoryByte
(
long
bytes
)
{
return
String
.
format
(
"%s(%s)"
,
bytes
,
StringUtils
.
humanReadableByteCount
(
bytes
));
}
}
core/src/main/java/com/taobao/arthas/core/command/view/LoggerView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.logger.LoggerHelper
;
import
com.taobao.arthas.core.command.model.LoggerModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
import
java.util.List
;
import
java.util.Map
;
import
static
com
.
taobao
.
text
.
ui
.
Element
.
label
;
/**
* View of 'logger' command
*
* @author gongdewei 2020/4/22
*/
public
class
LoggerView
extends
ResultView
<
LoggerModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
LoggerModel
result
)
{
if
(
result
.
getMatchedClassLoaders
()
!=
null
)
{
process
.
write
(
"Matched classloaders: \n"
);
ClassLoaderView
.
drawClassLoaders
(
process
,
result
.
getMatchedClassLoaders
(),
false
);
process
.
write
(
"\n"
);
return
;
}
process
.
write
(
renderLoggerInfo
(
result
.
getLoggerInfoMap
(),
process
.
width
()));
}
private
String
renderLoggerInfo
(
Map
<
String
,
Map
<
String
,
Object
>>
loggerInfos
,
int
width
)
{
StringBuilder
sb
=
new
StringBuilder
(
8192
);
for
(
Map
.
Entry
<
String
,
Map
<
String
,
Object
>>
entry
:
loggerInfos
.
entrySet
())
{
Map
<
String
,
Object
>
info
=
entry
.
getValue
();
TableElement
table
=
new
TableElement
(
2
,
10
).
leftCellPadding
(
1
).
rightCellPadding
(
1
);
TableElement
appendersTable
=
new
TableElement
().
rightCellPadding
(
1
);
Class
<?>
clazz
=
(
Class
<?>)
info
.
get
(
LoggerHelper
.
clazz
);
table
.
row
(
label
(
LoggerHelper
.
name
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
name
)))
.
row
(
label
(
LoggerHelper
.
clazz
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
clazz
.
getName
()))
.
row
(
label
(
LoggerHelper
.
classLoader
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
classLoader
)))
.
row
(
label
(
LoggerHelper
.
classLoaderHash
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
classLoaderHash
)))
.
row
(
label
(
LoggerHelper
.
level
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
level
)));
if
(
info
.
get
(
LoggerHelper
.
effectiveLevel
)
!=
null
)
{
table
.
row
(
label
(
LoggerHelper
.
effectiveLevel
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
effectiveLevel
)));
}
if
(
info
.
get
(
LoggerHelper
.
config
)
!=
null
)
{
table
.
row
(
label
(
LoggerHelper
.
config
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
config
)));
}
table
.
row
(
label
(
LoggerHelper
.
additivity
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
additivity
)))
.
row
(
label
(
LoggerHelper
.
codeSource
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
info
.
get
(
LoggerHelper
.
codeSource
)));
@SuppressWarnings
(
"unchecked"
)
List
<
Map
<
String
,
Object
>>
appenders
=
(
List
<
Map
<
String
,
Object
>>)
info
.
get
(
LoggerHelper
.
appenders
);
if
(
appenders
!=
null
&&
!
appenders
.
isEmpty
())
{
for
(
Map
<
String
,
Object
>
appenderInfo
:
appenders
)
{
Class
<?>
appenderClass
=
(
Class
<?>)
appenderInfo
.
get
(
LoggerHelper
.
clazz
);
appendersTable
.
row
(
label
(
LoggerHelper
.
name
).
style
(
Decoration
.
bold
.
bold
()),
label
(
""
+
appenderInfo
.
get
(
LoggerHelper
.
name
)));
appendersTable
.
row
(
label
(
LoggerHelper
.
clazz
),
label
(
""
+
appenderClass
.
getName
()));
appendersTable
.
row
(
label
(
LoggerHelper
.
classLoader
),
label
(
""
+
info
.
get
(
LoggerHelper
.
classLoader
)));
appendersTable
.
row
(
label
(
LoggerHelper
.
classLoaderHash
),
label
(
""
+
info
.
get
(
LoggerHelper
.
classLoaderHash
)));
if
(
appenderInfo
.
get
(
LoggerHelper
.
file
)
!=
null
)
{
appendersTable
.
row
(
label
(
LoggerHelper
.
file
),
label
(
""
+
appenderInfo
.
get
(
LoggerHelper
.
file
)));
}
if
(
appenderInfo
.
get
(
LoggerHelper
.
target
)
!=
null
)
{
appendersTable
.
row
(
label
(
LoggerHelper
.
target
),
label
(
""
+
appenderInfo
.
get
(
LoggerHelper
.
target
)));
}
if
(
appenderInfo
.
get
(
LoggerHelper
.
blocking
)
!=
null
)
{
appendersTable
.
row
(
label
(
LoggerHelper
.
blocking
),
label
(
""
+
appenderInfo
.
get
(
LoggerHelper
.
blocking
)));
}
if
(
appenderInfo
.
get
(
LoggerHelper
.
appenderRef
)
!=
null
)
{
appendersTable
.
row
(
label
(
LoggerHelper
.
appenderRef
),
label
(
""
+
appenderInfo
.
get
(
LoggerHelper
.
appenderRef
)));
}
}
table
.
row
(
label
(
"appenders"
).
style
(
Decoration
.
bold
.
bold
()),
appendersTable
);
}
sb
.
append
(
RenderUtil
.
render
(
table
,
width
)).
append
(
'\n'
);
}
return
sb
.
toString
();
}
}
core/src/main/java/com/taobao/arthas/core/command/view/MBeanView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.MBeanAttributeVO
;
import
com.taobao.arthas.core.command.model.MBeanModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.text.Color
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.ui.LabelElement
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
import
javax.management.*
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Map
;
import
static
com
.
taobao
.
text
.
ui
.
Element
.
label
;
import
static
javax
.
management
.
MBeanOperationInfo
.*;
/**
* View of 'mbean' command
*
* @author gongdewei 2020/4/26
*/
public
class
MBeanView
extends
ResultView
<
MBeanModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
MBeanModel
result
)
{
if
(
result
.
getMbeanNames
()
!=
null
)
{
drawMBeanNames
(
process
,
result
.
getMbeanNames
());
}
else
if
(
result
.
getMbeanMetadata
()
!=
null
)
{
drawMBeanMetadata
(
process
,
result
.
getMbeanMetadata
());
}
else
if
(
result
.
getMbeanAttribute
()
!=
null
)
{
drawMBeanAttributes
(
process
,
result
.
getMbeanAttribute
());
}
}
private
void
drawMBeanAttributes
(
CommandProcess
process
,
Map
<
String
,
List
<
MBeanAttributeVO
>>
mbeanAttributeMap
)
{
for
(
Map
.
Entry
<
String
,
List
<
MBeanAttributeVO
>>
entry
:
mbeanAttributeMap
.
entrySet
())
{
String
objectName
=
entry
.
getKey
();
List
<
MBeanAttributeVO
>
attributeVOList
=
entry
.
getValue
();
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
row
(
true
,
"OBJECT_NAME"
,
objectName
);
table
.
row
(
true
,
label
(
"NAME"
).
style
(
Decoration
.
bold
.
bold
()),
label
(
"VALUE"
).
style
(
Decoration
.
bold
.
bold
()));
for
(
MBeanAttributeVO
attributeVO
:
attributeVOList
)
{
String
attributeName
=
attributeVO
.
getName
();
String
valueStr
;
if
(
attributeVO
.
getError
()
!=
null
)
{
valueStr
=
RenderUtil
.
render
(
new
LabelElement
(
attributeVO
.
getError
()).
style
(
Decoration
.
bold_off
.
fg
(
Color
.
red
)));
}
else
{
//convert array to list
// TODO support all array type
Object
value
=
attributeVO
.
getValue
();
if
(
value
instanceof
String
[])
{
value
=
Arrays
.
asList
((
String
[])
value
);
}
else
if
(
value
instanceof
Integer
[])
{
value
=
Arrays
.
asList
((
Integer
[])
value
);
}
else
if
(
value
instanceof
Long
[])
{
value
=
Arrays
.
asList
((
Long
[])
value
);
}
else
if
(
value
instanceof
int
[])
{
value
=
convertArrayToList
((
int
[])
value
);
}
else
if
(
value
instanceof
long
[])
{
value
=
convertArrayToList
((
long
[])
value
);
}
//to string
valueStr
=
String
.
valueOf
(
value
);
}
table
.
row
(
attributeName
,
valueStr
);
}
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
()));
process
.
write
(
"\n"
);
}
}
private
List
<
Long
>
convertArrayToList
(
long
[]
longs
)
{
List
<
Long
>
list
=
new
ArrayList
<
Long
>();
for
(
long
aLong
:
longs
)
{
list
.
add
(
aLong
);
}
return
list
;
}
private
List
<
Integer
>
convertArrayToList
(
int
[]
ints
)
{
List
<
Integer
>
list
=
new
ArrayList
<
Integer
>();
for
(
int
anInt
:
ints
)
{
list
.
add
(
anInt
);
}
return
list
;
}
private
void
drawMBeanMetadata
(
CommandProcess
process
,
Map
<
String
,
MBeanInfo
>
mbeanMetadata
)
{
TableElement
table
=
createTable
();
for
(
Map
.
Entry
<
String
,
MBeanInfo
>
entry
:
mbeanMetadata
.
entrySet
())
{
String
objectName
=
entry
.
getKey
();
MBeanInfo
mBeanInfo
=
entry
.
getValue
();
drawMetaInfo
(
mBeanInfo
,
objectName
,
table
);
drawAttributeInfo
(
mBeanInfo
.
getAttributes
(),
table
);
drawOperationInfo
(
mBeanInfo
.
getOperations
(),
table
);
drawNotificationInfo
(
mBeanInfo
.
getNotifications
(),
table
);
}
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
()));
}
private
void
drawMBeanNames
(
CommandProcess
process
,
List
<
String
>
mbeanNames
)
{
for
(
String
mbeanName
:
mbeanNames
)
{
process
.
write
(
mbeanName
).
write
(
"\n"
);
}
}
private
static
TableElement
createTable
()
{
TableElement
table
=
new
TableElement
().
leftCellPadding
(
1
).
rightCellPadding
(
1
);
table
.
row
(
true
,
label
(
"NAME"
).
style
(
Decoration
.
bold
.
bold
()),
label
(
"VALUE"
).
style
(
Decoration
.
bold
.
bold
()));
return
table
;
}
private
void
drawMetaInfo
(
MBeanInfo
mBeanInfo
,
String
objectName
,
TableElement
table
)
{
table
.
row
(
new
LabelElement
(
"MBeanInfo"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)));
table
.
row
(
new
LabelElement
(
"Info:"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
table
.
row
(
"ObjectName"
,
objectName
);
table
.
row
(
"ClassName"
,
mBeanInfo
.
getClassName
());
table
.
row
(
"Description"
,
mBeanInfo
.
getDescription
());
drawDescriptorInfo
(
"Info Descriptor:"
,
mBeanInfo
,
table
);
MBeanConstructorInfo
[]
constructors
=
mBeanInfo
.
getConstructors
();
if
(
constructors
.
length
>
0
)
{
for
(
int
i
=
0
;
i
<
constructors
.
length
;
i
++)
{
table
.
row
(
new
LabelElement
(
"Constructor-"
+
i
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
table
.
row
(
"Name"
,
constructors
[
i
].
getName
());
table
.
row
(
"Description"
,
constructors
[
i
].
getDescription
());
}
}
}
private
void
drawAttributeInfo
(
MBeanAttributeInfo
[]
attributes
,
TableElement
table
)
{
for
(
MBeanAttributeInfo
attribute
:
attributes
)
{
table
.
row
(
new
LabelElement
(
"MBeanAttributeInfo"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)));
table
.
row
(
new
LabelElement
(
"Attribute:"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
table
.
row
(
"Name"
,
attribute
.
getName
());
table
.
row
(
"Description"
,
attribute
.
getDescription
());
table
.
row
(
"Readable"
,
String
.
valueOf
(
attribute
.
isReadable
()));
table
.
row
(
"Writable"
,
String
.
valueOf
(
attribute
.
isWritable
()));
table
.
row
(
"Is"
,
String
.
valueOf
(
attribute
.
isIs
()));
table
.
row
(
"Type"
,
attribute
.
getType
());
drawDescriptorInfo
(
"Attribute Descriptor:"
,
attribute
,
table
);
}
}
private
void
drawOperationInfo
(
MBeanOperationInfo
[]
operations
,
TableElement
table
)
{
for
(
MBeanOperationInfo
operation
:
operations
)
{
table
.
row
(
new
LabelElement
(
"MBeanOperationInfo"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)));
table
.
row
(
new
LabelElement
(
"Operation:"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
table
.
row
(
"Name"
,
operation
.
getName
());
table
.
row
(
"Description"
,
operation
.
getDescription
());
String
impact
=
""
;
switch
(
operation
.
getImpact
())
{
case
ACTION:
impact
=
"action"
;
break
;
case
ACTION_INFO:
impact
=
"action/info"
;
break
;
case
INFO:
impact
=
"info"
;
break
;
case
UNKNOWN:
impact
=
"unknown"
;
break
;
}
table
.
row
(
"Impact"
,
impact
);
table
.
row
(
"ReturnType"
,
operation
.
getReturnType
());
MBeanParameterInfo
[]
signature
=
operation
.
getSignature
();
if
(
signature
.
length
>
0
)
{
for
(
int
i
=
0
;
i
<
signature
.
length
;
i
++)
{
table
.
row
(
new
LabelElement
(
"Parameter-"
+
i
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
table
.
row
(
"Name"
,
signature
[
i
].
getName
());
table
.
row
(
"Type"
,
signature
[
i
].
getType
());
table
.
row
(
"Description"
,
signature
[
i
].
getDescription
());
}
}
drawDescriptorInfo
(
"Operation Descriptor:"
,
operation
,
table
);
}
}
private
void
drawNotificationInfo
(
MBeanNotificationInfo
[]
notificationInfos
,
TableElement
table
)
{
for
(
MBeanNotificationInfo
notificationInfo
:
notificationInfos
)
{
table
.
row
(
new
LabelElement
(
"MBeanNotificationInfo"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
red
)));
table
.
row
(
new
LabelElement
(
"Notification:"
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
table
.
row
(
"Name"
,
notificationInfo
.
getName
());
table
.
row
(
"Description"
,
notificationInfo
.
getDescription
());
table
.
row
(
"NotifTypes"
,
Arrays
.
toString
(
notificationInfo
.
getNotifTypes
()));
drawDescriptorInfo
(
"Notification Descriptor:"
,
notificationInfo
,
table
);
}
}
private
void
drawDescriptorInfo
(
String
title
,
DescriptorRead
descriptorRead
,
TableElement
table
)
{
Descriptor
descriptor
=
descriptorRead
.
getDescriptor
();
String
[]
fieldNames
=
descriptor
.
getFieldNames
();
if
(
fieldNames
.
length
>
0
)
{
table
.
row
(
new
LabelElement
(
title
).
style
(
Decoration
.
bold
.
fg
(
Color
.
yellow
)));
for
(
String
fieldName
:
fieldNames
)
{
Object
fieldValue
=
descriptor
.
getFieldValue
(
fieldName
);
table
.
row
(
fieldName
,
fieldValue
==
null
?
""
:
fieldValue
.
toString
());
}
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/MemoryCompilerView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.MemoryCompilerModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
/**
* @author gongdewei 2020/4/20
*/
public
class
MemoryCompilerView
extends
ResultView
<
MemoryCompilerModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
MemoryCompilerModel
result
)
{
if
(
result
.
getMatchedClassLoaders
()
!=
null
)
{
process
.
write
(
"Matched classloaders: \n"
);
ClassLoaderView
.
drawClassLoaders
(
process
,
result
.
getMatchedClassLoaders
(),
false
);
process
.
write
(
"\n"
);
return
;
}
process
.
write
(
"Memory compiler output:\n"
);
for
(
String
file
:
result
.
getFiles
())
{
process
.
write
(
file
+
'\n'
);
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/MemoryView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
java.lang.management.MemoryUsage
;
import
java.util.List
;
import
java.util.Map
;
import
com.taobao.arthas.core.command.model.MemoryEntryVO
;
import
com.taobao.arthas.core.command.model.MemoryModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
import
com.taobao.text.Color
;
import
com.taobao.text.Decoration
;
import
com.taobao.text.Style
;
import
com.taobao.text.ui.RowElement
;
import
com.taobao.text.ui.TableElement
;
import
com.taobao.text.util.RenderUtil
;
/**
* View of 'memory' command
*
* @author hengyunabc 2022-03-01
*/
public
class
MemoryView
extends
ResultView
<
MemoryModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
MemoryModel
result
)
{
TableElement
table
=
drawMemoryInfo
(
result
.
getMemoryInfo
());
process
.
write
(
RenderUtil
.
render
(
table
,
process
.
width
()));
}
static
TableElement
drawMemoryInfo
(
Map
<
String
,
List
<
MemoryEntryVO
>>
memoryInfo
)
{
TableElement
table
=
new
TableElement
(
3
,
1
,
1
,
1
,
1
).
rightCellPadding
(
1
);
table
.
add
(
new
RowElement
().
style
(
Decoration
.
bold
.
fg
(
Color
.
black
).
bg
(
Color
.
white
)).
add
(
"Memory"
,
"used"
,
"total"
,
"max"
,
"usage"
));
List
<
MemoryEntryVO
>
heapMemoryEntries
=
memoryInfo
.
get
(
MemoryEntryVO
.
TYPE_HEAP
);
//heap memory
for
(
MemoryEntryVO
memoryEntryVO
:
heapMemoryEntries
)
{
if
(
MemoryEntryVO
.
TYPE_HEAP
.
equals
(
memoryEntryVO
.
getName
()))
{
new
MemoryEntry
(
memoryEntryVO
).
addTableRow
(
table
,
Decoration
.
bold
.
bold
());
}
else
{
new
MemoryEntry
(
memoryEntryVO
).
addTableRow
(
table
);
}
}
//non-heap memory
List
<
MemoryEntryVO
>
nonheapMemoryEntries
=
memoryInfo
.
get
(
MemoryEntryVO
.
TYPE_NON_HEAP
);
for
(
MemoryEntryVO
memoryEntryVO
:
nonheapMemoryEntries
)
{
if
(
MemoryEntryVO
.
TYPE_NON_HEAP
.
equals
(
memoryEntryVO
.
getName
()))
{
new
MemoryEntry
(
memoryEntryVO
).
addTableRow
(
table
,
Decoration
.
bold
.
bold
());
}
else
{
new
MemoryEntry
(
memoryEntryVO
).
addTableRow
(
table
);
}
}
//buffer-pool
List
<
MemoryEntryVO
>
bufferPoolMemoryEntries
=
memoryInfo
.
get
(
MemoryEntryVO
.
TYPE_BUFFER_POOL
);
if
(
bufferPoolMemoryEntries
!=
null
)
{
for
(
MemoryEntryVO
memoryEntryVO
:
bufferPoolMemoryEntries
)
{
new
MemoryEntry
(
memoryEntryVO
).
addTableRow
(
table
);
}
}
return
table
;
}
static
class
MemoryEntry
{
String
name
;
long
used
;
long
total
;
long
max
;
int
unit
;
String
unitStr
;
public
MemoryEntry
(
String
name
,
long
used
,
long
total
,
long
max
)
{
this
.
name
=
name
;
this
.
used
=
used
;
this
.
total
=
total
;
this
.
max
=
max
;
unitStr
=
"K"
;
unit
=
1024
;
if
(
used
/
1024
/
1024
>
0
)
{
unitStr
=
"M"
;
unit
=
1024
*
1024
;
}
}
public
MemoryEntry
(
String
name
,
MemoryUsage
usage
)
{
this
(
name
,
usage
.
getUsed
(),
usage
.
getCommitted
(),
usage
.
getMax
());
}
public
MemoryEntry
(
MemoryEntryVO
memoryEntryVO
)
{
this
(
memoryEntryVO
.
getName
(),
memoryEntryVO
.
getUsed
(),
memoryEntryVO
.
getTotal
(),
memoryEntryVO
.
getMax
());
}
private
String
format
(
long
value
)
{
String
valueStr
=
"-"
;
if
(
value
==
-
1
)
{
return
"-1"
;
}
if
(
value
!=
Long
.
MIN_VALUE
)
{
valueStr
=
value
/
unit
+
unitStr
;
}
return
valueStr
;
}
public
void
addTableRow
(
TableElement
table
)
{
double
usage
=
used
/
(
double
)
(
max
==
-
1
||
max
==
Long
.
MIN_VALUE
?
total
:
max
)
*
100
;
if
(
Double
.
isNaN
(
usage
)
||
Double
.
isInfinite
(
usage
))
{
usage
=
0
;
}
table
.
row
(
name
,
format
(
used
),
format
(
total
),
format
(
max
),
String
.
format
(
"%.2f%%"
,
usage
));
}
public
void
addTableRow
(
TableElement
table
,
Style
.
Composite
style
)
{
double
usage
=
used
/
(
double
)
(
max
==
-
1
||
max
==
Long
.
MIN_VALUE
?
total
:
max
)
*
100
;
if
(
Double
.
isNaN
(
usage
)
||
Double
.
isInfinite
(
usage
))
{
usage
=
0
;
}
table
.
add
(
new
RowElement
().
style
(
style
).
add
(
name
,
format
(
used
),
format
(
total
),
format
(
max
),
String
.
format
(
"%.2f%%"
,
usage
)));
}
}
}
core/src/main/java/com/taobao/arthas/core/command/view/MessageView.java
0 → 100644
View file @
5d7c4150
package
com.taobao.arthas.core.command.view
;
import
com.taobao.arthas.core.command.model.MessageModel
;
import
com.taobao.arthas.core.shell.command.CommandProcess
;
/**
* @author gongdewei 2020/4/2
*/
public
class
MessageView
extends
ResultView
<
MessageModel
>
{
@Override
public
void
draw
(
CommandProcess
process
,
MessageModel
result
)
{
writeln
(
process
,
result
.
getMessage
());
}
}
Prev
1
…
16
17
18
19
20
21
22
23
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment