diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 1a62df5698fbb04a2d5ec209f10a0741f74409e4..7bb3cdf915706c800adf962c1cf4372532c8469f 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -56,6 +56,7 @@ class AsyncGenericService;
 class RpcService;
 class RpcServiceMethod;
 class ServerAsyncStreamingInterface;
+class ServerContext;
 class ThreadPoolInterface;
 
 /// Models a gRPC server.
@@ -84,6 +85,23 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook {
   /// call \a Shutdown for this function to ever return.
   void Wait();
 
+  /// Global Callbacks
+  ///
+  /// Can be set exactly once per application to install hooks whenever
+  /// a server event occurs
+  class GlobalCallbacks {
+   public:
+    virtual ~GlobalCallbacks() {}
+    /// Called before application callback for each synchronous server request
+    virtual void PreSynchronousRequest(ServerContext* context) = 0;
+    /// Called after application callback for each synchronous server request
+    virtual void PostSynchronousRequest(ServerContext* context) = 0;
+  };
+  /// Set the global callback object. Can only be called once. Does not take
+  /// ownership of callbacks, and expects the pointed to object to be alive
+  /// until all server objects in the process have been destroyed.
+  static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
  private:
   friend class AsyncGenericService;
   friend class AsynchronousService;
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index 695e8116548742fb5e2b4ca77ae89aa028259ba7..377c1ed167ea20974769db84215fa8cec5fecd8d 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -51,6 +51,22 @@
 
 namespace grpc {
 
+class DefaultGlobalCallbacks GRPC_FINAL : public Server::GlobalCallbacks {
+ public:
+  void PreSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
+  void PostSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
+};
+
+static Server::GlobalCallbacks* g_callbacks = nullptr;
+static gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
+
+static void InitGlobalCallbacks() {
+  if (g_callbacks == nullptr) {
+    static DefaultGlobalCallbacks default_global_callbacks;
+    g_callbacks = &default_global_callbacks;
+  }
+}
+
 class Server::UnimplementedAsyncRequestContext {
  protected:
   UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {}
@@ -220,8 +236,10 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
 
     void Run() {
       ctx_.BeginCompletionOp(&call_);
+      g_callbacks->PreSynchronousRequest(&ctx_);
       method_->handler()->RunHandler(MethodHandler::HandlerParameter(
           &call_, &ctx_, request_payload_, call_.max_message_size()));
+      g_callbacks->PostSynchronousRequest(&ctx_);
       request_payload_ = nullptr;
       void* ignored_tag;
       bool ignored_ok;
@@ -283,6 +301,7 @@ Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
       server_(CreateServer(max_message_size, compression_options)),
       thread_pool_(thread_pool),
       thread_pool_owned_(thread_pool_owned) {
+  gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
   grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
 }
 
@@ -304,6 +323,12 @@ Server::~Server() {
   delete sync_methods_;
 }
 
+void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
+  GPR_ASSERT(g_callbacks == nullptr);
+  GPR_ASSERT(callbacks != nullptr);
+  g_callbacks = callbacks;
+}
+
 bool Server::RegisterService(const grpc::string* host, RpcService* service) {
   for (int i = 0; i < service->GetMethodCount(); ++i) {
     RpcServiceMethod* method = service->GetMethod(i);