-
Notifications
You must be signed in to change notification settings - Fork 1.9k
feat: Add {otel}
support
#4269
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
Draft
schloerke
wants to merge
127
commits into
main
Choose a base branch
from
feat/otel
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
feat: Add {otel}
support
#4269
Changes from all commits
Commits
Show all changes
127 commits
Select commit
Hold shift + click to select a range
36b830c
Add otel promise remote
schloerke b8a9184
WIP: Add OpenTelemetry integration for reactives
schloerke 0faf1b7
Remove check errors
schloerke 7b8c9c1
Merge branch 'main' into feat/otel
schloerke 542681c
Add otel packages
schloerke 21c1ce1
Merge branch 'main' into feat/otel
schloerke bf963a1
Add r-lib/otelsdk to Remotes in DESCRIPTION
schloerke bd6d1ab
Add Open Telemetry section to pkgdown config
schloerke 7f38738
connect sync items. Need to prove promise calculations
schloerke eca760b
Update shiny-package.R
schloerke 2ca085e
Commit current state
schloerke c88bef4
Merge branch 'main' into feat/otel
schloerke 0903eee
Init otel.R
schloerke f004e54
Nerf all impl in bindOtel to use new otel methods
schloerke bb66440
Log with safe and dynamically use existing reactive locks when available
schloerke c584a00
Use new otel methods
schloerke ac14795
Disable render function observer from otel
schloerke 8c4d9d7
Set the otel span before running calling handlers for render function
schloerke 751ce6e
`devtools::document()` (GitHub Actions)
schloerke f8c2fda
Pair to the correct react lock span
schloerke 1858220
Merge branch 'feat/otel' of https://github.com/rstudio/shiny into fea…
schloerke abf7b5c
Require domain be given to with exsting ospan method
schloerke bdbfd0b
Update bind-otel.R
schloerke 3de7b7b
tweaks
schloerke 1c91cd9
Wrap execute flush with context's domain for ospan activation
schloerke 686fcf2
`devtools::document()` (GitHub Actions)
schloerke aacf00c
Update demo app to use promises.
schloerke 35eeb09
Reactivate ospan promise domains in reverse order so that the most re…
schloerke 1267d3e
Fix promise resolve to be a regular promise to get the eval in the co…
schloerke c3e90a2
Better debugging
schloerke cae54cb
Add debug message
schloerke 0583213
Try to add a span link. Leave as comment for now
schloerke e181c0a
clean up codes
schloerke 3126080
`rm` does not inherit when removing... so only check for existence wi…
schloerke e7c8f97
use single value within shiny for `otel is tracing` to avoid consiste…
schloerke 3b8abd9
Update bind-otel.R
schloerke d924ea8
Consistent label format
schloerke 8b4d49b
Comments
schloerke c202b53
Latest otel integrations. Use wrapper otel methods for consistent imp…
schloerke 222ead0
Disable languageserver styler changes
schloerke f839cf5
Update otel log to not interpolate anything
schloerke 97b9973
Use `"Reactive update"` . Need to remove "lock" from name
schloerke a4a9f7f
Update shiny.R
schloerke 4910fdb
Unify otel label display within `otel-label.R`
schloerke 7c77156
`reactive_lock` -> `reactive_update`
schloerke f8e87be
Bump dev version v1.11.1.9001
schloerke 6fd9a9c
`withOtelShiny()` -> `withOtel()`
schloerke 85809a5
Apply suggestions from code review
schloerke df6994b
Code feedback
schloerke b32ff78
Have `otel_is_tracing` allow to be dynamic
schloerke 2f12f0f
Fix new bind otel. Add docs. Move existing ospan methods closer to impl
schloerke 923a81a
Update docs for option
schloerke 877f5c7
From ospan capture from within Context flush to `run()`
schloerke ff45870
Don't make the option for the dev app bleed out
schloerke 653ef9f
Update stacks given new otel
schloerke a969167
Make stack testing more robust
schloerke e1c0310
Update pkgdown.yml
schloerke 3df8447
Update bind-otel.R
schloerke 5fa79aa
`npm run build` (GitHub Actions)
schloerke f308e53
Sync package version (GitHub Actions)
schloerke c35b254
Nerf bind options to just `"all"` and `"none"`
schloerke 0d1037f
`reactive-update` -> `reactive_update`
schloerke 4977e52
Merge branch 'feat/otel' of https://github.com/rstudio/shiny into fea…
schloerke b23fd71
Update labels and srcrefs for all otel bound objects
schloerke ec5e4e4
Start transition to otel session start/end event. Use `session.id` at…
schloerke 6c8cbc2
Remove unnecessary domain parameters
schloerke 83ab5ac
refactor(otel): split span management into focused modules
schloerke 982aad4
Require new promises package
schloerke e0ba77e
refactor(otel): migrate to promises package otel functions
schloerke 24dd639
Update reactives.R
schloerke 3580742
Update bind-otel.R
schloerke 07649ad
If a srcref is `NULL`, return `NULL`
schloerke cc56f4a
Update stacks snaps
schloerke 7ebd19c
rerun stack traces with testthat from cran, not github
schloerke 346bf38
Fix doc issue
schloerke 9117f55
Remove message about using new syntax in code
schloerke 39bdcaf
`devtools::document()` (GitHub Actions)
schloerke c284c2d
Merge branch 'feat/otel' of https://github.com/rstudio/shiny into fea…
schloerke 273c4c6
Do not namespace reactive val label
schloerke 39d6059
Allow for eventReactive to find the variable name for it's label
schloerke 7980201
Do not auto otel within eventReactive or observeEvent methods until r…
schloerke 17e6261
Update bind-otel.R
schloerke 23ffe44
debug: Add OTEL config options to with_options in barret
schloerke 2fa71cf
Similar to promises, do not have a custom tracer. Instead, capture it…
schloerke 175c5b9
tmp: Use .Renviron instead of local options
schloerke 6aaaf43
Wrap the implementation of `runApp()` in a ospan promise domain
schloerke 0d44c2b
Merge branch 'main' into feat/otel
schloerke 5e8e2ce
`devtools::document()` (GitHub Actions)
schloerke 92584b2
Merge branch 'main' into feat/otel
schloerke ca46b26
Do not export `withOtel()`
schloerke f7bc93c
Use fast get_tracer() from httr2
schloerke 6797cbe
Delete withOtel.Rd
schloerke 12a8e44
Make anon label short
schloerke 52c8033
Make the default otel level "all"; Reduce internal options
schloerke 05bedd8
Move helper function outside of R folder into tests folder; Add encom…
schloerke 3828152
Use new `promises::local_ospan_promise_domain()`
schloerke bdd7569
Clearer fatal / error log title
schloerke c3f414b
Update helper-barret.R
schloerke 7f275bd
Updates from otelsdk and promises
schloerke c16d85b
Speed enhancement for `otel_is_tracing_enabled()`
schloerke bbe8166
Update `otel_log_safe()` -> `otel_log()` with cached logger
schloerke d7be0e7
Improve default labeling for reactiveVal and reactiveValues
schloerke 537f034
Use flags on reactive objects, rather than wrapping and re-writing th…
schloerke 2b0d2c8
Use safety net of tryCatch
schloerke 745adc0
Do not export internal s3 method: bindOtel()
schloerke ed6b424
Use a reactiveVal instead of reactiveValues for internal calculations…
schloerke 1f0d2c0
Better anonymous labels for otel
schloerke f4d6c94
Updates
schloerke 8d8d89f
Update .Renviron
schloerke 3933121
Fix bad subset
schloerke d1d60ba
FIx always false check
schloerke 54c7fbd
Refactor Session start and session end ospans / logs
schloerke b632e4b
Refactor otel labels to support both event and cache
schloerke ac31109
Update shiny.R
schloerke 6000499
Sanitize fatal/unhandled errors (unless disabled) before sending to O…
schloerke 9cf0900
Better labels for debounce and throttle
schloerke d5d6173
Add logging for reactives that are not made the traditional way (inpu…
schloerke 792d6f4
More otel attrs and better label for eventReactive
schloerke b889057
Update helper-barret.R
schloerke 645a88f
Spelling and remove outdated pkgdown section
schloerke 875c997
Update NEWS.md
schloerke da7e334
Add ExtendedTask Support
schloerke 5bbbc39
Add extended task label functions with domain support
schloerke c07557b
Nerf `session.start` / `session.end` events. Move start attrs into `s…
schloerke 54ca7c8
Update NEWS.md
schloerke 49cc4ec
Merge branch 'main' into feat/otel
schloerke a854f08
Merge branch 'main' into feat/otel
schloerke File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
OTEL_TRACES_EXPORTER=${LOGFIRE_OTEL_TRACES_EXPORTER} | ||
OTEL_EXPORTER_OTLP_ENDPOINT=${LOGFIRE_OTEL_EXPORTER_OTLP_ENDPOINT} | ||
OTEL_EXPORTER_OTLP_HEADERS=${LOGFIRE_OTEL_EXPORTER_OTLP_HEADERS} | ||
OTEL_LOGS_EXPORTER=${LOGFIRE_OTEL_LOGS_EXPORTER} | ||
OTEL_LOG_LEVEL=${LOGFIRE_OTEL_LOG_LEVEL} | ||
OTEL_METRICS_EXPORTER=${LOGFIRE_OTEL_METRICS_EXPORTER} | ||
OTEL_ENV=dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")), | ||
|
@@ -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, | ||
|
@@ -114,6 +115,7 @@ Suggests: | |
magrittr, | ||
markdown, | ||
mirai, | ||
otelsdk (>= 0.2.0), | ||
ragg, | ||
reactlog (>= 1.0.0), | ||
rmarkdown, | ||
|
@@ -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 | ||
|
@@ -133,6 +137,7 @@ Collate: | |
'app_template.R' | ||
'bind-cache.R' | ||
'bind-event.R' | ||
'bind-otel.R' | ||
'bookmark-state-local.R' | ||
'bookmark-state.R' | ||
'bootstrap-deprecated.R' | ||
|
@@ -185,6 +190,12 @@ Collate: | |
'modal.R' | ||
'modules.R' | ||
'notifications.R' | ||
'otel-attr-srcref.R' | ||
'otel-label.R' | ||
'otel-reactive-update.R' | ||
'otel-session.R' | ||
'otel-with.R' | ||
'otel.R' | ||
'priorityqueue.R' | ||
'progress.R' | ||
'react.R' | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,25 @@ | ||
# shiny (development version) | ||
|
||
## OpenTelemetry support (#4269) | ||
|
||
* Added support for [OpenTelemetry](https://opentelemetry.io/) tracing 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. To disable adjust the default `{shiny}` behavior, set the option `shiny.otel.bind` to `"none"` (or environment variable to `SHINY_OTEL_BIND=none`). See [`{otelsdk}`'s Collecting Telemetry Data](https://otelsdk.r-lib.org/reference/collecting.html) for more details on configuring OpenTelemetry. | ||
|
||
* 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*()`). | ||
* `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) | ||
|
@@ -10,9 +30,11 @@ | |
|
||
* Fixed an issue where `updateSelectizeInput(options = list(plugins="remove_button"))` could lead to multiple remove buttons. (#4275) | ||
|
||
* The default label for `reactiveValues()` will not attempt to retrieve the assigned name if the srcref is available. If a value can not easily be produced, the default label (`reactiveValuesXXXX`) will be used instead. (#4269) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for reactivePoll, debounce, throttle |
||
|
||
## 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 | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
# - OpenTelemetry ----------------------------------- | ||
# * Integration locations: | ||
# * √ Server: | ||
# * Start reactive_update when reactive busy count > 0 | ||
# * End reactive_update when reactive busy count == 0 | ||
# * √ Reactives: val, values, expr, render fn, observe | ||
# * Combinations: | ||
# * √ debounce() / throttle() | ||
# * bindCache() | ||
# * √ bindEvent() | ||
# * X - bindProgress() | ||
# * Special functions: | ||
# * ExtendedTask() | ||
# * Extended task links to submission reactive | ||
# * Reactive update that gets result links to the extended task | ||
# * √ observeEvent() | ||
# * √ eventReactive() | ||
# * TODO: Not recording updates within the span!! | ||
# * Maybe enhance all `withReactiveDomain()` calls? | ||
# * Global options: | ||
# * √ shiny.otel.bind: | ||
# * "all", "none" - all or nothing | ||
# * Current non-public options: | ||
# * "session" - Adds session start/end events | ||
# * "reactive_update" - Spans for any reactive update. (Includes `"session"` features). | ||
# * "reactivity" - Spans for all reactive things. (Includes `"reactive_update"` features). | ||
# * Private methods: | ||
# * bind_otel_*() - Methods that binds the reactive object to OpenTelemetry spans | ||
# * Note: When adding otel to an object, prepend a class of `FOO.otel`. Then add a dispatch method for `bindOtel.FOO.otel()` that declares the object already has been bound. | ||
# * without_otel_bind(expr) - Will not bind any reactives created within `expr` to OpenTelemetry spans. | ||
|
||
# - TODO: ----------------------------------- | ||
# * Span status for success/failure (render function and regular reactive exprs?) | ||
# * Error handling is not an "exception" for fatal logs | ||
# * Connect `user.id` to be their user name: https://opentelemetry.io/docs/specs/semconv/registry/attributes/user/ | ||
# * Tests with otel recording | ||
|
||
|
||
|
||
# - Questions ----------------------------------- | ||
# Add error handling for every otel. Use withCallingHandlers similar to https://github.com/r-lib/mirai/pull/395/files#diff-9e809582679952a93b9f34755bb38207471945eb36cedb9e2aa755125449f531R214-R215 | ||
|
||
# TODO: Extended Tasks are linked from parent span. Maybe use an envvar for span context? It is allowed for child process can end much later than the parent process. Take inspiration from callr PR (copying of the span context to the child process). | ||
|
||
# ------------------------------------------ | ||
|
||
# # Approach | ||
# Use flags on the reactive object to indicate whether to record OpenTelemetry spans. | ||
# | ||
# Cadence: | ||
# * `$.isRecordingOtel` - Whether to record OpenTelemetry spans for this reactive object | ||
# * `$.otelLabel` - The label to use for the OpenTelemetry span | ||
# * `$.otelAttrs` - Additional attributes to add to the OpenTelemetry span | ||
|
||
|
||
#' Add OpenTelemetry for reactivity to an object | ||
#' | ||
#' @description | ||
#' | ||
#' `bindOtel()` adds OpenTelemetry for [reactive()] expressions and `render*` | ||
#' functions (like [renderText()], [renderTable()], ...). | ||
#' | ||
#' Wrapper to creating an active reactive OpenTelemetry span that closes when | ||
#' the reactive expression is done computing. Typically this is when the | ||
#' reactive expression finishes (synchronous) or when the returned promise is | ||
#' done computing (asynchronous). | ||
|
||
#' @section Async with OpenTelemetry: | ||
#' | ||
#' With a reactive expression, the key and/or value expression can be | ||
#' _asynchronous_. In other words, they can be promises --- not regular R | ||
#' promises, but rather objects provided by the | ||
#' \href{https://rstudio.github.io/promises/}{\pkg{promises}} package, which | ||
#' are similar to promises in JavaScript. (See [promises::promise()] for more | ||
#' information.) You can also use [mirai::mirai()] or [future::future()] | ||
#' objects to run code in a separate process or even on a remote machine. | ||
#' | ||
#' When reactive expressions are being calculated in parallel (by having | ||
#' another reactive promise compute in the main process), the currently active | ||
#' OpenTelemetry span will be dynamically swapped out according to the | ||
#' currently active reactive expression. This means that as long as a promise | ||
#' was `then()`ed or `catch()`ed with an active OpenTelemetry span, the span | ||
#' will be correctly propagated to the next step (and subsequently other | ||
#' steps) in the promise chain. | ||
#' | ||
#' While the common case is for a reactive expression to be created | ||
#' synchronously, troubles arise when the reactive expression is created | ||
#' asynchronously. The span **must** be created before the reactive expression | ||
#' is executed, it **must** be active for the duration of the expression, and | ||
#' it **must** not be closed until the reactive expression is done executing. | ||
#' This is not easily achieved with a single function call, so we provide a | ||
#' way to create a reactive expression that is bound to an OpenTelemetry | ||
#' span. | ||
#' | ||
#' @param x The object to add caching to. | ||
#' @param ... Future parameter expansion. | ||
#' @seealso [bindCache()] and [bindEvent()] for other ways to bind to your reactives. | ||
#' @noRd | ||
NULL | ||
|
||
bind_otel_reactive_val <- function(x) { | ||
|
||
impl <- attr(x, ".impl", exact = TRUE) | ||
# Set flag for otel logging when setting the value | ||
impl$.isRecordingOtel <- TRUE | ||
|
||
class(x) <- c("reactiveVal.otel", class(x)) | ||
|
||
x | ||
} | ||
|
||
bind_otel_reactive_values <- function(x) { | ||
|
||
impl <- .subset2(x, "impl") | ||
# Set flag for otel logging when setting values | ||
impl$.isRecordingOtel <- TRUE | ||
|
||
class(x) <- c("reactivevalues.otel", class(x)) | ||
|
||
x | ||
} | ||
|
||
bind_otel_reactive_expr <- function(x) { | ||
|
||
domain <- reactive_get_domain(x) | ||
|
||
impl <- attr(x, "observable", exact = TRUE) | ||
impl$.isRecordingOtel <- TRUE | ||
# Covers both reactive and reactive.event | ||
impl$.otelLabel <- ospan_label_reactive(x, domain = impl$.domain) | ||
|
||
class(x) <- c("reactiveExpr.otel", class(x)) | ||
|
||
x | ||
} | ||
|
||
bind_otel_observe <- function(x) { | ||
x$.isRecordingOtel <- TRUE | ||
x$.otelLabel <- ospan_label_observer(x, domain = x$.domain) | ||
|
||
class(x) <- c("Observer.otel", class(x)) | ||
invisible(x) | ||
} | ||
|
||
|
||
|
||
bind_otel_shiny_render_function <- function(x) { | ||
if (inherits(x, "shiny.render.function.otel")) { | ||
# Already bound | ||
return(x) | ||
} | ||
Comment on lines
+148
to
+151
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't ever happen |
||
|
||
valueFunc <- x | ||
span_label <- NULL | ||
ospan_attrs <- attr(x, "otelAttrs") | ||
|
||
renderFunc <- function(...) { | ||
# Dynamically determine the span label given the current reactive domain | ||
if (is.null(span_label)) { | ||
span_label <<- | ||
ospan_label_render_function(x, domain = getDefaultReactiveDomain()) | ||
} | ||
|
||
with_shiny_ospan_async( | ||
span_label, | ||
{ | ||
valueFunc(...) | ||
}, | ||
attributes = ospan_attrs | ||
) | ||
} | ||
|
||
renderFunc <- addAttributes(renderFunc, renderFunctionAttributes(valueFunc)) | ||
class(renderFunc) <- c("shiny.render.function.otel", class(valueFunc)) | ||
renderFunc | ||
} | ||
|
||
|
||
|
||
# bindOtel.function <- function(x, ...) { | ||
# cli::cli_abort(paste0( | ||
# "Don't know how to add OpenTelemetry recording to a plain function. ", | ||
# "If this is a {.code render*()} function for Shiny, it may need to be updated. ", | ||
# "Please see {.help shiny::bindOtel} for more information." | ||
# )) | ||
# } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please delete