diff --git a/R/otel.R b/R/otel.R index 07ad50b77a..7da84ef39f 100644 --- a/R/otel.R +++ b/R/otel.R @@ -1,51 +1,50 @@ otel_tracer_name = 'org.yihui.knitr' -otel_tracer = NULL -otel_is_tracing = FALSE # generic otel helpers: -# - without specifying `scope`, the span ends when this function returns; -# to make this a local span (last as long as the function it is called from), -# specify `scope = environment()` -# - arguments remain unevaluated on early return -otel_active_span = function( - name, - label, - attributes = list(), - scope = environment() -) { - otel_is_tracing || return() - otel::start_local_active_span( - name = sprintf('%s %s', name, label), - attributes = otel::as_attributes(attributes), - tracer = otel_tracer, - activation_scope = scope - ) -} +otel_cache_tracer = NULL +otel_active_span = NULL -otel_cache_tracer = function() { - requireNamespace('otel', quietly = TRUE) || return() - otel_tracer <<- otel::get_tracer(otel_tracer_name) - otel_is_tracing <<- tracer_enabled(otel_tracer) -} +local({ + otel_tracer = NULL + otel_is_tracing = FALSE + + otel_cache_tracer <<- function() { + requireNamespace('otel', quietly = TRUE) || return() + otel_tracer <<- otel::get_tracer(otel_tracer_name) + otel_is_tracing <<- tracer_enabled(otel_tracer) + } + + # - without specifying `scope`, the span ends when this function returns; + # to make this a local span (last as long as the function it is called from), + # specify `scope = environment()` + # - arguments remain unevaluated on early return + otel_active_span <<- function( + name, + label, + attributes = list(), + scope = environment() + ) { + otel_is_tracing || return() + otel::start_local_active_span( + name = sprintf('%s %s', name, label), + attributes = otel::as_attributes(attributes), + tracer = otel_tracer, + activation_scope = scope + ) + } +}) tracer_enabled = function(tracer) { .subset2(tracer, 'is_enabled')() } -otel_refresh_tracer = function(pkgname) { - requireNamespace('otel', quietly = TRUE) || return() - tracer = otel::get_tracer() - modify_binding( - getNamespace(pkgname), - list(otel_tracer = tracer, otel_is_tracing = tracer_enabled(tracer)) - ) -} - -modify_binding = function(env, lst) { - lapply(names(lst), unlockBinding, env) - list2env(lst, envir = env) - lapply(names(lst), lockBinding, env) +with_otel_record = function(expr) { + on.exit(otel_cache_tracer()) + otelsdk::with_otel_record({ + otel_cache_tracer() + expr + }) } # knitr-specific helpers: diff --git a/tests/testit/test-otel.R b/tests/testit/test-otel.R index cc89a2cf3c..54cb1d4cce 100644 --- a/tests/testit/test-otel.R +++ b/tests/testit/test-otel.R @@ -2,10 +2,7 @@ library(testit) if (requireNamespace('otelsdk', quietly = TRUE)) { - record = otelsdk::with_otel_record({ - # refresh tracer within the `with_otel_record()` scope - otel_refresh_tracer('knitr') - + record = with_otel_record({ knit( text = c('<>=', '1', '1+', '1', '1', '@'), quiet = TRUE @@ -32,9 +29,7 @@ if (requireNamespace('otelsdk', quietly = TRUE)) { (traces[[3L]]$attributes$knitr.output %==% '') }) - record = otelsdk::with_otel_record({ - otel_refresh_tracer('knitr') - + record = with_otel_record({ local({ env = new.env() env$y = 1:3 @@ -64,7 +59,4 @@ if (requireNamespace('otelsdk', quietly = TRUE)) { (traces[[3L]]$attributes$knitr.output %==% 'knit-envir.md') }) - # reset tracer after tests - otel_refresh_tracer('knitr') - }