diff --git a/CHANGES b/CHANGES
index 4a55a06ff2c3c5b17d307bce95824e08a345bb28..348927b1d89c77edddfa40e8c662e1bbad7cb729 100644
--- a/CHANGES
+++ b/CHANGES
@@ -36,10 +36,19 @@ Dialplan Functions
 
 res_pjsip_outbound_registration
 -------------------------------
-* A new 'fatal_retry_interval' option has been added to outbound registration.
-  When set (default is zero), and upon receiving a failure response to an
-  outbound registration, registration is retried at the given interval up to
-  'max_retries'.
+ * A new 'fatal_retry_interval' option has been added to outbound registration.
+   When set (default is zero), and upon receiving a failure response to an
+   outbound registration, registration is retried at the given interval up to
+   'max_retries'.
+
+ * If res_statsd is loaded and a StatsD server is configured, basic statistics
+   regarding the state of outbound registrations will now be emitted. This
+   includes:
+   - A GUAGE statistic for the overall number of outbound registrations, i.e.:
+       PJSIP.registrations.count
+   - A GUAGE statistic for the overall number of outbound registrations in a
+     particular state, e.g.:
+       PJSIP.registrations.state.Registered
 
 res_pjsip
 ------------------
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 9795a5971a053f4c1188d65893d7340206b3d6a1..6f3155d8b7c0ebee67dbb1ae4f866f20b5ac8682 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -35,6 +35,7 @@
 #include "asterisk/stasis_system.h"
 #include "asterisk/threadstorage.h"
 #include "asterisk/threadpool.h"
+#include "asterisk/statsd.h"
 #include "res_pjsip/include/res_pjsip_private.h"
 
 /*** DOCUMENTATION
@@ -612,6 +613,19 @@ static void schedule_registration(struct sip_outbound_registration_client_state
 	}
 }
 
+static void update_client_state_status(struct sip_outbound_registration_client_state *client_state, enum sip_outbound_registration_status status)
+{
+	if (client_state->status == status) {
+		return;
+	}
+
+	ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GUAGE, "-1", 1.0,
+		sip_outbound_registration_status_str(client_state->status));
+	ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GUAGE, "+1", 1.0,
+		sip_outbound_registration_status_str(status));
+	client_state->status = status;
+}
+
 /*! \brief Callback function for unregistering (potentially) and destroying state */
 static int handle_client_state_destruction(void *data)
 {
@@ -645,7 +659,7 @@ static int handle_client_state_destruction(void *data)
 				(int) info.server_uri.slen, info.server_uri.ptr,
 				(int) info.client_uri.slen, info.client_uri.ptr);
 
-			client_state->status = SIP_REGISTRATION_STOPPING;
+			update_client_state_status(client_state, SIP_REGISTRATION_STOPPING);
 			client_state->destroy = 1;
 			if (pjsip_regc_unregister(client_state->client, &tdata) == PJ_SUCCESS
 				&& registration_client_send(client_state, tdata) == PJ_SUCCESS) {
@@ -664,7 +678,7 @@ static int handle_client_state_destruction(void *data)
 		client_state->client = NULL;
 	}
 
-	client_state->status = SIP_REGISTRATION_STOPPED;
+	update_client_state_status(client_state, SIP_REGISTRATION_STOPPED);
 	ast_sip_auth_vector_destroy(&client_state->outbound_auths);
 	ao2_ref(client_state, -1);
 
@@ -726,7 +740,7 @@ static int sip_outbound_registration_is_temporal(unsigned int code,
 static void schedule_retry(struct registration_response *response, unsigned int interval,
 			   const char *server_uri, const char *client_uri)
 {
-	response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
+	update_client_state_status(response->client_state, SIP_REGISTRATION_REJECTED_TEMPORARY);
 	schedule_registration(response->client_state, interval);
 
 	if (response->rdata) {
@@ -800,7 +814,7 @@ static int handle_registration_response(void *data)
 
 			/* If the registration went fine simply reschedule registration for the future */
 			ast_debug(1, "Outbound registration to '%s' with client '%s' successful\n", server_uri, client_uri);
-			response->client_state->status = SIP_REGISTRATION_REGISTERED;
+			update_client_state_status(response->client_state, SIP_REGISTRATION_REGISTERED);
 			response->client_state->retries = 0;
 			next_registration_round = response->expiration - REREGISTER_BUFFER_TIME;
 			if (next_registration_round < 0) {
@@ -810,7 +824,7 @@ static int handle_registration_response(void *data)
 			schedule_registration(response->client_state, next_registration_round);
 		} else {
 			ast_debug(1, "Outbound unregistration to '%s' with client '%s' successful\n", server_uri, client_uri);
-			response->client_state->status = SIP_REGISTRATION_UNREGISTERED;
+			update_client_state_status(response->client_state, SIP_REGISTRATION_UNREGISTERED);
 		}
 	} else if (response->client_state->destroy) {
 		/* We need to deal with the pending destruction instead. */
@@ -821,7 +835,7 @@ static int handle_registration_response(void *data)
 		&& sip_outbound_registration_is_temporal(response->code, response->client_state)) {
 		if (response->client_state->retries == response->client_state->max_retries) {
 			/* If we received enough temporal responses to exceed our maximum give up permanently */
-			response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
+			update_client_state_status(response->client_state, SIP_REGISTRATION_REJECTED_PERMANENT);
 			ast_log(LOG_WARNING, "Maximum retries reached when attempting outbound registration to '%s' with client '%s', stopping registration attempt\n",
 				server_uri, client_uri);
 		} else {
@@ -834,7 +848,7 @@ static int handle_registration_response(void *data)
 			&& response->client_state->forbidden_retry_interval
 			&& response->client_state->retries < response->client_state->max_retries) {
 			/* A forbidden response retry interval is configured and there are retries remaining */
-			response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
+			update_client_state_status(response->client_state, SIP_REGISTRATION_REJECTED_TEMPORARY);
 			response->client_state->retries++;
 			schedule_registration(response->client_state, response->client_state->forbidden_retry_interval);
 			ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
@@ -842,14 +856,14 @@ static int handle_registration_response(void *data)
 		} else if (response->client_state->fatal_retry_interval
 			   && response->client_state->retries < response->client_state->max_retries) {
 			/* Some kind of fatal failure response received, so retry according to configured interval */
-			response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY;
+			update_client_state_status(response->client_state, SIP_REGISTRATION_REJECTED_TEMPORARY);
 			response->client_state->retries++;
 			schedule_registration(response->client_state, response->client_state->fatal_retry_interval);
 			ast_log(LOG_WARNING, "'%d' fatal response received from '%s' on registration attempt to '%s', retrying in '%u' seconds\n",
 				response->code, server_uri, client_uri, response->client_state->fatal_retry_interval);
 		} else {
 			/* Finally if there's no hope of registering give up */
-			response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT;
+			update_client_state_status(response->client_state, SIP_REGISTRATION_REJECTED_PERMANENT);
 			if (response->rdata) {
 				ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n",
 					response->code, server_uri, client_uri);
@@ -934,7 +948,6 @@ static void sip_outbound_registration_state_destroy(void *obj)
 
 	ast_debug(3, "Destroying registration state for registration to server '%s' from client '%s'\n",
 			state->registration->server_uri, state->registration->client_uri);
-
 	ao2_cleanup(state->registration);
 
 	if (!state->client_state) {
@@ -953,6 +966,10 @@ static void sip_outbound_registration_client_state_destroy(void *obj)
 {
 	struct sip_outbound_registration_client_state *client_state = obj;
 
+	ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GUAGE, "-1", 1.0);
+	ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GUAGE, "-1", 1.0,
+		sip_outbound_registration_status_str(client_state->status));
+
 	ast_taskprocessor_unreference(client_state->serializer);
 }
 
@@ -981,6 +998,10 @@ static struct sip_outbound_registration_state *sip_outbound_registration_state_a
 	state->client_state->timer.user_data = state->client_state;
 	state->client_state->timer.cb = sip_outbound_registration_timer_cb;
 
+	ast_statsd_log_string("PJSIP.registrations.count", AST_STATSD_GUAGE, "+1", 1.0);
+	ast_statsd_log_string_va("PJSIP.registrations.state.%s", AST_STATSD_GUAGE, "+1", 1.0,
+		sip_outbound_registration_status_str(state->client_state->status));
+
 	state->registration = ao2_bump(registration);
 	return state;
 }
@@ -2013,6 +2034,12 @@ static int load_module(void)
 	ast_manager_register_xml("PJSIPRegister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_register);
 	ast_manager_register_xml("PJSIPShowRegistrationsOutbound", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_show_outbound_registrations);
 
+	/* Clear any previous statsd gauges in case we weren't shutdown cleanly */
+	ast_statsd_log("PJSIP.registrations.count", AST_STATSD_GUAGE, 0);
+	ast_statsd_log("PJSIP.registrations.state.Registered", AST_STATSD_GUAGE, 0);
+	ast_statsd_log("PJSIP.registrations.state.Unregistered", AST_STATSD_GUAGE, 0);
+	ast_statsd_log("PJSIP.registrations.state.Rejected", AST_STATSD_GUAGE, 0);
+
 	/* Load configuration objects */
 	ast_sorcery_load_object(ast_sip_get_sorcery(), "registration");