summaryrefslogtreecommitdiffstats
path: root/Documentation/dev-inspector.txt
blob: 2134f2f77aa0a5530d3254e65a35f1327cd0686b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
= Gerrit Inspector

== NAME
Gerrit Inspector - Interactive Jython environment for Gerrit

== SYNOPSIS
[verse]
--
_java_ -jar gerrit.war _daemon_
  -d <SITE_PATH>
  [--enable-httpd | --disable-httpd]
  [--enable-sshd | --disable-sshd]
  [--console-log]
  [--slave]
  -s
--

== DESCRIPTION
Runs the Gerrit network daemon on the local system as described
in the link:pgm-daemon.html[Daemon documentation], additionally
starting an interactive Jython shell for inspection
and troubleshooting of live data of the Gerrit instance.

CAUTION: Gerrit Inspector works directly on instances of Java Virtual
Machine objects and it is possible to read and write instance
members as well as invoke Java functions. Access is granted
also to 'private' and 'protected' members. Therefore it is possible
to introduce changes to the internal state of the system in
an inconsistent way. Care must be taken not to break the running system
and/or destroy the data.

== INSTALLATION

Gerrit Inspector requires Jython library ('jython.jar') to be installed
in the '$site_path/lib' directory. Jython, a Python interpreter for
the Java Virtual Machine, can be obtained from the http://www.jython.org/
website. Only 'jython.jar' file is needed, installation of Jython libraries
is optional. Gerrit Inspector has been tested with Jython 2.5.2 but
might work an earlier version.

== STARTUP

During startup Jython examines Java libraries found on the classpath.
While libraries are inspected a large amount of messages is displayed on the console:

----
*sys-package-mgr*: processing new jar, '/home/user/.gerritcodereview/tmp/gerrit_4890671371398741854_app/sshd-core-0.5.1-r1095809.jar'
----

After this a system-wide embedded initialization script is started. This script
is contained in the gerrit's WAR archive. This script produces output similar to
the following on the console:

----
"Shell" is "com.google.gerrit.pgm.shell.JythonShell@61644f2d"
"m" is "com.google.gerrit.lifecycle.LifecycleManager@6f03b248"
"ds" is "com.google.gerrit.server.schema.DataSourceProvider@6b3592c"
"schk" is "com.google.gerrit.server.schema.SchemaVersionCheck@5e8cb9bd"

Welcome to the Gerrit Inspector
Enter help() to see the above again, EOF to quit and stop Gerrit
----

Then an optional user startup script is processed. It should be
located in the gerrit user home directory as '.gerritcodereview/Startup.py'.

This script can access all variables defined in the system (such
as the ones displayed by the initialization script as shown above).
Variables and functions defined by the startup scripts are available for
the interactive interpreter.

When interactive interpreter exits (by issuing EOF on the command line),
a whole Gerrit instance is shut down gracefully.

== USING THE INTERPRETER

Gerrit Inspector launches Jython interpreter in the context of the Gerrit
Java Virtual Machine. All core facilities of the Jython (and Python)
language are available to the user.

Additional facilities can be provided, for example a 'Lib' directory from the
Jython distribution can be installed under '$site_path/lib/Lib' to provide
access to many standard Python modules. Jython can also use additional Java
classes and libraries and most of the Python modules and scripts.

The Inspector has by default access to classes and object instances available
in the Java Virtual Machine. Objects are introspected and *private* and *protected*
members are also available.

For more information on using Jython, especially with regards to its limitations
in interfacing to the Java Virtual Machine, please refer to the
http://www.jython.org/[Jython documentation].

After successful initialization it is possible to examine components of
Java packages, classes and live instances.

----
>>> import com.google.inject
>>> dir(com.google.inject)
['AbstractModule', 'Binder', 'Binding', 'BindingAnnotation', 'ConfigurationException', 'CreationException', 'Exposed', 'Guice', 'ImplementedBy', 'Inject', 'Injector', 'Key', 'MembersInjector', 'Module', 'OutOfScopeException', 'PrivateBinder', 'PrivateModule', 'ProvidedBy', 'Provider', 'Provides', 'ProvisionException', 'Scope', 'ScopeAnnotation', 'Scopes', 'Singleton', 'Stage', 'TypeLiteral', '__name__', 'assistedinject', 'binder', 'internal', 'matcher', 'name', 'servlet', 'spi', 'util']
>>> type(com.google.inject)
<type 'javapackage'>
>>> dir(com.google.inject.Guice)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__doc__',
'__eq__', '__getattribute__', '__hash__', '__init__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__str__', '__unicode__', 'class', 'clone', 'createInjector',
'equals', 'finalize', 'getClass', 'hashCode', 'notify', 'notifyAll',
'registerNatives', 'toString', 'wait']
----

Startup script provides some convenient variables to access some global Gerrit components,
for example a connection to the review database is kept open:

----
>>> ds
org.apache.commons.dbcp.BasicDataSource@61db2215
>>> ds.driverClassName
u'org.postgresql.Driver'
>>> ds.dataSource
org.apache.commons.dbcp.PoolingDataSource@23226fe1
>>> ds.dataSource.connection
jdbc:postgresql://localhost/reviewdb, UserName=rv, PostgreSQL Native Driver
----

It is also possible to interact with the ORM layer:

----
>>> db = schk.schema.open()
>>> db
com.google.gerrit.reviewdb.server.ReviewDb_Schema_GwtOrm$$28@24cbbdf3
>>> db.getDialect()
com.google.gwtorm.schema.sql.DialectPostgreSQL@4de07d3e
>>> for x in db.patchSets().iterateAllEntities():
...     print x
...
[PatchSet 1,1]
[PatchSet 2,1]
[PatchSet 3,1]
[PatchSet 4,1]
[PatchSet 5,1]
[PatchSet 6,1]
[PatchSet 7,1]
[PatchSet 8,1]
[PatchSet 6,2]
>>> for x in db.patchComments().iterateAllEntities():
...     print x
com.google.gerrit.reviewdb.client.PatchLineComment@5381298a
com.google.gerrit.reviewdb.client.PatchLineComment@44ce4dda
com.google.gerrit.reviewdb.client.PatchLineComment@44594680
>>> dir(com.google.gerrit.reviewdb.client.PatchLineComment)
['Key', 'STATUS_DRAFT', 'STATUS_PUBLISHED', 'Status', '__class__',
'__copy__', '__deepcopy__', '__delattr__', '__doc__', '__eq__',
'__getattribute__', '__hash__', '__init__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'__unicode__', 'author', 'class', 'clone', 'equals', 'finalize',
'getAuthor', 'getClass', 'getKey', 'getLine', 'getMessage',
'getParentUuid', 'getSide', 'getStatus', 'getWrittenOn', 'hashCode',
'key', 'line', 'lineNbr', 'message', 'notify', 'notifyAll',
'parentUuid', 'registerNatives', 'setMessage', 'setSide', 'setStatus',
'side', 'status', 'toString', 'updated', 'wait', 'writtenOn']
>>> for x in db.patchComments().iterateAllEntities():
...     print x.status, x.line, x.message
...
P 2 I like it!
P 2 more
P 1 better
----

A built-in *help()* function provides values of global variables
defined in the interpreter:

----
>>> help()
"schk" is "com.google.gerrit.server.schema.SchemaVersionCheck@5e8cb9bd"
"ds" is "com.google.gerrit.server.schema.DataSourceProvider@6b3592c"
"m" is "com.google.gerrit.lifecycle.LifecycleManager@6f03b248"
"Shell" is "com.google.gerrit.pgm.shell.JythonShell@61644f2d"
"d" is "com.google.gerrit.pgm.Daemon@28a3f689"

Welcome to the Gerrit Inspector
Enter help() to see the above again, EOF to quit and stop Gerrit
----

Java and Python exceptions are intercepted by the Inspector:
----
>>> import java.lang.RuntimeException
>>> raise java.lang.RuntimeException("Exiting")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
        at org.python.core.PyReflectedConstructor.constructProxy(PyReflectedConstructor.java:210)

java.lang.RuntimeException: java.lang.RuntimeException: Exiting
>>>
----

To exit the interpreter, use EOF character (Ctrl-D on Unix systems, Ctrl-Z on Windows).

It is also possible to shut down the JVM by using *System.exit()*

----
>>> import java.lang.System
>>> java.lang.System.exit(1)
----

And Gerrit should shut down all its subsystems and exit:

----
[2012-04-17 15:31:08,458] INFO  com.google.gerrit.pgm.Daemon : caught shutdown, cleaning up
----

== TROUBLESHOOTING

Gerrit Inspector is logging to the Gerrit error log.

A successful startup is indicated in the logfile:

----
  [2012-04-17 13:43:44,888] INFO  com.google.gerrit.pgm.shell.JythonShell : Jython shell instance created.
----

If 'jython.jar' library is not available, Gerrit refuses to start when given *-s* option:

----
[2012-04-17 13:57:29,611] ERROR com.google.gerrit.pgm.Daemon : Unable to start daemon
com.google.inject.ProvisionException: Guice provision errors:

1) Error injecting constructor, java.lang.UnsupportedOperationException: Cannot create Jython shell: Class org.python.util.InteractiveConsole not found
     (You might need to install jython.jar in the lib directory)
  at com.google.gerrit.pgm.shell.JythonShell.<init>(JythonShell.java:47)
  while locating com.google.gerrit.pgm.shell.JythonShell
  while locating com.google.gerrit.pgm.shell.InteractiveShell
----

Errors during processing of the startup script, 'Startup.py', are logged
to the error log:

----
[2012-04-17 14:20:30,558] INFO  com.google.gerrit.pgm.shell.JythonShell : Jython shell instance created.
[2012-04-17 14:20:38,005] ERROR com.google.gerrit.pgm.shell.JythonShell : Exception occurred while loading file Startup.py :
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at com.google.gerrit.pgm.shell.JythonShell.runMethod0(JythonShell.java:112)
        at com.google.gerrit.pgm.shell.JythonShell.execFile(JythonShell.java:194)
        at com.google.gerrit.pgm.shell.JythonShell.reload(JythonShell.java:178)
        at com.google.gerrit.pgm.shell.JythonShell.run(JythonShell.java:152)
        at com.google.gerrit.pgm.Daemon.run(Daemon.java:190)
        at com.google.gerrit.pgm.util.AbstractProgram.main(AbstractProgram.java:67)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at com.google.gerrit.launcher.GerritLauncher.invokeProgram(GerritLauncher.java:167)
        at com.google.gerrit.launcher.GerritLauncher.mainImpl(GerritLauncher.java:91)
        at com.google.gerrit.launcher.GerritLauncher.main(GerritLauncher.java:49)
        at Main.main(Main.java:25)
Caused by: Traceback (most recent call last):
  File "/home/user/.gerritcodereview/Startup.py", line 1, in <module>
    Test
NameError: name 'Test' is not defined
----

Those errors are non-fatal. System and user scripts can be loaded again
by issuing the following command in the Gerrit Inspector console:

----
Shell.reload()
----

== LOGGING
Error and warning messages from the server are automatically written
to the log file under '$site_path/logs/error_log'.

Output and error messages (including Java and Python exceptions)
resulting from interactive work are logged to the console.

== KNOWN ISSUES
The Inspector does not yet recognize Google Guice bindings.

[IMPORTANT]
Using the Inspector may void your warranty.

GERRIT
------
Part of link:index.html[Gerrit Code Review]

SEARCHBOX
---------