1 debug
The debug tag is used to obtain the activity log and usage statistics and SQL response times of the execution of a program XSQL-Script
.
The debuf can be:
- Sent by e-mail: indicating the e-mail using the attribute mailto.
- Sent to file: indicating the file path using the attribute file. The file is located in the application server in the indicated file path that should be configurated as server work directory in the configuration database.
- Sent to the standard console: If the e-mail or the file is not specified, the debug is issued in the standard console or in the application error console
DBStudio
if it is executed from it.
It exist differents levels of debug that allows to the programmer determine which type of log wants to obtain. By default, if not indicated the database logs are issued as connections, queries and performed transactions.
The option dump is independent of the level of defined debug. This option is used to issue with the debug, the summary of usage statistics and SQL response times. This option is very useful to obtain the total of performed operations and totals of time.
Dump de estadísticas globales sin debug
To indicate that only global statistics without debug are desired, the following values should be indicated.
dump='true' level='none'
<debug
mailto='mailto'
smtphost='smtphost'
file='file'
disk='true|false'
mode='local|calls'
level='none|soft|eval|attr|conv|dbms|dump|args|file|hard'
dump='true|false'
explain='true|false'
/>
Attributes | |||||
---|---|---|---|---|---|
Name | Type | Required | Default | Description | |
Amailto | string | E-mail destination. | |||
Asmtphost | string | Domain name of the outgoing email server. | |||
Afile | string | Name of the file. | |||
Adisk | boolean | Save debug output to user's mailtool | |||
Amode | string | By default, all functions and subroutines are debugged.
|
|||
Alevel | string | none | Indicates the level of debug (information dump).
|
||
Adump | boolean | true | true to obtain statistics of use and SQL reponses time. If you only want to obtain the statistics without debug, you must indicate dump='true' y level='none'. | ||
Aexplain | boolean |
true to obtain detailed information about the SQL sentences.
Activate the SQL EXPLAIN of the SQL sentences which are executed in the XSQL-Script scope. In order to obtain the explain file, it is necessary to send the debug to an email address. Depending on the database agent in which the XSQL-script is running, it performs various tasks:
|
Exceptions
unsupported mode [...]
The specified value in the mode attribute is not valid.
no smtp host defined for sending debug file by mail, user= [...]
The mail server has not been indicated and it is not deductible by the user.
unknown SMTP host: [...]
The informed value as mail server is not valid.
could not connect to SMTP host: [...]
It is not possible to establish communication with the specified mail server.
Remarks
The compiled debug information can be visualized by console, sent to the specified email address in the mailto attribute (through the server of the Outgoing mail indicated in the smtphost attribute, or dumped to file using the attribute file. There is a possibility that the debug is propagated to functions (subroutines). Indicating the value calls to the attribute mode, the debug will affect to the possible subroutines, informing the local value (default option), we will get only information of the main routine.
Get debug information by console of certain lines of code.
<xsql-script name='debug_sample1'> <body> <debug /> <set name='word1'>hello</set> <set name='word2'>world</set> <set name='sentence'> <string><word1/><string.space /><word2/></string> </set> <println><sentence/></println> </body> </xsql-script>
The result shown on the screen would be:
00:00.000: 4 p:\tmp\test:. 00:00.000: 4 p:\tmp\test:.. req 00:00.000: 4 p:\tmp\test:.. get all args 00:00.016: 4 p:\tmp\test:.. = java.lang.String[hello] 00:00.016: p:\tmp\test:. Variable(java.lang.String)[hello] 00:00.016: 4 p:\tmp\test:. 00:00.016: 5 p:\tmp\test:. 00:00.016: 5 p:\tmp\test:.. req 00:00.016: 5 p:\tmp\test:.. get all args 00:00.016: 5 p:\tmp\test:.. = java.lang.String[world] 00:00.016: p:\tmp\test:. Variable(java.lang.String)[world] 00:00.016: 5 p:\tmp\test:. hello world
Where the different columns show the following information (from left to right):
Execution time. Number of code line. XSQL-Script route. Nesting level of the tag. Label and information of the interpreter.
Example:
00:00.016: 4 p:\tmp\dvt\test:..</set> = java.lang.String[hello]
The instruction has been processed in the second 16 from the beginning of the execution of the script, the code line is 4, the XML file route is p:\tmp\test, the tag end mark </set> is in the level 2 of nesting and the value 'hello' is interpreted as Java string type (clase java.lang.String).
Get debug information from e-mail.
<xsql-script name='debug_sample2'> <body> <debug mailto='destinatario@deister.es' smtphost='mail.deister.net' /> <set name='word1'>hello</set> <set name='word2'>world</set> <set name='sentence'> <string><word1/><string.space /><word2/></string> </set> <println><sentence/></println> </body> </xsql-script>
The headboard from the e-mail who would receive the recipient is shown below:
Subject: debug file generated at p:\tmp\test Date: Mon Oct 31 14:51:37 CET 2005 From: xsqlscript.debug@deister.net To: destinatario@deister.es Attached: debug.txt debug.xml XSQLScript debug from script p:\tmp\test user=null pool=null host=camelot addr=192.168.10.104 This is an automatic generated message from DEISTER Axional Studio application server. Please, do not respond!
Where debug.txt contains the debuf information and debug.xml includes the code of the script.
Get debug information from disktool.
<xsql-script name='debug_sample2'> <body> <debug disk='true' /> <set name='word1'>hello</set> <set name='word2'>world</set> <set name='sentence'> <string><word1/><string.space /><word2/></string> </set> <println><sentence/></println> </body> </xsql-script>
A ZIP
file in the user's disktool will be created with the name file-{dbms}-{timestamp} where dbms is the database code of execution and timestamp
is the current date in milliseconds
Get the debug information for file.
<xsql-script name='debug_sample3'> <body> <set name='file_debug'>debug.log</set> <debug file='#file_debug' /> <set name='word1'>hello</set> <set name='word2'>world</set> <set name='sentence'> <string><word1/><string.space /><word2/></string> </set> <println><sentence/></println> <println></println> <println>Debug:</println> <println></println> <println> <file.bytes.read> <file name='#file_debug' type='absolute'/> </file.bytes.read> </println> </body> </xsql-script>
The debug information is stored in the file of new creation debug.txt.
Only get information of debug and statistics.
<xsql-script name='debug_sample4'> <body> <debug dump='true' level='none' /> <set name='word1'>hello</set> <set name='word2'>world</set> <set name='sentence'> <string><word1/><string.space /><word2/></string> </set> <println><sentence/></println> </body> </xsql-script>
In this case, the result only shows statistic information, because the debug level is disabled:
< SCRIPT (p:\tmp\dvt\debug_test) > User........................: null Current tag.................: [sentence: null] Current line................: 9 Execution time..............: 00:00.031 Local module functions......: 0 < SQL SELECT > Cached ResultSets...........: 0 (0 / 0) 0,00 (N/A) Instructions of type select.: 0 (cached = 0, direct = 0, prepared = 0) Physically executed fetch...: 0 < SQL STATEMENTS > Cached Statements...........: 0 (0 / 0) 0,00 (N/A) Physically Prepared.........: 0 (cached = 0, direct = 0) Physically executed insert..: 0 / 0 Physically executed delete..: 0 / 0 Physically executed update..: 0 / 0 Physically executed exec-f..: 0 Physically executed exec-p..: 0 Physically executed other...: 0 Physically executed total...: 0 (direct = 0, prepared = 0) < SPL FUNCTIONS > Cached function calls.......: (0 / 0) 0,00 (N/A) < SPL PROCEDURES > Cached procedures calls.....: (0 / 0) 0,00 (N/A) < SCRIPT FUNCTIONS > Cached script calls.........: (0 / 0) 0.00,00 (N/A) < LOCAL VARIABLES (3) > +--------+-+--------+-------------------------+--------+-----------+ |name |P|recycles|Type XML |Type SQL|Data | +--------+-+--------+-------------------------+--------+-----------+ |sentence| | 0|string (java.lang.String)|CHAR |hello world| |word1 | | 0|string (java.lang.String)|CHAR |hello | |word2 | | 0|string (java.lang.String)|CHAR |world | +--------+-+--------+-------------------------+--------+-----------+
Get the SQL Explain of the performed SQL query and recover the file from an e-mail.
<xsql-script name='debug_sample2'> <body> <debug explain='true' mailto='destinatario@deister.es' smtphost='mail.deister.net' /> <file.out.open id='out1'> <file name='z:\yy' type='absolute' /> </file.out.open> <file.out.print.sql id='out1' head='false'> <select> <columns>*</columns> <from table='cdiarios'> <join table='cdiarios' type='left' alias='b'> <on>cdiarios.codigo = b.codigo</on> </join> </from> <where> cdiarios.nomdia like '%b%' </where> <group>1,2,3,4</group> <order>1</order> </select> </file.out.print.sql> </body> </xsql-script>
The headboard from the e-mail who would receive the recipient is shown below:
Subject: debug file generated at p:\tmp\test Date: Mon Oct 31 14:51:37 CET 2005 From: xsqlscript.debug@deister.net To: destinatario@deister.es Attached: debug.txt.gz debug.xml.gz sqlexplain.txt.gz XSQLScript debug from script p:\tmp\test user=null pool=null host=camelot addr=192.168.10.104 This is an automatic generated message from DEISTER Axional Studio application server. Please, do not respond!
Where sqlexplain.txt the SQL Explain of the performed SQL query.
2 Main cases
The main uses of debugging are a query performance test or tracking variables in a script.
2.1 Query performance
In this case, we make two queries and analyze the times in the table TOP SQL STATEMENTS
The debug attributes required in this case are dump = true and level = none. These attributes are the ones that are by default.
<xsql-script> <body> <debug mailto='destinatario@deister.es' smtphost='mail.deister.net'/> <select prefix='m_'> <columns> the_year the_year1, SUM(store_sales) total_sales1, SUM(store_cost) total_cost1 </columns> <from table='sales_fact'> <join table='time_by_day'> <on>sales_fact.time_id = time_by_day.time_id</on> </join> </from> <where> the_year = 1998 </where> <group>1</group> </select> <select prefix='m_'> <columns> the_year the_year2, SUM(sales) total_sales2, SUM(cost) total_cost2 </columns> <from table='sales_fact_yearmonth_store'/> <where> the_year = 1998 </where> <group>1</group> </select> <println> ok <m_the_year1/> total_sales: <m_total_sales2/> </println> </body> </xsql-script>
The headboard from the e-mail who would receive the recipient is shown below:
< FUNCTION CALLS > +--------+----+----+----+-----+----+----+----+ |Function|Rank|Self|Acum|Count|Min |Max |Avg | +--------+----+----+----+-----+----+----+----+ |select | 1|0.24|0.24| 2|0.01|0.23|0.12| |println | 2|0.00|0.24| 1|0.00|0.00|0.00| +--------+----+----+----+-----+----+----+----+ < TOP SQL STATEMENTS > +-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+ |Script |Rank|Self|Acum|Count|Line|User |Dbms |SQL | +-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+ |<embed>| 1|0.23|0.23| 1| 6|user.deister |sample_foodmart| | | | | | | | | | |SELECT | | | | | | | | | | the_year the_year1, | | | | | | | | | | SUM(store_sales) total_sales1, | | | | | | | | | | SUM(store_cost) total_cost1 | | | | | | | | | | | | | | | | | | | | FROM sales_fact | | | | | | | | | | ,time_by_day | | | | | | | | | | WHERE | | | | | | | | | | sales_fact.time_id = time_by_day.time_id| | | | | | | | | |[ 5 line(s) more ] | |<embed>| 2|0.01|0.23| 1| 23|user.deister |sample_foodmart| | | | | | | | | | |SELECT | | | | | | | | | | the_year the_year2, | | | | | | | | | | SUM(sales) total_sales2, | | | | | | | | | | SUM(cost) total_cost2 | | | | | | | | | | | | | | | | | | | | FROM sales_fact_yearmonth_store | | | | | | | | | | WHERE | | | | | | | | | | | | | | | | | | | | the_year = 1998 | | | | | | | | | |[ 3 line(s) more ] | +-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+ < ALL(2) SQL STATEMENTS (ACUMULATED TIME AND COUNT) > +-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+ |Script |Rank|Self|Acum|Count|Line|User |Dbms |SQL | +-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+ |<embed>| 1|0.23|0.23| 1| 6|user.deister |sample_foodmart| | | | | | | | | | |SELECT | | | | | | | | | | the_year the_year1, | | | | | | | | | | SUM(store_sales) total_sales1, | | | | | | | | | | SUM(store_cost) total_cost1 | | | | | | | | | | | | | | | | | | | | FROM sales_fact | | | | | | | | | | ,time_by_day | | | | | | | | | | WHERE | | | | | | | | | | sales_fact.time_id = time_by_day.time_id| | | | | | | | | |[ 5 line(s) more ] | |<embed>| 2|0.01|0.23| 1| 23|user.deister |sample_foodmart| | | | | | | | | | |SELECT | | | | | | | | | | the_year the_year2, | | | | | | | | | | SUM(sales) total_sales2, | | | | | | | | | | SUM(cost) total_cost2 | | | | | | | | | | | | | | | | | | | | FROM sales_fact_yearmonth_store | | | | | | | | | | WHERE | | | | | | | | | | | | | | | | | | | | the_year = 1998 | | | | | | | | | |[ 3 line(s) more ] | +-------+----+----+----+-----+----+-------------+---------------+-----------------------------------------------+ < DATABASE SESSION STATISTICS > < MEMORY POOLS STATUS > +-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+ Memory pools +-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+ | |Usage |Peak |Threshold | +-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+ |rowid|poolname |pooltype|jvm_flags |used |commited |max |percent_used|peak_used |peak_max |th_max |th_percent|th_count|th_exceed| +-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+ |0 |G1 Eden Space |HEAP |-Xmx,-XX:MaxNewSize | 251 MB| 482 MB| -1 b| | 902 MB| 0 b| | | | | |1 |G1 Old Gen |HEAP |-Xmx | 1.11 GB| 1.46 GB| 2 GB| 55.43 %| 1.62 GB| 2 GB| 1.60 GB| 80| 5|false | |2 |G1 Survivor Space |HEAP |-Xmx | 73 MB| 73 MB| -1 b| | 84 MB| 0 b| | | | | |3 |CodeHeap 'non-nmethods' |NON_HEAP|-XX:ReservedCodeCacheSize| 1.56 MB| 2.44 MB| 5.56 MB| 28.12 %| 1.68 MB| 5.56 MB| 0 b| | 0|false | |4 |Metaspace |NON_HEAP| | 193.68 MB| 239.92 MB| -1 b| | 210.83 MB| 0 b| 0 b| | 0|false | |5 |CodeHeap 'profiled nmethods' |NON_HEAP|-XX:ReservedCodeCacheSize| 71.70 MB| 73.88 MB| 117.22 MB| 61.17 %| 72.02 MB| 117.22 MB| 0 b| | 0|false | |6 |CodeHeap 'non-profiled nmethods'|NON_HEAP|-XX:ReservedCodeCacheSize| 58.71 MB| 59.19 MB| 117.22 MB| 50.09 %| 59.01 MB| 117.22 MB| 0 b| | 0|false | +-----+--------------------------------+--------+-------------------------+-----------+-----------+-----------+------------+-----------+-----------+-----------+----------+--------+---------+
Where sqlexplain.txt the SQL Explain of the performed SQL query.
2.2 Script tracking
In this example we can track the use of three local functions.
The debug attributes required in this case are level = 'soft' and dump = 'true' (default attribute)
<xsql-script> <body> <debug mailto='destinatario@deister.es' smtphost='localhost' level='soft' /> <function name='get_sales_year'> <args> <arg name='p_year'/> </args> <body> <select prefix='m_'> <columns> SUM(store_sales) total_sales </columns> <from table='sales_fact'> <join table='time_by_day'> <on>sales_fact.time_id = time_by_day.time_id</on> </join> </from> <where> the_year = <p_year/> </where> </select> <return><m_total_sales/></return> </body> </function> <function name='get_cost_year'> <args> <arg name='p_year'/> </args> <body> <select prefix='m_'> <columns> SUM(cost) total_cost </columns> <from table='sales_fact_yearmonth_store'/> <where> the_year = <p_year/> </where> </select> <return><m_total_cost/></return> </body> </function> <function name='get_gain_year'> <args> <arg name='p_year'/> </args> <body> <set name='m_total_sales'><get_sales_year><p_year/></get_sales_year></set> <set name='m_total_cost'><get_cost_year><p_year/></get_cost_year></set> <return><mul><sub><div><ifnull><m_total_sales/>0</ifnull><ifnull><m_total_cost/>1</ifnull></div>1</sub>100</mul></return> </body> </function> <println> total gain : <get_gain_year>1998</get_gain_year>% </println> </body> </xsql-script>
:..</debug> :..<function/> :..</function> :..<function/> :..</function> :..<function/> :..</function> :..<println/> :..<get_gain_year/> internal :...<get_gain_year/> call attribute p_year=java.lang.Integer[1998] type=null ->get_gain_year:<function/> ->get_gain_year:.<body/> ->get_gain_year:..<set/> ->get_gain_year:...<get_sales_year/> internal ->get_gain_year:....</p_year> var=Variable 'p_year' java.lang.Integer[1998] ->get_gain_year:....<get_sales_year/> call attribute p_year=java.lang.Integer[1998] type=null ->get_gain_year->get_sales_year:<function/> ->get_gain_year->get_sales_year:.<body/> ->get_gain_year->get_sales_year:..<select/> ->get_gain_year->get_sales_year:..</p_year> var=Variable 'p_year' java.lang.Integer[1998] <RUN sample_foodmart transaction='false' tag='select' method='__prepareStatement'> SELECT SUM(store_sales) total_sales FROM sales_fact ,time_by_day WHERE sales_fact.time_id = time_by_day.time_id AND the_year = ? </RUN> ->get_gain_year->get_sales_year:..<select/> prepared statement stored in cache, size=1 ps=JDBCPreparedStatement[00000008][JDBCConnection[ <PREPAREDSTATEMENT hold='HOLD_CURSORS_OVER_COMMIT' class='deister.axional.server.jdbc.impl.JDBCPreparedStatement'> ->get_gain_year->get_sales_year:..<select/> setUpdateParameter(1) sqltype=4 (INTEGER) value=[1998] class=java.lang.Integer <RESULTSET hold='HOLD_CURSORS_OVER_COMMIT' type='FORWARD_ONLY' class='deister.axional.server.jdbc.impl.JDBCResultSet'> ->get_gain_year->get_sales_year: <resultset-autovars prefix='m_' struct='' preserve-case='false'> ->get_gain_year->get_sales_year: set rs variable m_total_sales = [1079147.4700] sqltype(3, DECIMAL) isnull(false) java.math.BigDecimal ->get_gain_year->get_sales_year: </resultset-autovars> ->get_gain_year->get_sales_year:..</select> data=java.math.BigDecimal[1079147.4700] ->get_gain_year->get_sales_year:..<return/> ->get_gain_year->get_sales_year:....</m_total_sales> var=Variable 'm_total_sales' java.math.BigDecimal[1079147.4700] ->get_gain_year->get_sales_year:..</return> ->get_gain_year->get_sales_year:.</body> return=java.math.BigDecimal[1079147.4700] ->get_gain_year->get_sales_year:</function> ->get_gain_year:..</set> data=Variable 'm_total_sales' java.math.BigDecimal[1079147.4700] ->get_gain_year:..<set/> ->get_gain_year:...<get_cost_year/> internal ->get_gain_year:....</p_year> var=Variable 'p_year' java.lang.Integer[1998] ->get_gain_year:....<get_cost_year/> call attribute p_year=java.lang.Integer[1998] type=null ->get_gain_year->get_cost_year:<function/> ->get_gain_year->get_cost_year:.<body/> ->get_gain_year->get_cost_year:..<select/> ->get_gain_year->get_cost_year:..</p_year> var=Variable 'p_year' java.lang.Integer[1998] <RUN sample_foodmart transaction='false' tag='select' method='__prepareStatement'> SELECT SUM(cost) total_cost FROM sales_fact_yearmonth_store WHERE the_year = ? </RUN> ->get_gain_year->get_cost_year:..<select/> prepared statement stored in cache, size=2 ps=JDBCPreparedStatement[00000009][JDBCConnection[ <PREPAREDSTATEMENT hold='HOLD_CURSORS_OVER_COMMIT' class='deister.axional.server.jdbc.impl.JDBCPreparedStatement'> ->get_gain_year->get_cost_year:..<select/> setUpdateParameter(1) sqltype=4 (INTEGER) value=[1998] class=java.lang.Integer <RESULTSET hold='HOLD_CURSORS_OVER_COMMIT' type='FORWARD_ONLY' class='deister.axional.server.jdbc.impl.JDBCResultSet'> ->get_gain_year->get_cost_year:..<select/> resultset returned from query, rs=JDBCResultSet[rs134426:st9][refc=1/1][JDBCPreparedStatement[00000009][JDBCConnection[ ->get_gain_year->get_cost_year: <resultset-autovars prefix='m_' struct='' preserve-case='false'> ->get_gain_year->get_cost_year: set rs variable m_total_cost = [432565.7289] sqltype(3, DECIMAL) isnull(false) java.math.BigDecimal ->get_gain_year->get_cost_year: </resultset-autovars> ->get_gain_year->get_cost_year:..</select> data=java.math.BigDecimal[432565.7289] ->get_gain_year->get_cost_year:..<return/> ->get_gain_year->get_cost_year:....</m_total_cost> var=Variable 'm_total_cost' java.math.BigDecimal[432565.7289] ->get_gain_year->get_cost_year:..</return> ->get_gain_year->get_cost_year:.</body> return=java.math.BigDecimal[432565.7289] ->get_gain_year->get_cost_year:</function> ->get_gain_year:..</set> data=Variable 'm_total_cost' java.math.BigDecimal[432565.7289] ->get_gain_year:..<return/> ->get_gain_year:....<mul/> ->get_gain_year:.....<sub/> ->get_gain_year:......<div/> ->get_gain_year:.......<ifnull/> ->get_gain_year:........</m_total_sales> var=Variable 'm_total_sales' java.math.BigDecimal[1079147.4700] ->get_gain_year:.......</ifnull> data=java.math.BigDecimal[1079147.4700] ->get_gain_year:.......<ifnull/> ->get_gain_year:........</m_total_cost> var=Variable 'm_total_cost' java.math.BigDecimal[432565.7289] ->get_gain_year:.......</ifnull> data=java.math.BigDecimal[432565.7289] ->get_gain_year:......</div> data=java.math.BigDecimal[2.4947595195399216] ->get_gain_year:.....</sub> data=java.math.BigDecimal[1.4947595195399216] ->get_gain_year:....</mul> data=java.math.BigDecimal[149.4759519539921600] ->get_gain_year:..</return> ->get_gain_year:.</body> return=java.math.BigDecimal[149.4759519539921600] ->get_gain_year:</function> :..</println> data=java.lang.String[ total gain : 149.4759519539921600% ]