Christoph Rueger created FREEMARKER-120:
-------------------------------------------
Summary: Hook to collect which members are accessed on runtime
Key: FREEMARKER-120
URL: https://issues.apache.org/jira/browse/FREEMARKER-120
Project: Apache Freemarker
Issue Type: Improvement
Components: engine
Affects Versions: 2.3.29
Reporter: Christoph Rueger
h2. Problem description
We would like to collect metrics which counts which Objects and methods are
called by templates.
h2. Why?
We have lots of FM-templates which are provided by users (not developers).
Collecting metrics about method invocations would allow us to track what users
are doing in templates, find out about about which methods are used how often
(e.g. to determine potential for performance optimizations or detect unused
methods (potential dead code)). Furthermore it allows to detect malicious usage
(e.g. attempts to call "dangerous" methods on objects which were are accessible
in templates etc.).
h3. Example of possible metrics output
{code:java}
com.company.MyClass#getA()=1
com.company.MyClass#getB(String)=567
com.company.Otherclass#getA(String, String)=134 {code}
etc.
I know this e.g. from Hibernate which could be enabled / disabled
([https://docs.jboss.org/hibernate/orm/3.2/api/org/hibernate/stat/Statistics.html])
h3. Suggestion
It would be great if we e.g. could just override a method / hook in a Custom
ObjectWrapper.
{code:java}
Could be specified in BeansWrapper.java and called from
freemarker.ext.beans.BeansWrapper.invokeMethod(Object, Method, Object[]) just
before the actual method invocation.
/**
* This hook can be used by subclasses
* e.g. for statistics about method invokation
* (which methods get called on which objects how often).
*
* @param object
* @param method
* @param args
*/
protected void logMethodInvocation(Object object, Method method, Object[]
args) {
// TODO Auto-generated method stub
}
{code}
See example
[https://github.com/chrisrueger/freemarker/commit/804b3d99188e1dbb00fd03f8fe120515b17bbbca]
*Possible implementation*
{code:java}
public class MyObjectWrapper extends SimpleObjectWrapper{
private AtomicLongMap<String> methodStats = AtomicLongMap.create();
public MyObjectWrapper(Version version) {
super(version);
@Override
protected void logMethodInvocation(Object object, Method method,
Object[] args) {
methodStats.incrementAndGet(object.getClass().getName()+"#"+method.getName());
}
}{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)