diff --git a/keyserver/addons/rust-node-addon/Cargo.lock b/keyserver/addons/rust-node-addon/Cargo.lock
--- a/keyserver/addons/rust-node-addon/Cargo.lock
+++ b/keyserver/addons/rust-node-addon/Cargo.lock
@@ -649,6 +649,15 @@
  "cfg-if",
 ]
 
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata",
+]
+
 [[package]]
 name = "matchit"
 version = "0.7.0"
@@ -739,6 +748,16 @@
  "libloading",
 ]
 
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.15.0"
@@ -795,6 +814,12 @@
  "zeroize",
 ]
 
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
 [[package]]
 name = "password-hash"
 version = "0.4.2"
@@ -996,6 +1021,15 @@
  "regex-syntax",
 ]
 
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax",
+]
+
 [[package]]
 name = "regex-syntax"
 version = "0.6.28"
@@ -1030,6 +1064,7 @@
  "tonic",
  "tonic-build",
  "tracing",
+ "tracing-subscriber",
 ]
 
 [[package]]
@@ -1099,6 +1134,15 @@
  "digest 0.10.6",
 ]
 
+[[package]]
+name = "sharded-slab"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
+dependencies = [
+ "lazy_static",
+]
+
 [[package]]
 name = "slab"
 version = "0.4.8"
@@ -1108,6 +1152,12 @@
  "autocfg",
 ]
 
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
 [[package]]
 name = "socket2"
 version = "0.4.7"
@@ -1355,6 +1405,36 @@
 checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
 dependencies = [
  "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
+dependencies = [
+ "lazy_static",
+ "log",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
 ]
 
 [[package]]
@@ -1387,6 +1467,12 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
 
+[[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
 [[package]]
 name = "version_check"
 version = "0.9.4"
diff --git a/keyserver/addons/rust-node-addon/Cargo.toml b/keyserver/addons/rust-node-addon/Cargo.toml
--- a/keyserver/addons/rust-node-addon/Cargo.toml
+++ b/keyserver/addons/rust-node-addon/Cargo.toml
@@ -20,6 +20,7 @@
 tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
 tokio-stream = "0.1"
 tracing = "0.1"
+tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
 prost = "0.11"
 comm-opaque2 = {path = "../../../shared/comm-opaque2"}
 lazy_static = "1.4"
diff --git a/keyserver/addons/rust-node-addon/rust-binding-types.js b/keyserver/addons/rust-node-addon/rust-binding-types.js
--- a/keyserver/addons/rust-node-addon/rust-binding-types.js
+++ b/keyserver/addons/rust-node-addon/rust-binding-types.js
@@ -3,7 +3,7 @@
 import type { SignedIdentityKeysBlob } from 'lib/types/crypto-types.js';
 
 type UserLoginResponse = {
-  +userID: string,
+  +userId: string,
   +accessToken: string,
 };
 
diff --git a/keyserver/addons/rust-node-addon/src/identity_client/login.rs b/keyserver/addons/rust-node-addon/src/identity_client/login.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client/login.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client/login.rs
@@ -2,6 +2,7 @@
 
 use comm_opaque2::client::Login;
 use identity_client::{OpaqueLoginFinishRequest, OpaqueLoginStartRequest};
+use tracing::debug;
 
 #[napi]
 #[instrument(skip_all)]
@@ -16,6 +17,8 @@
   content_one_time_keys: Vec<String>,
   notif_one_time_keys: Vec<String>,
 ) -> Result<UserLoginInfo> {
+  debug!("Attempting to login user: {}", username);
+
   // Set up the gRPC client that will be used to talk to the Identity service
   let channel = get_identity_service_channel().await?;
   let mut identity_client = IdentityClientServiceClient::new(channel);
@@ -51,7 +54,7 @@
   let login_start_response = identity_client
     .login_password_user_start(login_start_request)
     .await
-    .map_err(|_| Error::from_status(Status::GenericFailure))?
+    .map_err(handle_grpc_error)?
     .into_inner();
 
   let opaque_login_upload = client_login
@@ -65,7 +68,7 @@
   let login_finish_response = identity_client
     .login_password_user_finish(login_finish_request)
     .await
-    .map_err(|_| Error::from_status(Status::GenericFailure))?
+    .map_err(handle_grpc_error)?
     .into_inner();
 
   let user_info = UserLoginInfo {
diff --git a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client/mod.rs
@@ -17,10 +17,20 @@
 use serde::{Deserialize, Serialize};
 use std::env::var;
 use tonic::{transport::Channel, Request};
-use tracing::instrument;
+use tracing::{self, info, instrument, warn, Level};
+use tracing_subscriber::EnvFilter;
 
 lazy_static! {
   static ref IDENTITY_SERVICE_CONFIG: IdentityServiceConfig = {
+    let filter = EnvFilter::builder()
+      .with_default_directive(Level::INFO.into())
+      .with_env_var(EnvFilter::DEFAULT_ENV)
+      .from_env_lossy();
+
+    let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish();
+    tracing::subscriber::set_global_default(subscriber)
+      .expect("Unable to configure tracing");
+
     let config_json_string =
       var("COMM_JSONCONFIG_secrets_identity_service_config");
     match config_json_string {
@@ -39,6 +49,7 @@
 
 impl Default for IdentityServiceConfig {
   fn default() -> Self {
+    info!("Using default identity configuration");
     Self {
       identity_socket_addr: "https://[::1]:50054".to_string(),
       identity_auth_token: "test".to_string(),
@@ -47,6 +58,7 @@
 }
 
 async fn get_identity_service_channel() -> Result<Channel> {
+  info!("Connecting to identity service");
   Channel::from_static(&IDENTITY_SERVICE_CONFIG.identity_socket_addr)
     .connect()
     .await
@@ -69,3 +81,8 @@
   pub user_id: String,
   pub access_token: String,
 }
+
+pub fn handle_grpc_error(error: tonic::Status) -> napi::Error {
+  warn!("Received error: {}", error.message());
+  Error::new(Status::GenericFailure, error.message())
+}
diff --git a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs
--- a/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs
+++ b/keyserver/addons/rust-node-addon/src/identity_client/register_user.rs
@@ -1,5 +1,7 @@
 use super::*;
 
+use tracing::{debug, warn};
+
 #[napi]
 #[instrument(skip_all)]
 pub async fn register_user(
@@ -13,6 +15,8 @@
   content_one_time_keys: Vec<String>,
   notif_one_time_keys: Vec<String>,
 ) -> Result<UserLoginInfo> {
+  debug!("Attempting to register user: {}", username);
+
   // Set up the gRPC client that will be used to talk to the Identity service
   let channel = get_identity_service_channel().await?;
   let mut identity_client = IdentityClientServiceClient::new(channel);
@@ -49,8 +53,9 @@
   let registration_start_response = identity_client
     .register_password_user_start(registration_start_request)
     .await
-    .map_err(|_| Error::from_status(Status::GenericFailure))?
+    .map_err(handle_grpc_error)?
     .into_inner();
+  debug!("Received registration start response");
 
   let opaque_registration_upload = opaque_registration
     .finish(
@@ -67,7 +72,7 @@
   let registration_response = identity_client
     .register_password_user_finish(registration_finish_request)
     .await
-    .map_err(|_| Error::from_status(Status::GenericFailure))?
+    .map_err(handle_grpc_error)?
     .into_inner();
 
   let user_info = UserLoginInfo {