Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
36b830c
Add otel promise remote
schloerke Aug 4, 2025
b8a9184
WIP: Add OpenTelemetry integration for reactives
schloerke Aug 5, 2025
0faf1b7
Remove check errors
schloerke Aug 5, 2025
7b8c9c1
Merge branch 'main' into feat/otel
schloerke Aug 5, 2025
542681c
Add otel packages
schloerke Aug 5, 2025
21c1ce1
Merge branch 'main' into feat/otel
schloerke Aug 5, 2025
bf963a1
Add r-lib/otelsdk to Remotes in DESCRIPTION
schloerke Aug 5, 2025
bd6d1ab
Add Open Telemetry section to pkgdown config
schloerke Aug 5, 2025
7f38738
connect sync items. Need to prove promise calculations
schloerke Aug 5, 2025
eca760b
Update shiny-package.R
schloerke Aug 5, 2025
2ca085e
Commit current state
schloerke Aug 5, 2025
c88bef4
Merge branch 'main' into feat/otel
schloerke Aug 18, 2025
0903eee
Init otel.R
schloerke Aug 18, 2025
f004e54
Nerf all impl in bindOtel to use new otel methods
schloerke Aug 18, 2025
bb66440
Log with safe and dynamically use existing reactive locks when available
schloerke Aug 18, 2025
c584a00
Use new otel methods
schloerke Aug 18, 2025
ac14795
Disable render function observer from otel
schloerke Aug 18, 2025
8c4d9d7
Set the otel span before running calling handlers for render function
schloerke Aug 18, 2025
751ce6e
`devtools::document()` (GitHub Actions)
schloerke Aug 18, 2025
f8c2fda
Pair to the correct react lock span
schloerke Aug 18, 2025
1858220
Merge branch 'feat/otel' of https://github.com/rstudio/shiny into fea…
schloerke Aug 18, 2025
abf7b5c
Require domain be given to with exsting ospan method
schloerke Aug 18, 2025
bdbfd0b
Update bind-otel.R
schloerke Aug 18, 2025
3de7b7b
tweaks
schloerke Aug 18, 2025
1c91cd9
Wrap execute flush with context's domain for ospan activation
schloerke Aug 18, 2025
686fcf2
`devtools::document()` (GitHub Actions)
schloerke Aug 18, 2025
aacf00c
Update demo app to use promises.
schloerke Aug 18, 2025
35eeb09
Reactivate ospan promise domains in reverse order so that the most re…
schloerke Aug 18, 2025
1267d3e
Fix promise resolve to be a regular promise to get the eval in the co…
schloerke Aug 18, 2025
c3e90a2
Better debugging
schloerke Aug 18, 2025
cae54cb
Add debug message
schloerke Aug 19, 2025
0583213
Try to add a span link. Leave as comment for now
schloerke Aug 19, 2025
e181c0a
clean up codes
schloerke Aug 19, 2025
3126080
`rm` does not inherit when removing... so only check for existence wi…
schloerke Aug 19, 2025
e7c8f97
use single value within shiny for `otel is tracing` to avoid consiste…
schloerke Aug 19, 2025
3b8abd9
Update bind-otel.R
schloerke Aug 19, 2025
d924ea8
Consistent label format
schloerke Aug 20, 2025
8b4d49b
Comments
schloerke Aug 20, 2025
c202b53
Latest otel integrations. Use wrapper otel methods for consistent imp…
schloerke Aug 25, 2025
222ead0
Disable languageserver styler changes
schloerke Aug 25, 2025
f839cf5
Update otel log to not interpolate anything
schloerke Aug 25, 2025
97b9973
Use `"Reactive update"` . Need to remove "lock" from name
schloerke Aug 25, 2025
a4a9f7f
Update shiny.R
schloerke Aug 26, 2025
4910fdb
Unify otel label display within `otel-label.R`
schloerke Aug 26, 2025
7c77156
`reactive_lock` -> `reactive_update`
schloerke Aug 26, 2025
f8e87be
Bump dev version v1.11.1.9001
schloerke Aug 26, 2025
6fd9a9c
`withOtelShiny()` -> `withOtel()`
schloerke Aug 26, 2025
85809a5
Apply suggestions from code review
schloerke Aug 26, 2025
df6994b
Code feedback
schloerke Aug 26, 2025
b32ff78
Have `otel_is_tracing` allow to be dynamic
schloerke Aug 26, 2025
2f12f0f
Fix new bind otel. Add docs. Move existing ospan methods closer to impl
schloerke Aug 27, 2025
923a81a
Update docs for option
schloerke Aug 27, 2025
877f5c7
From ospan capture from within Context flush to `run()`
schloerke Aug 27, 2025
ff45870
Don't make the option for the dev app bleed out
schloerke Aug 27, 2025
653ef9f
Update stacks given new otel
schloerke Aug 27, 2025
a969167
Make stack testing more robust
schloerke Aug 27, 2025
e1c0310
Update pkgdown.yml
schloerke Aug 27, 2025
3df8447
Update bind-otel.R
schloerke Aug 28, 2025
5fa79aa
`npm run build` (GitHub Actions)
schloerke Aug 28, 2025
f308e53
Sync package version (GitHub Actions)
schloerke Aug 28, 2025
c35b254
Nerf bind options to just `"all"` and `"none"`
schloerke Aug 28, 2025
0d1037f
`reactive-update` -> `reactive_update`
schloerke Aug 28, 2025
4977e52
Merge branch 'feat/otel' of https://github.com/rstudio/shiny into fea…
schloerke Aug 29, 2025
b23fd71
Update labels and srcrefs for all otel bound objects
schloerke Aug 29, 2025
ec5e4e4
Start transition to otel session start/end event. Use `session.id` at…
schloerke Aug 29, 2025
6c8cbc2
Remove unnecessary domain parameters
schloerke Aug 29, 2025
83ab5ac
refactor(otel): split span management into focused modules
schloerke Aug 31, 2025
982aad4
Require new promises package
schloerke Sep 1, 2025
e0ba77e
refactor(otel): migrate to promises package otel functions
schloerke Sep 3, 2025
24dd639
Update reactives.R
schloerke Sep 3, 2025
3580742
Update bind-otel.R
schloerke Sep 3, 2025
07649ad
If a srcref is `NULL`, return `NULL`
schloerke Sep 3, 2025
cc56f4a
Update stacks snaps
schloerke Sep 3, 2025
7ebd19c
rerun stack traces with testthat from cran, not github
schloerke Sep 3, 2025
346bf38
Fix doc issue
schloerke Sep 3, 2025
9117f55
Remove message about using new syntax in code
schloerke Sep 3, 2025
39bdcaf
`devtools::document()` (GitHub Actions)
schloerke Sep 3, 2025
c284c2d
Merge branch 'feat/otel' of https://github.com/rstudio/shiny into fea…
schloerke Sep 3, 2025
273c4c6
Do not namespace reactive val label
schloerke Sep 3, 2025
39d6059
Allow for eventReactive to find the variable name for it's label
schloerke Sep 3, 2025
7980201
Do not auto otel within eventReactive or observeEvent methods until r…
schloerke Sep 3, 2025
17e6261
Update bind-otel.R
schloerke Sep 3, 2025
23ffe44
debug: Add OTEL config options to with_options in barret
schloerke Sep 5, 2025
2fa71cf
Similar to promises, do not have a custom tracer. Instead, capture it…
schloerke Sep 5, 2025
175c5b9
tmp: Use .Renviron instead of local options
schloerke Sep 5, 2025
6aaaf43
Wrap the implementation of `runApp()` in a ospan promise domain
schloerke Sep 5, 2025
0d44c2b
Merge branch 'main' into feat/otel
schloerke Sep 5, 2025
5e8e2ce
`devtools::document()` (GitHub Actions)
schloerke Sep 5, 2025
92584b2
Merge branch 'main' into feat/otel
schloerke Sep 5, 2025
ca46b26
Do not export `withOtel()`
schloerke Sep 9, 2025
f7bc93c
Use fast get_tracer() from httr2
schloerke Sep 9, 2025
6797cbe
Delete withOtel.Rd
schloerke Sep 9, 2025
12a8e44
Make anon label short
schloerke Sep 10, 2025
52c8033
Make the default otel level "all"; Reduce internal options
schloerke Sep 10, 2025
05bedd8
Move helper function outside of R folder into tests folder; Add encom…
schloerke Sep 10, 2025
3828152
Use new `promises::local_ospan_promise_domain()`
schloerke Sep 10, 2025
bdd7569
Clearer fatal / error log title
schloerke Sep 11, 2025
c3f414b
Update helper-barret.R
schloerke Sep 11, 2025
7f275bd
Updates from otelsdk and promises
schloerke Sep 25, 2025
c16d85b
Speed enhancement for `otel_is_tracing_enabled()`
schloerke Sep 25, 2025
bbe8166
Update `otel_log_safe()` -> `otel_log()` with cached logger
schloerke Sep 25, 2025
d7be0e7
Improve default labeling for reactiveVal and reactiveValues
schloerke Sep 26, 2025
537f034
Use flags on reactive objects, rather than wrapping and re-writing th…
schloerke Oct 6, 2025
2b0d2c8
Use safety net of tryCatch
schloerke Oct 6, 2025
745adc0
Do not export internal s3 method: bindOtel()
schloerke Oct 6, 2025
ed6b424
Use a reactiveVal instead of reactiveValues for internal calculations…
schloerke Oct 6, 2025
1f0d2c0
Better anonymous labels for otel
schloerke Oct 6, 2025
f4d6c94
Updates
schloerke Oct 6, 2025
8d8d89f
Update .Renviron
schloerke Oct 8, 2025
3933121
Fix bad subset
schloerke Oct 8, 2025
d1d60ba
FIx always false check
schloerke Oct 8, 2025
54c7fbd
Refactor Session start and session end ospans / logs
schloerke Oct 8, 2025
b632e4b
Refactor otel labels to support both event and cache
schloerke Oct 8, 2025
ac31109
Update shiny.R
schloerke Oct 8, 2025
6000499
Sanitize fatal/unhandled errors (unless disabled) before sending to O…
schloerke Oct 8, 2025
9cf0900
Better labels for debounce and throttle
schloerke Oct 8, 2025
d5d6173
Add logging for reactives that are not made the traditional way (inpu…
schloerke Oct 8, 2025
792d6f4
More otel attrs and better label for eventReactive
schloerke Oct 8, 2025
b889057
Update helper-barret.R
schloerke Oct 8, 2025
645a88f
Spelling and remove outdated pkgdown section
schloerke Oct 8, 2025
875c997
Update NEWS.md
schloerke Oct 8, 2025
da7e334
Add ExtendedTask Support
schloerke Oct 9, 2025
5bbbc39
Add extended task label functions with domain support
schloerke Oct 10, 2025
c07557b
Nerf `session.start` / `session.end` events. Move start attrs into `s…
schloerke Oct 10, 2025
54ca7c8
Update NEWS.md
schloerke Oct 10, 2025
49cc4ec
Merge branch 'main' into feat/otel
schloerke Oct 10, 2025
a854f08
Merge branch 'main' into feat/otel
schloerke Oct 10, 2025
e593061
Update NEWS.md
schloerke Oct 10, 2025
1635295
Test global variable
schloerke Oct 10, 2025
4d49a4d
Move label to be set during init
schloerke Oct 10, 2025
dc29683
Delete .Renviron
schloerke Oct 14, 2025
9aff69b
Remove bad if statement
schloerke Oct 14, 2025
921d717
Do not record ospans for debounce, throttle, and ExtendedTask interna…
schloerke Oct 14, 2025
274f19a
Use helper method when init'ing `Context`, not a consistent followup …
schloerke Oct 14, 2025
6b1aed0
Fix broken test for stack trace
schloerke Oct 14, 2025
013f409
comment temp code that makes the check unhappy
schloerke Oct 14, 2025
0fd3ef6
Expose different `shiny.bind.otel` option levels
schloerke Oct 14, 2025
3a67d66
Rename bind-otel.R to otel-bind.R
schloerke Oct 14, 2025
1ffe4a8
Add comments on why we do not use noop spans
schloerke Oct 14, 2025
537483a
Clarify shiny.otel.bind option values in documentation
schloerke Oct 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"[r]": {
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"editor.formatOnSave": false,
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
Expand Down
15 changes: 13 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: shiny
Title: Web Application Framework for R
Version: 1.11.1.9000
Version: 1.11.1.9001
Authors@R: c(
person("Winston", "Chang", , "[email protected]", role = "aut",
comment = c(ORCID = "0000-0002-1576-2126")),
Expand Down Expand Up @@ -94,7 +94,8 @@ Imports:
later (>= 1.0.0),
lifecycle (>= 0.2.0),
mime (>= 0.3),
promises (>= 1.3.2),
otel,
promises (>= 1.3.3.9006),
R6 (>= 2.0),
rlang (>= 0.4.10),
sourcetools,
Expand All @@ -114,6 +115,7 @@ Suggests:
magrittr,
markdown,
mirai,
otelsdk (>= 0.2.0),
ragg,
reactlog (>= 1.0.0),
rmarkdown,
Expand All @@ -122,6 +124,8 @@ Suggests:
testthat (>= 3.2.1),
watcher,
yaml
Remotes:
rstudio/promises
Config/Needs/check: shinytest2
Config/testthat/edition: 3
Encoding: UTF-8
Expand Down Expand Up @@ -185,6 +189,13 @@ Collate:
'modal.R'
'modules.R'
'notifications.R'
'otel-attr-srcref.R'
'otel-bind.R'
'otel-label.R'
'otel-reactive-update.R'
'otel-session.R'
'otel-with.R'
'otel.R'
'priorityqueue.R'
'progress.R'
'react.R'
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,12 @@ importFrom(promises,"%...!%")
importFrom(promises,"%...>%")
importFrom(promises,as.promise)
importFrom(promises,is.promising)
importFrom(promises,local_ospan_promise_domain)
importFrom(promises,promise)
importFrom(promises,promise_reject)
importFrom(promises,promise_resolve)
importFrom(promises,with_ospan_async)
importFrom(promises,with_ospan_promise_domain)
importFrom(rlang,"%||%")
importFrom(rlang,"fn_body<-")
importFrom(rlang,"fn_fmls<-")
Expand Down
32 changes: 31 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
# shiny (development version)

## OpenTelemetry support (#4269)

* Added support for [OpenTelemetry](https://opentelemetry.io/) via [`{otel}`](https://otel.r-lib.org/index.html). By default, if `otel::is_tracing_enabled()` returns `TRUE`, then `{shiny}` will record all OpenTelemetery spans. See [`{otelsdk}`'s Collecting Telemetry Data](https://otelsdk.r-lib.org/reference/collecting.html) for more details on configuring OpenTelemetry.

* Supported values for `options(shiny.otel.bind)` (or `Sys.getenv("SHINY_OTEL_BIND")`):
* `"none"` - No Shiny OpenTelemetry tracing.
* `"session"` - Adds session start/end spans.
* `"reactive_update"` - Spans for any synchronous/asynchronous reactive update. (Includes `"session"` features).
* `"reactivity"` - Spans for all reactive expressions. (Includes `"reactive_update"` features).
* `"all"` [default] - All Shiny OpenTelemetry tracing. Currently equivalent to `"reactivity"`.

* Spans are recorded for:
* `session_start`: Wraps the calling of the `server()` function. Also contains HTTP request within the attributes.
* `session_end`: Wraps the calling of the `onSessionEnded()` handlers.
* `reactive_update`: Signals the start of when Shiny knows something is to be calculated. This span ends when there are no more reactive updates (promises or synchronous) to be calculated.
* `reactive`, `observe`, `output`: Captures the calculation (including any async promise chains) of a reactive expression (`reactive()`), an observer (`observe()`), or an output render function (`render*()`).
* `reactive debounce`, `reactive throttle`: Captures the calculation (including any async promise chains) of a `debounce()`d or `throttle()`d reactive expression.
* `ExtendedTask`: Captures the calculation (including any async promise chains) of an `ExtendedTask`.

* OpenTelemetry Logs are recorded for:
* `Set reactiveVal <name>` - When a `reactiveVal()` is set
* `Set reactiveValues <name>$<key>` - When a `reactiveValues()` element is set
* Fatal or unhandled errors - When an error occurs that causes the session to end, or when an unhandled error occurs in a reactive context. Contains the error within the attributes. To unsantize the error message being collected, set `options(shiny.otel.sanitize.errors = FALSE)`.
* `Set ExtendedTask <name> <value>` - When an `ExtendedTask`'s respective reactive value (e.g., `status`, `value`, and `error`) is set.
* `<ExtendedTask name> add to queue` - When an `ExtendedTask` is added to the task queue.

* All logs and spans contain the `session.id` attribute.

## New features

* The `icon` argument of `updateActionButton()`/`updateActionLink()` nows allows values other than `shiny::icon()` (e.g., `fontawesome::fa()`, `bsicons::bs_icon()`, etc). (#4249)
Expand All @@ -10,9 +38,11 @@

* Fixed an issue where `updateSelectizeInput(options = list(plugins="remove_button"))` could lead to multiple remove buttons. (#4275)

* The default label for `reactiveValues()`, `reactivePoll()`, `reactiveFileReader()`, `debounce()`, and `throttle()` will now attempt to retrieve the assigned name if the srcref is available. If a value can not easily be produced, a default label will be used instead. (#4269)

## Changes

* The return value of `actionButton()`/`actionLink()` changed slightly: `label` and `icon` are wrapped in an additional HTML container element. This allows for: 1. `updateActionButton()`/`updateActionLink()` to distinguish between the `label` and `icon` when making updates and 2. spacing between `label` and `icon` to be more easily customized via CSS.
* The return value of `actionButton()`/`actionLink()` changed slightly: `label` and `icon` are wrapped in an additional HTML container element. This allows for: 1. `updateActionButton()`/`updateActionLink()` to distinguish between the `label` and `icon` when making updates and 2. spacing between `label` and `icon` to be more easily customized via CSS.

# shiny 1.11.1

Expand Down
6 changes: 3 additions & 3 deletions R/bind-cache.R
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ bindCache.default <- function(x, ...) {
bindCache.reactiveExpr <- function(x, ..., cache = "app") {
check_dots_unnamed()

label <- exprToLabel(substitute(key), "cachedReactive")
label <- exprToLabel(substitute(x), "cachedReactive")
domain <- reactive_get_domain(x)

# Convert the ... to a function that returns their evaluated values.
Expand All @@ -494,8 +494,8 @@ bindCache.reactiveExpr <- function(x, ..., cache = "app") {
rm(x)
# Hacky workaround for issue with `%>%` preventing GC:
# https://github.com/tidyverse/magrittr/issues/229
if (exists(".GenericCallEnv") && exists(".", envir = .GenericCallEnv)) {
rm(list = ".", envir = .GenericCallEnv)
if (exists(".GenericCallEnv") && exists(".", envir = .GenericCallEnv, inherits = FALSE)) {
rm(list = ".", envir = .GenericCallEnv, inherits = FALSE)
}


Expand Down
40 changes: 27 additions & 13 deletions R/bind-event.R
Original file line number Diff line number Diff line change
Expand Up @@ -199,28 +199,39 @@ bindEvent.reactiveExpr <- function(x, ..., ignoreNULL = TRUE, ignoreInit = FALSE
label <- label %||%
sprintf('bindEvent(%s, %s)', attr(x, "observable", exact = TRUE)$.label, quos_to_label(qs))

x_classes <- class(x)

# Don't hold on to the reference for x, so that it can be GC'd
rm(x)

initialized <- FALSE

res <- reactive(label = label, domain = domain, ..stacktraceon = FALSE, {
hybrid_chain(
eventFunc(),
function(value) {
if (ignoreInit && !initialized) {
initialized <<- TRUE
req(FALSE)
}
with_no_otel_bind({
res <- reactive(label = label, domain = domain, ..stacktraceon = FALSE, {
hybrid_chain(
{
eventFunc()
},
function(value) {
if (ignoreInit && !initialized) {
initialized <<- TRUE
req(FALSE)
}

req(!ignoreNULL || !isNullEvent(value))
req(!ignoreNULL || !isNullEvent(value))

isolate(valueFunc())
}
)
isolate(valueFunc())
}
)
})
})

class(res) <- c("reactive.event", class(res))
class(res) <- c("reactive.event", x_classes)

if (has_otel_bind("reactivity")) {
res <- bind_otel_reactive_expr(res)
}

res
}

Expand Down Expand Up @@ -302,6 +313,9 @@ bindEvent.Observer <- function(x, ..., ignoreNULL = TRUE, ignoreInit = FALSE,
)

class(x) <- c("Observer.event", class(x))
if (has_otel_bind("reactivity")) {
x <- bind_otel_observe(x)
}
invisible(x)
}

Expand Down
5 changes: 3 additions & 2 deletions R/conditions.R
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,9 @@ dropTrivialTestFrames <- function(callnames) {
"testthat::test_local"
)

firstGoodCall <- min(which(!hideable))
toRemove <- firstGoodCall - 1L
# Remove everything from inception to calling the test
# It shouldn't matter how you get there, just that you're finally testing
toRemove <- max(which(hideable))

c(
rep_len(FALSE, toRemove),
Expand Down
69 changes: 65 additions & 4 deletions R/extended-task.R
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,41 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
#' read reactive inputs and pass them as arguments.
initialize = function(func) {
private$func <- func
private$rv_status <- reactiveVal("initial")
private$rv_value <- reactiveVal(NULL)
private$rv_error <- reactiveVal(NULL)

# Do not show these private reactive values in otel spans
with_no_otel_bind({
private$rv_status <- reactiveVal("initial")
private$rv_value <- reactiveVal(NULL)
private$rv_error <- reactiveVal(NULL)
})

private$invocation_queue <- fastmap::fastqueue()

domain <- getDefaultReactiveDomain()

# Set a label for the reactive values for easier debugging
# Go up an extra sys.call() to get the user's call to ExtendedTask$new()
# The first sys.call() is to `initialize(...)`
call_srcref <- attr(sys.call(-1), "srcref", exact = TRUE)
label <- rassignSrcrefToLabel(
call_srcref,
defaultLabel = "<anonymous>",
fnName = "ExtendedTask\\$new"
)
private$otel_label <- otel_label_extended_task(label, domain = domain)
private$otel_label_add_to_queue <- otel_label_extended_task_add_to_queue(label, domain = domain)

set_rv_label <- function(rv, suffix) {
impl <- attr(rv, ".impl", exact = TRUE)
impl$.otelLabel <- otel_label_extended_task_set_reactive_val(
label,
suffix,
domain = domain
)
}
set_rv_label(private$rv_status, "status")
set_rv_label(private$rv_value, "value")
set_rv_label(private$rv_error, "error")
},
#' @description
#' Starts executing the long-running operation. If this `ExtendedTask` is
Expand All @@ -139,8 +170,27 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
isolate(private$rv_status()) == "running" ||
private$invocation_queue$size() > 0
) {
otel_log(
private$otel_label_add_to_queue,
severity = "debug",
attributes = c(
otel_session_id_attrs(getDefaultReactiveDomain()),
list(
queue_size = private$invocation_queue$size() + 1L
)
)
)
private$invocation_queue$add(list(args = args, call = call))
} else {

if (has_otel_bind("reactivity")) {
private$ospan <- create_shiny_ospan(
private$otel_label,
attributes = otel_session_id_attrs(getDefaultReactiveDomain())
)
otel::local_active_span(private$ospan)
}

private$do_invoke(args, call = call)
}
invisible(NULL)
Expand Down Expand Up @@ -188,7 +238,7 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
#' invalidation will be ignored.
result = function() {
switch (private$rv_status(),
running = req(FALSE, cancelOutput="progress"),
running = req(FALSE, cancelOutput = "progress"),
success = if (private$rv_value()$visible) {
private$rv_value()$value
} else {
Expand All @@ -207,6 +257,9 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
rv_value = NULL,
rv_error = NULL,
invocation_queue = NULL,
otel_label = NULL,
otel_label_add_to_queue = NULL,
ospan = NULL,

do_invoke = function(args, call = NULL) {
private$rv_status("running")
Expand All @@ -220,9 +273,17 @@ ExtendedTask <- R6Class("ExtendedTask", portable = TRUE, cloneable = FALSE,
p <- promises::then(
p,
onFulfilled = function(value, .visible) {
if (is_ospan(private$ospan)) {
private$ospan$end(status_code = "ok")
private$ospan <- NULL
}
private$on_success(list(value = value, visible = .visible))
},
onRejected = function(error) {
if (is_ospan(private$ospan)) {
private$ospan$end(status_code = "error")
private$ospan <- NULL
}
private$on_error(error, call = call)
}
)
Expand Down
4 changes: 4 additions & 0 deletions R/globals.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ on_load_exprs <- list()
on_load <- function(expr) {
on_load_exprs[[length(on_load_exprs) + 1]] <<- substitute(expr)
}

on_load({
IS_SHINY_LOCAL_PKG <- exists(".__DEVTOOLS__")
})
24 changes: 24 additions & 0 deletions R/otel-attr-srcref.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@


# Very similar to srcrefFromShinyCall(),
# however, this works when the function does not have a srcref attr set
otel_srcref_attributes <- function(srcref) {
if (is.function(srcref)) {
srcref <- getSrcRefs(srcref)[[1]][[1]]
}

if (is.null(srcref)) {
return(NULL)
}

stopifnot(inherits(srcref, "srcref"))

# Semantic conventions for code: https://opentelemetry.io/docs/specs/semconv/registry/attributes/code/
#
# Inspiration from https://github.com/r-lib/testthat/pull/2087/files#diff-92de3306849d93d6f7e76c5aaa1b0c037e2d716f72848f8a1c70536e0c8a1564R123-R124
dropNulls(list(
"code.filepath" = attr(srcref, "srcfile")$filename,
"code.lineno" = srcref[1],
"code.column" = srcref[2]
))
}
Loading
Loading