Hi,
I have an instrumentation need, where in same method is being called twice as part of execution. I would like to retain some data between these calls for my metric computation.
Let me give a pseudo code for example.
`
public void doSomeActivity(){
//some initilization code here.
//first callto setStatus method.
setStatus("STARTED");
//do some more business logic process, heavy lifting work.
//second call to setStatus method.
setStatus("COMPLETE");
//some more light steps here.
}
`
I'm trying to instrument "setStatus()" method, trying to push some data to inspectIt-context upon first call and try to retrive it when method is called for second time as part of same execution.
the instrumentation data element is set for both up-propagation & down-propagation (JVM_LOCAL) with is-tag = false.
But I can see that, inspectIT fails to propagate value set during first call of setStatus method to subsequent call of same method as part of same execution cycle.
Is there a way I can achieve this with in current inspectIT ocelot framework using yaml files it self? Any pointers is highly appreciated.
inspectit:
tags:
extra:
prev_status:
instrumentation:
data:
exec_in_process: {up-propagation: JVM_LOCAL,down-propagation: JVM_LOCAL, is-tag: false}
prev_status : {up-propagation: GLOBAL, down-propagation: JVM_LOCAL, is-tag: true}
scopes:
updateRequestStatus:
type:
name: com.abcd.xyz.core.parser.ExpressionParser
methods:
- name: updateRequestStatus
rules:
entry:
method_entry_time:
action: timestamp_nanos
method_name:
action: get_method_fqn
exec_flag:
action: test_and_set_marker
constant-input: { marker: exec_in_process}
exit:
method_duration:
action: elapsed_millis
data-input:
sinceNanos: method_entry_time
abcd_exec_status:
action: check_and_count_exec
data-input: {flag: exec_flag}
metrics:
'[abcd/exec/status]' : abcd_exec_status
'[method/duration]' : method_duration
actions:
check_and_count_exec:
input:
_arg1: String
flag: Boolean
value-body: |
if( !(_arg1.equalsIgnoreCase("PROCESSING")) && flag.booleanValue()== true) return new Integer(0);
else return new Integer(1);
setRequestState
calls? The easiest way to do this is by propagating the entry-timestamp using something like this:inspectit:
instrumentation:
data:
request_start_time:
up-propagation: JVM_LOCAL
down-propagation: JVM_LOCAL
is-tag: false
rules:
your_rule:
entry:
is_start:
action: is_arg1_equal
constant-input: {value: "PROCESSING"}
#only override the time if we are the start
request_start_time:
only-if-true: is_start
action: timestamp_nanos
exit:
is_finish:
action: is_arg1_equal
constant-input: {value: "FINISHED"}
request_duration:
only-if-true: is_finish
action: elapsed_millis
data-input:
sinceNanos: request_duration
metrics:
'[your/metric]' : method_duration
actions:
is_arg1_equal:
input:
_arg1: Object
value: Object
value: Boolean.valueOf(Objects.equals(_arg1,value))
Thanks for your reply @JonasKunz .. I tried below 2 approaches and getting some trace logs but as not it is supposed to be Below is my scope definition scopes:
scopes:
tracemaintestReportmethod:
type:
name: com.org.test.controller.controllerTest
methods:
- name: testReport
tracesubMethod: (sub method from other class invoked from 'testReport' main method)
type:
name: com.org.test.util.InputData
methods:
- name: getId
- name: setStatus
I tried to set rules as below
(Approach 1)
rules:
tracemaintestReportmethod:
tracing:
start-span: true
store-span: report_span_data
end-span: false
scopes:
tracemaintestReportmethod: true
tracesubMethod_Trace:
tracing:
continue-span: report_span_data
scopes:
tracesubMethod: true
This approach didn't work for me
(Approach 2)
tracemaintestReportmethod:
tracing:
start-span: true
scopes:
tracemaintestReportmethod: true
tracesubMethod: true
In this approach traces are logged for only 'controllerTest' test class but for 'InputData' class no traces are logged.
If you can provide a sample example for collecting traces data that would help me a lot. or any link which explained this in detail will surely help me.
Hi @JonasKunz , I did some modification in my scopes ( removed methods from main method)
'''scopes:
tracemaintestReportmethod:
type:
name: com.org.test.controller.controllerTest
tracesubMethod: (sub method from other class invoked from 'testReport' main method)
type:
name: com.org.test.util.InputData
methods:
- name: getId
- name: setStatus'''
and my rule config is as below
'''
rules:
tracemaintestReportmethod:
tracing:
start-span: true
scopes:
tracemaintestReportmethod: true
tracesubMethod: true
'''
With these configuration I am getting traces(method execution timings) for all the main class methods and mentioned sub methods of other classes(is my configurations correct? and to get details like query (if method executed a query) as in attached screenshot is there a extra configuration needed? or will it capture automatically.
scopes:
tracemaintestReportmethod:
type:
name: com.org.test.controller.controllerTest
tracesubMethod: (sub method from other class invoked from 'testReport' main method)
type:
name: com.org.test.util.InputData
methods:
- name: getId
- name: setStatus
rules:
tracemaintestReportmethod:
tracing:
start-span: true
scopes:
tracemaintestReportmethod: true
tracesubMethod: true
Hi @JonasKunz , I tried to implemet JDBC tracing for MSSQL prepared statement by referring the HSQL db conf in demo app.
getting below exception. Database name gettting printed in trace but not SQL queries.
below is my instrumentation config
inspectit:
instrumentation:
data:
db_name: {down-propagation: NONE, is-tag: false}
sql: {down-propagation: NONE, is-tag: false}
servicegraph_is_entry: {down-propagation: NONE, is-tag: false}
scopes:
mssqldb_prepared_statement_execute:
type:
name: com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement
methods:
- name: execute
matcher-mode: STARTS_WITH
rules:
mssql_get_prep_statement_sql:
scopes:
mssqldb_prepared_statement_execute: true
tracing:
attributes:
database: db_name
sql: sql
entry:
db_name:
action: get_jdbc_statement_connection_name
sql:
action: mssql_prepared_statement_get_sql
actions:
mssql_prepared_statement_get_sql:
imports:
- com.microsoft.sqlserver.jdbc
- java.lang.reflect
input:
_this: SQLServerPreparedStatement
_class: Class
value-body: |
Field sqlField = _class.getDeclaredField("sql");
sqlField.setAccessible(true);
return sqlField.get(_this);
get_jdbc_statement_connection_name:
imports:
- java.sql
input:
_this: Statement
value-body: |
if(!_this.isClosed()) {
Connection con = _this.getConnection();
String url = con.getMetaData().getURL();
int semiColonIndex = url.indexOf(';');
if(semiColonIndex != -1) {
url = url.substring(0,semiColonIndex);
}
int questionIndex = url.indexOf('?');
if(questionIndex != -1) {
url = url.substring(0,questionIndex);
When I execute with this configuration only DB name is getting logged in trace.
Encountering below exception.
2020-02-13 23:13:08,894 ERROR 81787820 --- [] [Bean#0_Worker-1] r.i.o.c.instrumentation.hook.MethodHook : Entry action Action 'mssql_prepared_statement_get_sql' for call 'sql' executed for method com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery threw an exception and from now on is disabled!
java.lang.NoSuchFieldException: sql
at java.lang.Class.getDeclaredField(Class.java:2070)
at com.sun.proxy.inspectitGen
KaTeX parse error: Can't use function '$' in math mode at position 1: $̲557729609728220…: $5577296097282200557.executeImpl(GenericActionTemplate.java)
at com.sun.proxy.inspectitGen
$5577296097282200557.execute(GenericActionTemplate.java:24)Can you please help me with this.! Thanks
mssql_prepared_statement_get_sql
tries to lookup an sql
private field of the given SQLServerPreparedStatement class. This field doesn't exist, therefore you get the NoSuchFieldException
. Have a look at the source code:sqlCommand
.
data:
db_name: {down-propagation: NONE, is-tag: false}
sql: {down-propagation: NONE, is-tag: false}
servicegraph_is_entry: {down-propagation: NONE, is-tag: false}
scopes:
oracle_prepared_statement_execute:
type:
name: oracle.jdbc.OraclePreparedStatement
methods:
- name: execute
matcher-mode: STARTS_WITH
rules:
# Extract the sql and add it to the trace
oracle_get_prep_statement_sql:
scopes:
oracle_prepared_statement_execute: true
tracing:
attributes:
database: db_name
sql: sql
entry:
db_name:
action: get_jdbc_statement_connection_name
sql:
action: oracle_prepared_statement_get_sql
# We also trace JDBC calls including their target database
servicegraph_record_jdbc_calls:
tracing:
start-span: true
attributes:
database: db_name
start-span-conditions:
only-if-true: servicegraph_is_entry
entry:
db_name:
action: get_jdbc_statement_connection_name
actions:
oracle_prepared_statement_get_sql:
imports:
- oracle.jdbc
- java.lang.reflect
input:
_this: OraclePreparedStatement
_class: Class
value-body:
Field sqlField = _class.getDeclaredField("sql");
sqlField.setAccessible(true);
return sqlField.get(_this);