Wiki source code of Debugging

Version 24.1 by Thomas Mortagne on 2015/05/18 11:27

Show last authors
1 There are several possibilities for debugging XWiki:
2
3 {{toc/}}
4
5 = Debug mode =
6
7 [Since 7.1]
8
9 It's possible to enable debug log by adding ##debug=true## (as in [[http://127.0.0.1:8080/xwiki/bin/Main/WebHome?debug=true]]) to the URL. This provide various details on what exactly happens during the request.
10
11 == Elapsed time tree ==
12
13 A detailed tree of how long has been spent in each step. You can add you own step to the tree by using [[progress API>>extensions:Extension.Job Module||anchor="HNotifyaboutprogress"]].
14
15 = Debugging XWiki from your IDE =
16
17 == Debugging with Eclipse ==
18
19 Once you've gotten the debugger working, you'll wonder how you ever survived without it.
20
21 === Complete tutorial based on M2Eclipse and WTP ===
22
23 [[Debug XWiki with Eclipse>>DebugXEWithEclipse]]
24
25 === Debug a XWiki released version ===
26
27 * Follow the steps from [[Building In Eclipse>>BuildingInEclipse]] including the optional "Import the WAR as a web project".
28 * Select from the Eclipse menu **Run > Debug...**
29 * Create a new configuration for your server
30 * Hit the **Debug** button
31 * Set breakpoints, step through code, have fun!
32
33 WTP will deploy XWiki into ##{workspace_location}/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/webapps/xwiki##. If you suspect a change has not been deployed correctly (e.g. a change to a config file), check there to confirm.
34
35 If you are working on an XWiki plugin in a separate project in your workspace, you can ensure it is automatically deployed to XWiki's ##WEB-INF/lib## directory when debugging. Open the project properties of the XWiki project resulting from the WAR import above, go to the ##J2EE Module Dependencies## section, and add your plugin project.
36
37 === Using Firebug when debugging a selenium test ===
38
39 For that you will need to install Firebug [[as a global extension>>http://kb.mozillazine.org/Installing_extensions#Global_installation]]
40
41 = Remote Debugging =
42
43 To perform remote debugging, start your wiki in debug mode. To do this modify the way you start your container and ensure that the following JVM parameters are passed:
44
45 {{code}}
46 -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
47 {{/code}}
48
49 For example, for Jetty you could use the following start script:
50
51 {{code}}
52 #!/bin/sh
53
54 JETTY_HOME=.
55 JETTY_PORT=8080
56 JAVA_OPTS="-Xmx300m -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
57
58 java $JAVA_OPTS -Dfile.encoding=iso-8859-1 -Djetty.port=$JETTY_PORT -Djetty.home=$JETTY_HOME -jar $JETTY_HOME/start.jar
59 {{/code}}
60
61 {{info}}
62 You can also easily run Jetty in debug mode by using the [[jettyrun profile in the Maven build>>Building#HUsingProfiles]].
63 {{/info}}
64
65 If you are using the Tomcat service on Windows, you should modify the JVM args with the Tomcat Service Configuration Panel. Select the Java tab and add each of the options **on a separate line**. For example:
66
67 {{code}}
68 -Dcatalina.home=C:\Program Files\Apache Software Foundation\Tomcat 5.5
69 -Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 5.5
70 -Djava.endorsed.dirs=C:\Program Files\Apache Software Foundation\Tomcat 5.5\common\endorsed
71 -Djava.io.tmpdir=C:\Program Files\Apache Software Foundation\Tomcat 5.5\temp
72 -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
73 -Djava.util.logging.config.file=C:\Program Files\Apache Software Foundation\Tomcat 5.5\conf\logging.properties
74 -Xdebug
75 -Xnoagent
76 -Djava.compiler=NONE
77 -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
78 {{/code}}
79
80 Then, in your favorite IDE, open the XWiki project and run a remote debugging session, attached to the socket on port 5005. For example, if you're using IntelliJ IDEA, go to ##Run|Edit Configurations...## and create a new ##Remote## configuration (default parameters should be fine). Then execute it and IDEA will connect to the executing JVM.
81
82 You can then place breakpoints in your source code.
83
84 = Logging =
85
86 == Turning on logging inside XWiki ==
87
88 See the [[Logging page in the Admin guide>>platform:AdminGuide.Logging]].
89
90 == Logging shutdown operations ==
91
92 {{info}}XWiki 6.3M1+{{/info}} To log debug information of what happens when there are shutdown operations, simply set the log level to ##DEBUG## for the ##org.xwiki.shutdown## logger:
93
94 {{code language="xml"}}
95 <logger name="org.xwiki.shutdown" level="info"/>
96 {{/code}}
97
98 == Logging calls at the database level ==
99
100 You have several options:
101 * Configure Hibernate to log SQL calls. To do this edit XWiki's log configuration file (see the [[Logging page>>platform:AdminGuide.Logging]]) and change the log level from ##warn## to ##trace## for the following:(((
102 {{code language="none"}}
103 <!-- Log HQL query parser activity -->
104 <logger name="org.hibernate.hql.ast.AST" level="warn"/>
105 <!-- Log just the SQL -->
106 <logger name="org.hibernate.SQL" level="warn"/>
107 <!-- Log JDBC bind parameters -->
108 <logger name="org.hibernate.type" level="warn"/>
109 <!-- Log schema export/update -->
110 <logger name="org.hibernate.tool.hbm2ddl" level="warn"/>
111 <!-- Log HQL parse trees -->
112 <logger name="org.hibernate.hql" level="warn"/>
113 <!-- Log cache activity -->
114 <logger name="org.hibernate.cache" level="warn"/>
115 <!-- Log transaction activity -->
116 <logger name="org.hibernate.transaction" level="warn"/>
117 <!-- Log JDBC resource acquisition -->
118 <logger name="org.hibernate.jdbc" level="warn"/>
119 <!-- Enable the following line if you want to track down connection leakages when using
120 DriverManagerConnectionProvider -->
121 <logger name="org.hibernate.connection.DriverManagerConnectionProvider" level="warn"/>
122 <!-- Log prepared statement cache activity -->
123 <logger name="org.hibernate.ps.PreparedStatementCache" level="warn"/>
124 {{/code}}
125 )))
126 * Use a wrapping JDBC driver such as [[log4jdbc>>http://code.google.com/p/log4jdbc/]] or [[p6spy>>http://sourceforge.net/projects/p6spy/]].
127 * Turn on logging in your database. The configuration is database-dependent
128 ** For **HSQLDB**. Two solutions:
129 *** Solution 1: Edit ##WEB-INF/hibernate.cfg.xml## and modify the URL connection property to add ##hsqldb.sqllog=3##, as in:(((
130 {{code language="none"}}
131 <property name="connection.url">jdbc:hsqldb:file:${environment.permanentDirectory}/database/xwiki_db;shutdown=true;hsqldb.sqllog=3</property>
132 {{/code}}
133 )))
134 *** Solution 2: Using Byteman (See the section below for more information). For example the following rule (tested on HSQLDB 2.3.1) will log SQL statements with parameters and schema when there's more than 1 parameter:(((
135 {{code language="none"}}
136 RULE Log SQL Statement
137 CLASS org.hsqldb.Session
138 METHOD executeCompiledStatement(org.hsqldb.Statement, Object[], int)
139 AT ENTRY
140 IF $2.length > 0
141 DO traceln("SQL Statement = [" + $1.getSQL() + "], parameter 1 = [" + $2[0] + "], schema = [" + $1.getSchemaName().name + "]")
142 ENDRULE
143 {{/code}}
144
145 Will give for example:
146
147 {{code language="none"}}
148 SQL Statement = [select xwikidocum0_.XWD_ID as XWD1_0_0_, xwikidocum0_.XWD_FULLNAME as XWD2_0_0_, xwikidocum0_.XWD_NAME as XWD3_0_0_, xwikidocum0_.XWD_TITLE as XWD4_0_0_, xwikidocum0_.XWD_LANGUAGE as XWD5_0_0_, xwikidocum0_.XWD_DEFAULT_LANGUAGE as XWD6_0_0_, xwikidocum0_.XWD_TRANSLATION as XWD7_0_0_, xwikidocum0_.XWD_DATE as XWD8_0_0_, xwikidocum0_.XWD_CONTENT_UPDATE_DATE as XWD9_0_0_, xwikidocum0_.XWD_CREATION_DATE as XWD10_0_0_, xwikidocum0_.XWD_AUTHOR as XWD11_0_0_, xwikidocum0_.XWD_CONTENT_AUTHOR as XWD12_0_0_, xwikidocum0_.XWD_CREATOR as XWD13_0_0_, xwikidocum0_.XWD_WEB as XWD14_0_0_, xwikidocum0_.XWD_CONTENT as XWD15_0_0_, xwikidocum0_.XWD_VERSION as XWD16_0_0_, xwikidocum0_.XWD_CUSTOM_CLASS as XWD17_0_0_, xwikidocum0_.XWD_PARENT as XWD18_0_0_, xwikidocum0_.XWD_CLASS_XML as XWD19_0_0_, xwikidocum0_.XWD_ELEMENTS as XWD20_0_0_, xwikidocum0_.XWD_DEFAULT_TEMPLATE as XWD21_0_0_, xwikidocum0_.XWD_VALIDATION_SCRIPT as XWD22_0_0_, xwikidocum0_.XWD_COMMENT as XWD23_0_0_, xwikidocum0_.XWD_MINOREDIT as XWD24_0_0_, xwikidocum0_.XWD_SYNTAX_ID as XWD25_0_0_, xwikidocum0_.XWD_HIDDEN as XWD26_0_0_ from xwikidoc xwikidocum0_ where xwikidocum0_.XWD_ID=?], parameter 1 = [-4526159677276379501], schema = [TEST91]
149 {{/code}}
150 )))
151
152 == Using Byteman ==
153
154 [[Byteman>>https://www.jboss.org/byteman]] is a great framework that allows to modify bytecode in a running JVM. It can easily be used to add logging (for ex) to find out what's happening in a running XWiki instance. Here's a quick tutorial:
155 * Download Byteman and unzip it in a directory. Set the ##$BYTEMAN_HOME## environment property to point to the directory where you've unzipped it. For example:
156 {{code}}
157 export BYTEMAN_HOME=/Users/vmassol/dev/byteman/byteman-download-2.1.0
158 {{/code}}
159 * Start an XWiki instance somewhere on the same machine
160 * Go to ##$BYTEMAN_HOME/bin## and connect Byteman to XWiki. For example:
161 {{code}}
162 sh bminstall.sh -b -Dorg.jboss.byteman.transform.all jetty/start.jar
163 {{/code}}
164 * Now create a Byteman rule by creating a file, for example ##my.btm## with the following:
165 (((
166 {{code}}
167 RULE XWiki Docs loaded
168 CLASS XWikiHibernateStore
169 METHOD loadXWikiDoc
170 AT ENTRY
171 IF TRUE
172 DO traceln("Load document = " + $1.getDocumentReference())
173 ENDRULE
174 {{/code}}
175 )))
176 * Load this rule with: {{code}}sh bmsubmit.sh -l my.btm{{/code}}
177 * Call a URL in your wiki and check that the console prints the document references that get loaded! For example:
178 (((
179 {{code}}
180 Load document = xwiki:Main.WebPreferences
181 Load document = xwiki:ColorThemes.DefaultColorTheme
182 Load document = xwiki:XWiki.SearchSuggestConfig
183 Load document = xwiki:XWiki.SearchSuggestConfig
184 Load document = xwiki:Dashboard.WebHome
185 Load document = xwiki:XWiki.GadgetClass
186 Load document = xwiki:Dashboard.WebHome
187 Load document = xwiki:Dashboard.WebPreferences
188 Load document = xwiki:Dashboard.colibri
189 Load document = xwiki:Main.Welcome
190 ...
191 {{/code}}
192 )))
193 * Modify your rule or add new rules to the same file and apply the changes with {{code}}sh bmsubmit.sh -l my.btm{{/code}}
194 * Remove your rules with {{code}}sh bmsubmit.sh -u{{/code}}
195
196 For more read [[A Byteman tutorial>>https://community.jboss.org/wiki/ABytemanTutorial]] or the [[Reference documentation>>http://downloads.jboss.org/byteman/2.0.1/ProgrammersGuideSinglePage.html]].
197
198 === Example ===
199
200 In this example we'll print calls to ##CommonsConfigurationSource.containsKey(...)## with the parameters printed and the time it takes to execute. In addition we'll also print calls to ##XWiki.getDocument(String, XWikiContext)## which is a deprecated method which, for the purpose of this example, we think generate the calls to ##containsKey##.
201
202 {{code}}
203 RULE Create timer for containsKey
204 CLASS CommonsConfigurationSource
205 METHOD containsKey
206 AT ENTRY
207 IF TRUE
208 DO resetTimer("containsKey")
209 ENDRULE
210
211 RULE Calls to containsKey
212 CLASS CommonsConfigurationSource
213 METHOD containsKey
214 AT EXIT
215 IF TRUE
216 DO traceln("containsKey for [" + $1 + "] = [" + $! + "], time = [" + getElapsedTimeFromTimer("containsKey") + "]")
217 ENDRULE
218
219 RULE Calls to deprecated getDocument
220 CLASS com.xpn.xwiki.XWiki
221 METHOD getDocument(String, XWikiContext)
222 AT ENTRY
223 IF TRUE
224 DO traceStack("getDocument() called for [" + $1 + "] ", 3)
225 ENDRULE
226 {{/code}}
227
228 Generates:
229
230 {{code}}
231 ...
232 getDocument() called for [XWiki.Admin] com.xpn.xwiki.XWiki.getDocument(XWiki.java:-1)
233 com.xpn.xwiki.XWiki.getUserName(XWiki.java:5072)
234 com.xpn.xwiki.XWiki.getUserName(XWiki.java:5062)
235 . . .
236 containsKey for [model.reference.default.document] = [false], time = [0]
237 containsKey for [model.reference.default.document] = [false], time = [0]
238 containsKey for [model.reference.default.space] = [false], time = [0]
239 containsKey for [model.reference.default.space] = [false], time = [0]
240 containsKey for [model.reference.default.wiki] = [false], time = [0]
241 containsKey for [model.reference.default.wiki] = [false], time = [1]
242 getDocument() called for [XWiki.DefaultSkin] com.xpn.xwiki.XWiki.getDocument(XWiki.java:-1)
243 com.xpn.xwiki.XWiki.getSkinFile(XWiki.java:1955)
244 com.xpn.xwiki.XWiki.getSkinFile(XWiki.java:1918)
245 . . .
246 ...
247 {{/code}}
248
249 = Debugging JavaScript =
250
251 The solution is to use a Browser add-on for inspecting JavaScript and putting breakpoints in it. The issue is that by default the XWiki build will minify and aggregate JavaScript files for performance reasons.
252
253 However there's a solution:
254 * Start by building XWiki with the ##debug## profile (##mvn clean install -Pdebug##)
255 * Then once you're on a page make sure to pass ##?minify=false## in the URL. If you don't do this then the aggregated JS files are going to be referenced and since they don't exist, the JS code will break
256
257 = Debugging the WYSIWYG editor =
258
259 == Debugging the Java code ==
260
261 === Debugging the client side Java code ===
262
263 Starting with GWT 2.0 we can run and debug the client side Java code directly in the browser. This is called Development Mode. Follow these steps:
264
265 1. Copy ##src/test/resources/start_wysiwyg_noserver_debug.sh## from the ##xwiki-gwt-wysiwyg-server## module to the root of your XWiki Enterprise installation. For the standard jetty+hsqldb distribution this is the directory where ##start_xwiki.sh## is located.
266 1. ##chmod 755 start_wysiwyg_noserver_debug.sh##
267 1. Open ##start_wysiwyg_noserver_debug.sh## with a text editor and make sure that the variables defined at the beginning of the file match what you have on your system.
268 1. The GWT Development Mode requires GWT Java sources (so not only the byte code) to be in the class path. The debug script looks for the needed dependencies in the local maven repository. Building the ##xwiki-gwt-*## modules ensures these dependencies are in your local maven repository. Alternatively you can edit the debug script and reference these dependencies with a different path.
269 1. Start the server (e.g. ##./start_xwiki.sh##).
270 1. ##./start_wysiwyg_noserver_debug.sh##
271 1. Connect to the specified port using your IDE. The client side code is in the ##xwiki-gwt-wysiwyg-client## maven module. Make sure you have imported it in your IDE.
272 1. The GWT Development Mode window should have opened. Click "Copy to Clipboard" to copy the startup URL.
273 1. Paste the startup URL in your browser's address bar and load it.
274 1. You may be asked to login since you're going to edit a wiki page in WYSIWYG mode.
275 1. You may be asked to install the GWT Developer plugin, if this is the first time you try to debug GWT code in Development Mode.
276 1. If you receive a message that tells you your GWT code needs to be recompiled just refresh the page. Note that the exiting JavaScript code of the editor (##resources/js/xwiki/wysiwyg/xwe##) might be affected so you should backup it if you don't have other means of restoring it.
277 1. At this point the WYSIWYG editor should be loaded and you should be able to add break points using your Java IDE. Currently the editor toolbar is badly displayed in debug mode due to some CSS issue we need to fix.
278
279 === Debugging the server side code ===
280
281 You can debug the server side code remotely. Start your wiki in debug mode (e.g. using the ##start_xwiki_debug.sh## script) and then connect with your IDE to the specified port. The server side code of the WYSIWYG editor is in the ##xwiki-gwt-wysiwyg-server## module. Make sure you have imported it in your IDE.
282
283 == Debugging the JavaScript code ==
284
285 The JavaScript code of the WYSIWYG editor is obfuscated by default to reduce its size. To be able to debug it you have to rebuild the editor using the detailed GWT compilation style. One way to achieve this is with the ##-Pdev## maven profile. Alternatively you can edit the pom of the ##xwiki-gwt-wysiwyg-server## module and change the value of the ##gwt.style## property. After you rebuild the editor, update your XWiki Enterprise instance and clean your browser's cache. Note that with the detailed style the JavaScript code is huge (around 5MB currently) so most of the debuggers will respond pretty slow. Sometimes you can save time by adding your break points from the JavaScript code. Edit the ##<hash>.cache.html## file that is loaded by your browser and add ##debugger## where you want the execution to be stopped. A quick way to find methods in the detailed JavaScript code is to search for ##<ClassName>.prototype##, e.g. ##RichTextArea.prototype##.

Get Connected