diff --git a/src/_zkapauthorizer/controller.py b/src/_zkapauthorizer/controller.py
index 368072d73c1de56a8eccd833a9a03ab5d9553a3e..92e5ccfaca57b63d78ee6330a49f7abc33becef1 100644
--- a/src/_zkapauthorizer/controller.py
+++ b/src/_zkapauthorizer/controller.py
@@ -30,6 +30,9 @@ from zope.interface import (
     implementer,
 )
 
+from twisted.logger import (
+    Logger,
+)
 from twisted.python.url import (
     URL,
 )
@@ -300,6 +303,8 @@ class PaymentController(object):
          the voucher.  The data store marks the voucher as redeemed and stores
          the unblinded tokens for use by the storage client.
     """
+    _log = Logger()
+
     store = attr.ib()
     redeemer = attr.ib()
 
@@ -316,16 +321,20 @@ class PaymentController(object):
         # server signs a given set of random tokens once or many times, the
         # number of passes that can be constructed is still only the size of
         # the set of random tokens.
+        self._log.info("Generating random tokens for a voucher ({voucher}).", voucher=voucher)
         tokens = self.redeemer.random_tokens_for_voucher(Voucher(voucher), 100)
 
         # Persist the voucher and tokens so they're available if we fail.
+        self._log.info("Persistenting random tokens for a voucher ({voucher}).", voucher=voucher)
         self.store.add(voucher, tokens)
 
         # Ask the redeemer to do the real task of redemption.
+        self._log.info("Redeeming random tokens for a voucher ({voucher}).", voucher=voucher)
         d = self.redeemer.redeem(Voucher(voucher), tokens)
         d.addCallback(
             partial(self._redeemSuccess, voucher),
         )
+        # XXX This needs an errback!
 
     def _redeemSuccess(self, voucher, unblinded_tokens):
         """
@@ -333,6 +342,7 @@ class PaymentController(object):
         store the resulting unblinded tokens (which can be used to construct
         passes later).
         """
+        self._log.info("Inserting redeemed unblinded tokens for a voucher ({voucher}).", voucher=voucher)
         self.store.insert_unblinded_tokens_for_voucher(voucher, unblinded_tokens)
 
 
diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py
index 7f78a0b41415370ebe9ca4f18e9fdb1b12da0233..c724fbca870dabb0457688c2ce162b91290161fd 100644
--- a/src/_zkapauthorizer/resource.py
+++ b/src/_zkapauthorizer/resource.py
@@ -24,6 +24,9 @@ from json import (
     loads, dumps,
 )
 
+from twisted.logger import (
+    Logger,
+)
 from twisted.web.http import (
     BAD_REQUEST,
 )
@@ -84,6 +87,8 @@ class _VoucherCollection(Resource):
     redemption controller.  Child resources of this resource can also be
     retrieved to monitor the status of previously submitted vouchers.
     """
+    _log = Logger()
+
     def __init__(self, store, controller):
         self._store = store
         self._controller = controller
@@ -104,6 +109,7 @@ class _VoucherCollection(Resource):
         if not is_syntactic_voucher(voucher):
             return bad_request(u"submitted voucher is syntactically invalid").render(request)
 
+        self._log.info("Accepting a voucher ({voucher}) for redemption.", voucher=voucher)
         self._controller.redeem(voucher)
         return b""