Monitoring D-Bus

Because D-Bus operates for the most part under the hood invisible to the user, means of monitoring D-Bus messages is important for both activation and debugging purposes.  In this post I examine how to monitor and act on such messages.  I assume that you are relatively familiar with D-Bus.  If not, you should look at my previous posts on D-Bus to gain an understanding of the basic concepts.

Probably the most commonly used tool is the command line utility dbus-monitor which was written by Philip Blundell as part of the reference D-Bus implementation and which is standard on most D-Bus enabled platforms.  It is a very powerful utility but unfortunately it's man page is terse and fails to explain the most powerful feature of dbus-monitor i.e. watch expressions.

Suppose, for example, I want to monitor the creation, saving and deletion of Tomboy notes using D-Bus signals.  To get the list of the supported signals I could introspect Tomboy using qdbus i.e.
$ qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl | grep signal
signal void org.gnome.Tomboy.RemoteControl.NoteAdded(QString uri)
signal void org.gnome.Tomboy.RemoteControl.NoteDeleted(QString uri, QString title)
signal void org.gnome.Tomboy.RemoteControl.NoteSaved(QString uri)
or I could use dbus-monitor to look at the signals generated when Tomboy creates, saves and deletes a note.
$ dbus-monitor type=signal interface="org.gnome.Tomboy.RemoteControl"
signal sender=org.freedesktop.DBus -> dest=:1.102 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired
string ":1.102"
signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteAdded
string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"
signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteSaved
string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"
signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteDeleted
string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc"
string "New Note 1"
As you can see Tomboy issues three signals - NoteAdded when a note is added, NoteSaved when a note is saved, and NoteDeleted when a note is deleted.  Interestingly, for some reason NoteDeleted provides both the uri and the title of the note whereas the other two signals only provide the uri.

Suppose I just want to to monitor when a Tomboy note is saved by a user.  I can use a dbus-monitor watch expression for this purpose as shown in the following example.
dbus-monitor "type='signal',sender='org.gnome.Tomboy',interface='org.gnome.Tomboy.RemoteControl',path='/org/gnome/Tomboy/RemoteControl',member='NoteSaved'"
A watch expression is essentially a message filter.  Note the syntax!  Everything between the two double quotes is part of the watch expression.

Unfortunately the syntax of a watch expression is not documented in the dbus-monitor man page.  However from looking at the source code for dbus-monitor, it appears that a watch expression consists of one or more name-value pairs, e.g. sender='org.gnome.Tomboy' separated by commas.  The following are valid names: type, sender, destination, path, interface, member and error_name.  The value of type must be one of the following: signal, method_call, method_return or error

Probably the most powerful feature of dbus-monitor is the fact that you are not limited to using just one watch expression at a time.  The following example simultaneously monitors all 3 Tomboy signals and uses awk to parse the output from dbus-monitor and display a meaningful message.


WATCH1="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteAdded'"
WATCH2="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteSaved'"
WATCH3="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteDeleted'"

dbus-monitor "${WATCH1}" "${WATCH2}" "${WATCH3}" | \
awk '
/member=NoteAdded/ { getline; print "Created note " substr($2,7) }
/member=NoteSaved/ { getline; print "Added note " substr($2,7) }
/member=NoteDeleted/ { getline; print "Deleted note " substr($2,7) }
Here is the output generated when I clicked on the Tomboy icon to create a new note, waited for the automatic save and then selected the delete option to delete the note.
$ ./test
Created note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"
Added note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"
Deleted note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"
Well that is all for this post.  Enjoy!

P.S. I tested these examples using Fedora 10. I have no idea whether they will work on previous versions of Fedora or other Linux distributions.


Daniel said...

Sorry to dredge this up... I'd be interested to know if this script still functions with the latest versions of everything? I get absolutely no output from awk when I run it.

Finnbarr P. Murphy said...

Which OS distribution and version are you using? Fedora 11?

Daniel said...

No, Ubuntu 8.10.

Finnbarr P. Murphy said...

Sorry, but I have no idea what support Ubuntu has for D-Bus. Try running dbus-monitor and Tomboy and see what messages you find.

Daniel said...

Everything seems to work fine separately - running dbus-monitor and Tomboy gives the output I'm expecting; outputting this to a file and running awk works, just not running awk on dbus-monitor.

Cheers for your time though!

Post a Comment