Simon HierarchyWhile Simons do just fine on their own (measuring) they are organized in the tree hierarchy because of better manageability. You can enable/disable whole sub-trees (via JMX in the future) or you can perform various aggregative operations on them (not yet implemented). You can organize monitors on your own as well (e.g. groups) - anyway this tree hierarchy is always there for you. Simon's place in the hierarchyName of the Simon is always fully qualified and it always position Simon into the tree somewhere. Name is structured the same way like name of the Logger from Java Util Logging API. Dot (.) works as separator of name components and as you read the name from left to right you go down the hierarchy to your Simon. There is no "local name", you always work with Simon via its full name. Obtaining the Simon is fast - it's done via hash-map. Only the Simon creation is a bit more expansive - we have to place the monitor into the tree, find out its effective state (if it's enabled), etc. Basic usage of Simons is not affected by the overhead of working with the tree. If you perform hierarchical data sampling (aggregations) or if you manage your Simons (disable, enable) then you work with the tree structure. Simon stateSimon can be enabled or disabled - this determines if it does its work (measures, counts) or not. Disabled Simon affects the application as little as possible. We call this effective state and it can be only enabled or disabled. However there is also an "inner" state of the Simon (simply state) and it can be enabled, disabled or inherit (see enumeration SimonState). If the state is set to inherit, tree is traversed parent by parent seeking for the first Simon with disabled or enabled state. This determines the effective state of the Simon. Or you can simply say that Simon inherits effective state of the parent - it's still the same. Because effective state is used a lot by the Simon, it's always stored in every Simon - so don't worry about the performance. :-) Nodes in between?When you create stopwatch with name com.myproject.package.something.monitor1 the stopwatch object is created - but it has to have parent in order to be in the tree. Its parent has name com.myproject.package.something and it has unspecified type. This is implemented by UnknownSimon class and you can replace this type of Simon with the monitor of your choice later. If you destroy monitor with some children, it's not actually removed - it's replaced by the "unknown" Simon. This node is needed to provide necessary hierarchy-related functionality. Example: SimonConfigTestThere is an example class org.javasimon.examples.SimonConfigTest in the examples directory. It shows how Simon pre-configuration works by reading org/javasimon/examples/simon.config resource as a configuration. Configuration is processed when SimonFactory class is loaded. After the configuration is read it prints the whole Simon tree on the console. Configuration goes like this: org.javasimon.test-stopwatch=stopwatch basic
org.javasimon.examples.counter=counter
org.javasimon.examples.stopwatch=stopwatch
org.javasimon.examples.config=disable
org.javasimon.examples.config.stopwatch1=stopwatch enable
org.javasimon.examples.config.stopwatch2=stopwatch errorvalue Property name is actually the name of the Simon. Keywords stopwatch and counter specifies type of the monitor - nothing specified results into UnknownSimon type. Word basic specifies type of statistic processor (ignore that for now). Words disable and enable sets the state of the Simon (nothing leaves inherit). Finally errorvalue is invalid value. Let's check the output of the example: Unknown config value 'errorvalue' for name 'org.javasimon.examples.config.stopwatch2'.
(+): Unknown Simon: [ ENABLED/opt=NULL]
org(+): Unknown Simon: [org INHERIT/opt=NULL]
org.javasimon(+): Unknown Simon: [org.javasimon INHERIT/opt=NULL]
org.javasimon.examples(+): Unknown Simon: [org.javasimon.examples INHERIT/opt=NULL]
org.javasimon.examples.config(-): Unknown Simon: [org.javasimon.examples.config DISABLED/opt=NULL]
org.javasimon.examples.config.stopwatch2(-): Simon Stopwatch: [org.javasimon.examples.config.stopwatch2 INHERIT/opt=NULL] total 0 ns, counter 0, max 0 ns, min undef
org.javasimon.examples.config.stopwatch1(+): Simon Stopwatch: [org.javasimon.examples.config.stopwatch1 ENABLED/opt=NULL] total 0 ns, counter 0, max 0 ns, min undef
org.javasimon.examples.counter(+): Simon Counter: [org.javasimon.examples.counter INHERIT/opt=NULL] counter=0
org.javasimon.examples.stopwatch(+): Simon Stopwatch: [org.javasimon.examples.stopwatch INHERIT/opt=NULL] total 0 ns, counter 0, max 0 ns, min undef
org.javasimon.test-stopwatch(+): Simon Stopwatch: [org.javasimon.test-stopwatch INHERIT/opt=BASIC] total 0 ns, counter 0, max 0 ns, min undefAfter Simon's name there is an effective state printed - plus means enabled, minus means disabled. The rest is Simon's toString output - you can see the real state there. As you can see org.javasimon.examples.config.stopwatch1 is explicitly enabled while org.javasimon.examples.config.stopwatch2 is disabled and this state is inherited. You can also notice UnknownSimon nodes on the upper levels of the hierarchy.
|