@@ -526,6 +526,157 @@ get_usage_static <- function(
526
526
return (out )
527
527
}
528
528
529
+ # ' Get usage information for deployed content
530
+ # '
531
+ # ' @description
532
+ # ' Retrieve content hits for all available content on the server. Available
533
+ # ' content depends on the user whose API key is in use. Administrator accounts
534
+ # ' will receive data for all content on the server. Publishers will receive data
535
+ # ' for all content they own or collaborate on.
536
+ # '
537
+ # ' If no date-times are provided, all usage data will be returned.
538
+ # '
539
+ # ' @param client A `Connect` R6 client object.
540
+ # ' @param from Optional date-time (`POSIXct` or `POSIXlt`). Only
541
+ # ' records after this time are returned. If not provided, records
542
+ # ' are returned back to the first record available.
543
+ # ' @param to Optional date-time (`POSIXct` or `POSIXlt`). Only records
544
+ # ' before this time are returned. If not provided, all records up to
545
+ # ' the most recent are returned.
546
+ # '
547
+ # ' @return A list of usage records. Each record is a list with all elements
548
+ # ' as character strings unless otherwise specified.
549
+ # '
550
+ # ' * `id`: An integer identifier for the hit.
551
+ # ' * `user_guid`: The user GUID if the visitor is logged-in, `NULL` for
552
+ # ' anonymous hits.
553
+ # ' * `content_guid`: The GUID of the visited content.
554
+ # ' * `timestamp`: The time of the hit in RFC3339 format.
555
+ # ' * `data`: A nested list with optional fields:
556
+ # ' * `path`: The request path (if recorded).
557
+ # ' * `user_agent`: The user agent string (if available).
558
+ # '
559
+ # ' Use [as.data.frame()] or [tibble::as_tibble()] to convert to a flat
560
+ # ' table with parsed types. In the resulting data frame:
561
+ # '
562
+ # ' * `timestamp` is parsed to `POSIXct`.
563
+ # ' * `path` and `user_agent` are extracted from the nested `data` field.
564
+ # '
565
+ # ' By default, [as.data.frame()] attempts to extract the nested fields using
566
+ # ' the \pkg{tidyr} package. If \pkg{tidyr} is not available, or if you want to
567
+ # ' skip unnesting, call `as.data.frame(x, unnest = FALSE)` to leave `data` as
568
+ # ' a list-column.
569
+ # '
570
+ # ' @details
571
+ # '
572
+ # ' The data returned by `get_usage()` includes all content types. For Shiny
573
+ # ' content, the `timestamp` indicates the *start* of the Shiny session.
574
+ # ' Additional fields for Shiny and non-Shiny are available respectively from
575
+ # ' [get_usage_shiny()] and [get_usage_static()]. `get_usage_shiny()` includes a
576
+ # ' field for the session end time; `get_usage_static()` includes variant,
577
+ # ' rendering, and bundle identifiers for the visited content.
578
+ # '
579
+ # ' When possible, however, we recommend using `get_usage()` over
580
+ # ' `get_usage_static()` or `get_usage_shiny()`, as it is faster and more efficient.
581
+ # '
582
+ # ' @seealso [as.data.frame.connect_list_hits()], [as_tibble.connect_list_hits()]
583
+ # '
584
+ # ' @examples
585
+ # ' \dontrun{
586
+ # ' client <- connect()
587
+ # '
588
+ # ' # Fetch the last 2 days of hits
589
+ # ' usage <- get_usage(client, from = Sys.Date() - 2, to = Sys.Date())
590
+ # '
591
+ # ' # Fetch usage after a specified date and convert to a data frame.
592
+ # ' usage <- get_usage(
593
+ # ' client,
594
+ # ' from = as.POSIXct("2025-05-02 12:40:00", tz = "UTC")
595
+ # ' )
596
+ # '
597
+ # ' # Fetch all usage
598
+ # ' usage <- get_usage(client)
599
+ # '
600
+ # ' # Convert to tibble or data frame
601
+ # ' usage_df <- tibble::as_tibble(usage)
602
+ # '
603
+ # ' # Skip unnesting if tidyr is not installed
604
+ # ' usage_df <- as.data.frame(usage, unnest = FALSE)
605
+ # ' }
606
+ # '
607
+ # ' @export
608
+ get_usage <- function (client , from = NULL , to = NULL ) {
609
+ error_if_less_than(client $ version , " 2025.04.0" )
610
+
611
+ usage <- client $ GET(
612
+ v1_url(" instrumentation" , " content" , " hits" ),
613
+ query = list (
614
+ from = make_timestamp(from ),
615
+ to = make_timestamp(to )
616
+ )
617
+ )
618
+
619
+ class(usage ) <- c(" connect_list_hits" , class(usage ))
620
+ usage
621
+ }
622
+
623
+ # ' Convert usage data to a data frame
624
+ # '
625
+ # ' @description
626
+ # ' Converts an object returned by [get_usage()] into a data frame with parsed
627
+ # ' column types. By default, extracts `path` and `user_agent` from the `data`
628
+ # ' field, if available.
629
+ # '
630
+ # ' @param x A `connect_list_hits` object (from [get_usage()]).
631
+ # ' @param row.names Passed to [base::as.data.frame()].
632
+ # ' @param optional Passed to [base::as.data.frame()].
633
+ # ' @param ... Passed to [base::as.data.frame()].
634
+ # ' @param unnest Logical; if `TRUE` (default), extracts nested fields using
635
+ # ' \pkg{tidyr}. Set to `FALSE` to skip unnesting.
636
+ # '
637
+ # ' @return A `data.frame` with one row per usage record.
638
+ # ' @export
639
+ # ' @method as.data.frame connect_list_hits
640
+ as.data.frame.connect_list_hits <- function (
641
+ x ,
642
+ row.names = NULL , # nolint
643
+ optional = FALSE ,
644
+ ... ,
645
+ unnest = TRUE
646
+ ) {
647
+ usage_df <- parse_connectapi_typed(x , connectapi_ptypes $ usage )
648
+ if (unnest ) {
649
+ if (! requireNamespace(" tidyr" , quietly = TRUE )) {
650
+ stop(
651
+ " `unnest = TRUE` requires tidyr. Install tidyr or set `unnest = FALSE`." ,
652
+ call. = FALSE
653
+ )
654
+ }
655
+ usage_df <- tidyr :: unnest_wider(
656
+ usage_df ,
657
+ " data" ,
658
+ ptype = list (path = character (0 ), user_agent = character (0 ))
659
+ )
660
+ }
661
+ as.data.frame(usage_df , row.names = row.names , optional = optional , ... )
662
+ }
663
+
664
+ # ' Convert usage data to a tibble
665
+ # '
666
+ # ' @description
667
+ # ' Converts an object returned by [get_usage()] to a tibble via
668
+ # ' [as.data.frame.connect_list_hits()].
669
+ # '
670
+ # ' @param x A `connect_list_hits` object.
671
+ # ' @param ... Passed to [as.data.frame()].
672
+ # '
673
+ # ' @return A tibble with one row per usage record.
674
+ # ' @export
675
+ # ' @importFrom tibble as_tibble
676
+ # ' @method as_tibble connect_list_hits
677
+ as_tibble.connect_list_hits <- function (x , ... ) {
678
+ tibble :: as_tibble(as.data.frame(x , ... ))
679
+ }
529
680
530
681
# ' Get Audit Logs from Posit Connect Server
531
682
# '
0 commit comments