Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tracing support for Apache HttpAsyncClient #84

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.util.concurrent._

import com.comcast.money.core.internal.{ MDCSupport, SpanLocal }
import com.comcast.money.core.logging.TraceLogging
import com.comcast.money.core.state.State
import org.slf4j.MDC

object TraceFriendlyThreadPoolExecutor {
Expand Down Expand Up @@ -64,28 +65,19 @@ class TraceFriendlyThreadPoolExecutor(corePoolSize: Int, maximumPoolSize: Int, k
setRejectedExecutionHandler(rejectedExecutionHandler)
}

override def execute(command: Runnable) = {
val inherited = SpanLocal.current
val submittingThreadsContext = MDC.getCopyOfContextMap
override def execute(command: Runnable) {
val state = State.capture()

super.execute(
new Runnable {
override def run = {
mdcSupport.propogateMDC(Option(submittingThreadsContext))
SpanLocal.clear()
inherited.foreach(SpanLocal.push)
try {
command.run()
} catch {
case t: Throwable =>
logException(t)
throw t
} finally {
SpanLocal.clear()
MDC.clear()
}
super.execute(new Runnable {
override def run(): Unit = state.restore {
try {
command.run()
} catch {
case t: Throwable =>
logException(t)
throw t
}
}
)
})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2012-2015 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.comcast.money.core.state

/** Represents the restored tracing state. */
trait RestoredState extends AutoCloseable {
/** Reverts the restored tracing state on the current thread */
override def close(): Unit
}
105 changes: 105 additions & 0 deletions money-core/src/main/scala/com/comcast/money/core/state/State.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2012-2015 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.comcast.money.core.state

import com.comcast.money.core.internal.{ MDCSupport, SpanLocal }
import org.slf4j.MDC

object State {
private lazy val mdcSupport = new MDCSupport()

/**
* Captures the state of the current tracing span so that it can be restored onto
* a separate worker thread.
*
* {{{
* import com.comcast.money.core.state
*
* def doSomethingAsynchronous(executor: ExecutorService) {
* val capturedState = State.capture()
*
* executor.submit(new Runnable {
* override def run(): Unit = state.restore {
* // resumes on captured
* }
* })
* }
* }}}
* @return the captured tracing state
*/
def capture(): State = {
val span = SpanLocal.current
val mdc = MDC.getCopyOfContextMap

new State {
override def restore(): RestoredState = {
mdcSupport.propogateMDC(Option(mdc))
SpanLocal.clear()
span.foreach(SpanLocal.push)
new RestoredState {
override def close(): Unit = {
MDC.clear()
SpanLocal.clear()
}
}
}
}
}
}

/** Represents the tracing state that has been captured from another thread */
trait State {
/**
* Restores the tracing state on the current thread returning a [[RestoredState]]
* that can be used with Java 7+ "try-with-resources" syntax to revert the
* restored state.
*
* {{{
* State state = State.capture();
* // later
* try (RestoredState restored = state.restore()) {
* // do something meaningful here
* }
* }}}
* @return the restored state
*/
def restore(): RestoredState

/**
* Restores the tracing state on the current thread for the duration of the
* function.
*
* {{{
* val state = State.capture
* // later
* state.restore {
* // do something meaningful here
* }
* }}}
* @param f the function to invoke
* @tparam T the return value of the function
* @return the value returned from the function
*/
def restore[T](f: => T): T = {
val restoredState = restore()
try {
f
} finally {
if (restoredState != null) restoredState.close()
}
}
}
24 changes: 24 additions & 0 deletions money-http-async-client/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2012-2015 Comcast Cable Communications Management, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

money {
http-client {
metric-names {
http-call-duration = "http-call-duration"
http-call-with-body-duration = "http-call-with-body-duration"
http-process-response-duration = "http-process-response-duration"
http-response-code = "http-response-code"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2012-2015 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.comcast.money.http.client

object HttpAsyncTraceConfig {
lazy val HttpResponseTimeTraceKey: String = "http-call-duration"
lazy val HttpFullResponseTimeTraceKey: String = "http-call-with-body-duration"
lazy val ProcessResponseTimeTraceKey: String = "http-process-response-duration"
lazy val HttpResponseCodeTraceKey: String = "http-response-code"
}
Loading