Источник:
http://axstart.spaces.live.com/Blog/...C0A0!282.entry
==============
Did we al have experienced the next example? A user complains that he received an error but he is not able to reproduce the error. In that case this small add on can help you out. The trick is that we gone log the error in the table of the long running queries. This integration is placed in the static error method of the global class. When the user is complaining about the error we can see it back in Administration\Inquiries\Databases\Sql Statement Trace Log. We can see the stack on tab page use and even jump to the code from that point.
X++:
client server static Exception error(SysInfoLogStr txt, URL helpUrl = '', SysInfoAction _sysInfoAction = null)
{
//add on AXSTART.spaces.live.com
#SysTrace
container traceContainer;
container stack = xSession::xppCallStack();
int currentStack;
str result;
;
//build memo field;
for(currentStack = 1; currentStack <= conlen(stack); currentStack++)
{
if(currentStack mod 2 == 0)
result += strfmt(' - line %1 \n',conpeek(stack,currentStack));
else
result += conpeek(stack,currentStack);
}
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_EXECUTION_PLAN,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_EXECUTION_TIME,0);
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_CATEGORY,SqlTraceCategory::Statement);
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_STATEMENT,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_TEXT,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_TEXT_MORE,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_CALLSTACK, result);
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_CODE,infolog.text() + '\n' + txt);
SYSTraceTableSQL::CreateFromContainer(traceContainer);
//add on AXSTART.spaces.live.com
return infolog.add(Exception::Error, getprefix()+txt, helpUrl, _sysInfoAction, false);
}
This trick can also be used to monitor deeply changes of data. Of course this can also be done with database logging, but in that case I don’t have information about the process that changed the record. I used this when a customer was complaining that AX was changing the data, but on the end it was a user.
X++:
public void update()
{
//add on AXSTART.spaces.live.com
#SysTrace
container traceContainer;
container stack = xSession::xppCallStack();
int currentStack;
str result;
;
//build memo field;
for(currentStack = 1; currentStack <= conlen(stack); currentStack++)
{
//skip line numers
if(currentStack mod 2 == 0)
result += strfmt(' - line %1 \n',conpeek(stack,currentStack));
else
result += conpeek(stack,currentStack);
}
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_EXECUTION_PLAN,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_EXECUTION_TIME,0);
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_CATEGORY,SqlTraceCategory::Statement);
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_STATEMENT,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_TEXT,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_TEXT_MORE,'');
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_CALLSTACK, result);
traceContainer = conpoke(traceContainer, #SYS_TRACE_SQL_CODE,strfmt('%1 changed to %2',this.orig().name , this.name);
SYSTraceTableSQL::CreateFromContainer(traceContainer);
//add on AXSTART.spaces.live.com
super();
}