diff --git a/DATAMODEL.md b/DATAMODEL.md
new file mode 100644
index 0000000..646a2e2
--- /dev/null
+++ b/DATAMODEL.md
@@ -0,0 +1,290 @@
+# Introduction
+
+This document provides an overview of the Events and Attributes used for media monitoring in New Relic.
+
+# Glossary
+
+This section defines the key terms used in the context of New Relic Media monitoring:
+
+## Event Types
+
+- **RokuSystem**: Events related to system tracking.
+- **videoAction**: Events triggered by general video interactions, such as starting, pausing, or seeking.
+- **videoAdAction**: Events related to ad playback, such as starting, completing, or skipping an ad.
+- **videoErrorAction**: Events triggered by errors encountered during video or ad playback.
+- **videoCustomAction**: Custom events defined to capture specific actions or interactions beyond default event types.
+
+## Attribute
+
+An Attribute is a piece of data associated with an event. Attributes provide additional context or details about the event, such as the video’s title, duration, or playback position.
+
+- Most attributes are included with every event.
+- Some attributes are specific to certain event types, such as ad-related data sent with ad events.
+
+## Event Type Reference
+
+### RokuSystem
+
+| Attribute Name | Description |
+|---|---|
+| instrumentation.provider | Always “media”. |
+| instrumentation.name | Always “roku”. |
+| instrumentation.version | Agent’s version. |
+| newRelicAgent | Always “RokuAgent”. |
+| newRelicVersion | Agent’s version. |
+| sessionId | Session ID, a hash that is generated every time the Roku app starts. |
+| hdmiIsConnected | Boolean. HDMI is connected or not. |
+| hdmiHdcpVersion | HDCP version. |
+| deviceUuid | Roku Device UUID. |
+| deviceName | Roku device name. |
+| deviceSize | Always "xLarge". |
+| deviceGroup | Always “Roku”. |
+| deviceManufacturer | Always “Roku”. |
+| deviceModel | Roku model. |
+| deviceType | Roku model type. |
+| vendorName | Roku model vendor. |
+| modelNumber | Roku model number. |
+| vendorUsbName | USB vendor. |
+| screenSize | Size of the Roku TV. |
+| osName | Always “RokuOS”. |
+| osVersion | Firmware version. |
+| countryCode | Country from where the current user is connected. |
+| timeZone | Current user’s timezone. |
+| locale | Current user’s locale. |
+| memoryLevel | Device memory level. |
+| memLimitPercent | Usage percentage of memory limit for the channel. Only reported if the memory monitor is enabled. |
+| channelAvailMem | Estimated kilobytes of memory available for the channel. Only reported if the memory monitor is enabled. |
+| connectionType | Network connection type (WiFi, etc). |
+| displayType | Type of display, screen, TV, etc. |
+| contentRenditionName | Display mode. |
+| displayAspectRatio | Aspect ratio. |
+| videoMode | Video mode. |
+| graphicsPlatform | Graphics platform (OpenGL, etc). |
+| timeSinceLastKeyPress | Time since last keypress in the remote. Milliseconds. |
+| appId | Application ID. |
+| appVersion | Application version. |
+| appName | Application name. |
+| appDevId | Developer ID. |
+| appBuild | Application build number. |
+| timeSinceLoad | Time since NewRelic function call. Seconds. |
+| uptime | Uptime of the system since the last reboot. Seconds. |
+| httpCode | Response code. |
+| method | HTTP method. |
+| origUrl | Original URL of request. |
+| domain | Host part of `origUrl`. |
+| status | Current request status. |
+| targetIp | Target IP address of request. |
+| url | Actual URL of request. |
+| bytesDownloaded | Number of bytes downloaded. |
+| bytesUploaded | Number of bytes uploaded. |
+| connectTime | Total connection time. |
+| contentType | Mime type of response body. |
+| dnsLookupTime | DNS lookup time. |
+| downloadSpeed | Download speed. |
+| firstByteTime | Time elapsed until the first bytes arrived. |
+| transferTime | Total transfer time. |
+| uploadSpeed | Upload speed. |
+| bandwidth | Bandwidth. |
+| lastExitOrTerminationReason | The reason for the last app exit / termination. |
+| splashTime | The splash time in ms. |
+| instantOnRunMode | Value of `instant_on_run_mode` property sent to Main. |
+| launchSource | Value of `source` property sent to Main. |
+| httpResult | Request final status. |
+| http* | Multiple attributes. All the header keys. |
+| transferIdentity | HTTP request identificator. |
+| sceneName | Identifier of the scene. |
+| timeSinceHttpRequest | Time since `HTTP_REQUEST` in milliseconds. |
+| enduser.id | User ID. |
+
+
+
+#### List of possible RokuSystem Actions
+
+| Action Name | Description |
+|---|---|
+| BANDWIDTH_MINUTE | Report the bandwidth every minute. |
+| HTTP_CONNECT | An HTTP request, generated by roSystemLog. |
+| HTTP_COMPLETE | An HTTP response, generated by roSystemLog. |
+| HTTP_ERROR | An HTTP error, generated by roSystemLog. |
+| HTTP_REQUEST | An HTTP request. Generated by nrSendHttpRequest function. |
+| HTTP_RESPONSE | An HTTP response. Generated by nrSendHttpResponse function. |
+| APP_STARTED | The app did start. Generated by nrAppStarted function. |
+| SCENE_LOADED | A scene did load. Generated by nrSceneLoaded function. |
+
+### VideoAction
+
+| Attribute Name | Definition |
+| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
+| actionName | The specific action being performed in the video player, such as play, pause, resume, content buffering, etc. |
+| appId | The ID of your application, as recorded by New Relic. |
+| appName | The name of the application. |
+| playerName | The name of the video player. |
+| playerVersion | The version of the video player. |
+| deviceType | The specific type of the device: iPhone 8, iPad Pro, etc. |
+| deviceGroup | The category of the device, such as iPhone or Tablet. |
+| deviceManufacturer | The manufacturer of the device, such as Motorola or HTC. |
+| deviceModel | The model number of the device. |
+| deviceName | The device's name. |
+| deviceSize | The display size of the device: Small, normal, large, xlarge. |
+| deviceUuid | A unique identifier assigned at the time of app installation by New Relic. |
+| viewSession | Trackers will generate unique IDs for every new video session. This could be the session ID from the client. |
+| viewId | Trackers will generate unique IDs for every new video iteration. |
+| contentId | The ID of the video. |
+| contentTitle | The title of the video. |
+| contentBitrate | Bitrate (in bits) of the video. |
+| contentIsFullscreen | Always "true". |
+| contentRenditionName | Name of the rendition (e.g., 1080p). |
+| contentDuration | Duration of the video, in ms. |
+| contentPlayhead | Playhead (currentTime) of the video, in ms. |
+| contentSrc | URL of the resource being played. |
+| contentIsFullscreen | True if the video is currently fullscreen. |
+| contentIsMuted | True if the video is currently muted. |
+| totalAdPlaytime | Total time ad is played for this video session. |
+| elapsedTime | Time that has passed since the last event. |
+| bufferType | When buffer starts, i.e., initial, seek, pause & connection. |
+| timestamp | The time (date, hour, minute, second) at which the interaction occurred. |
+| instrumentation.provider | Player/agent name. |
+| instrumentation.name | Name of the instrumentation collecting the data. |
+| instrumentation.version | Agent’s version. |
+| enduser.id | User ID. |
+
+#### List of possible Video Actions
+
+| Action Name | Definition |
+| ------------------------ | ------------------------------------------------------------------------------------------------ |
+| PLAYER_READY | The player is ready to start sending events. |
+| CONTENT_REQUEST | Content video has been requested. |
+| CONTENT_START | Content video started (first frame shown). |
+| CONTENT_END | Content video ended. |
+| CONTENT_PAUSE | Content video paused. |
+| CONTENT_RESUME | Content video resumed. |
+| CONTENT_BUFFER_START | Content video buffering started. |
+| CONTENT_BUFFER_END | Content video buffering ended. |
+| CONTENT_HEARTBEAT | Content video heartbeat, an event that happens once every 30 seconds while the video is playing. |
+
+### VideoAdAction
+
+| Attribute Name | Definition |
+| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
+| actionName | The specific action being performed in the video player, such as play, pause, resume, content buffering, etc. |
+| appId | The ID of your application, as recorded by New Relic. |
+| appName | The name of the application. |
+| playerName | The name of the video player. |
+| playerVersion | The version of the video player. |
+| deviceType | The specific type of the device: iPhone 8, iPad Pro, etc. |
+| deviceGroup | The category of the device, such as iPhone or Tablet. |
+| deviceManufacturer | The manufacturer of the device, such as Motorola or HTC. |
+| deviceModel | The model number of the device. |
+| viewSession | Trackers will generate unique IDs for every new video session. This could be the session ID from the client. |
+| viewId | Trackers will generate unique IDs for every new video iteration. |
+| adId | The ID of the video. |
+| adTitle | The title of the video. |
+| adDuration | Duration of the video, in ms. |
+| adPlayhead | Playhead (currentTime) of the video, in ms. |
+| adSrc | URL of the resource being played. |
+| adIsMuted | True if the video is currently muted. |
+| adQuartile | Quartile of the ad. 0 before first, 1 after first quartile, 2 after midpoint, 3 after third quartile, 4 when completed. |
+| adPosition | The position of the ad. |
+| adCreativeId | The creative ID of the ad. |
+| adPartner | The ad partner, e.g., ima, freewheel. |
+| timestamp | The time (date, hour, minute, second) at which the interaction occurred. |
+| elapsedTime | Time that has passed since the last event. |
+| instrumentation.provider | Player/agent name. |
+| instrumentation.name | Name of the instrumentation collecting the data. |
+| instrumentation.version | Agent’s version. |
+| enduser.id | User ID. |
+
+#### List of possible Video Ad Actions
+
+| Action Name | Definition |
+| ------------------- | ------------------------------------------------------------------------------------------- |
+| AD_REQUEST | Ad video has been requested. |
+| AD_START | Ad video started (first frame shown). |
+| AD_END | Ad video ended. |
+| AD_PAUSE | Ad video paused. |
+| AD_RESUME | Ad video resumed. |
+| AD_BREAK_START | Ad break (a block of ads) started. |
+| AD_BREAK_END | Ad break ended. |
+| AD_QUARTILE | Ad quartile happened. |
+
+### VideoErrorAction
+
+| Attribute Name | Definition |
+| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
+| actionName | The specific action being performed in the video player, such as play, pause, resume, content buffering, etc. |
+| appId | The ID of your application, as recorded by New Relic. |
+| appName | The name of the application. |
+| playerName | The name of the video player. |
+| playerVersion | The version of the video player. |
+| deviceType | The specific type of the device: iPhone 8, iPad Pro, etc. |
+| deviceGroup | The category of the device, such as iPhone or Tablet. |
+| deviceManufacturer | The manufacturer of the device, such as Motorola or HTC. |
+| deviceModel | The model number of the device. |
+| viewSession | Trackers will generate unique IDs for every new video session. This could be the session ID from the client. |
+| viewId | Trackers will generate unique IDs for every new video iteration. |
+| contentId | The ID of the video. |
+| contentTitle | The title of the video. |
+| errorName | Name of the error. |
+| errorCode | Error code if it's known. |
+| backTrace | Stack trace of the error. |
+| contentSrc | Content source URL. |
+| elapsedTime | Time that has passed since the last event. |
+| timestamp | The time (date, hour, minute, second) at which the interaction occurred. |
+| instrumentation.provider | Player/agent name. |
+| instrumentation.name | Name of the instrumentation collecting the data. |
+| instrumentation.version | Agent’s version. |
+| enduser.id | User ID. |
+
+#### List of possible Video Error Actions
+
+| Action Name | Definition |
+| ------------- | -------------------- |
+| AD_ERROR | Ad video error. |
+| HTTP_ERROR | An HTTP error. |
+| CONTENT_ERROR | Content video error. |
+
+### VideoCustomAction
+
+| Attribute Name | Definition |
+| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
+| actionName | The name of the PageAction, as defined by client in their code. |
+| appId | The ID of your application, as recorded by New Relic. |
+| appName | The name of the application. |
+| playerName | The name of the video player. |
+| playerVersion | The version of the video player. |
+| deviceType | The specific type of the device: iPhone 8, iPad Pro, etc. |
+| deviceGroup | The category of the device, such as iPhone or Tablet. |
+| deviceManufacturer | The manufacturer of the device, such as Motorola or HTC. |
+| deviceModel | The model number of the device. |
+| viewSession | Trackers will generate unique IDs for every new video session. This could be the session ID from the client. |
+| viewId | Trackers will generate unique IDs for every new video iteration. |
+| contentId | The ID of the video. |
+| contentTitle | The title of the video. |
+| timestamp | The time (date, hour, minute, second) at which the interaction occurred. |
+| instrumentation.provider | Player/agent name. |
+| instrumentation.name | Name of the instrumentation collecting the data. |
+| instrumentation.version | Agent’s version. |
+| enduser.id | User ID. |
+
+#### The following attributes are also a part of VideoAction
+
+| Attribute Name | Definition |
+| ------------- | -------------------- |
+| contentMeasuredBitrate | Video Measured Bitrate. |
+| contentSegmentBitrate | In case of segmented video sources (HLS, DASH), the current segment’s bitrate. |
+| sessionDuration | Time since the session started.. |
+| trackerName | Always “rokutracker”. |
+| trackerVersion | Agent version. |
+| numberOfVideos | Number of videos played. |
+| numberOfErrors | Number of errors happened. |
+| timeSinceLastHeartbeat | Time since last heartbeat, in milliseconds. |
+| timeSinceRequested | Time since the video requested, in milliseconds. |
+| timeSinceStarted | Time since the video started, in milliseconds. |
+| timeSinceTrackerReady | Time since `PLAYER_READY`, in milliseconds. |
+| totalPlaytime | Total time the user spend seeing the video. |
+| playtimeSinceLastEvent | Total time the user spend seeing the video since last video event. |
+| timeToStartStreaming | The time in milliseconds from playback being started until the video actually began playing. |
+| isPlaylist | Content is a playlist. Boolean. |
+| videoFormat | Video format, a mime type. |
+| timeSinceBufferBegin | Time since video last video buffering began, in milliseconds. |
+| timeSincePaused | Time since the video was paused, in milliseconds. |
\ No newline at end of file
diff --git a/README.md b/README.md
index ff95218..1a8b5d6 100644
--- a/README.md
+++ b/README.md
@@ -4,10 +4,16 @@
The New Relic Roku Agent tracks the behavior of a Roku App. It contains two parts, one to monitor general system level events and one to monitor video related events, for apps that use a video player.
-Internally, it uses the Event API to send events using the REST interface. It sends two types of events: RokuSystem for system events and RokuVideo for video events. After the agent has sent some data it will be accessible in NR One Dashboards with a simple NRQL request like:
+Internally, it uses the Event API to send events using the REST interface. It sends five types of events:
+- RokuSystem for system events
+- VideoAction for video events.
+- VideoErrorAction for errors.
+- VideoAdAction for ads.
+- VideoCustomAction for custom actions.
+After the agent has sent some data it will be accessible in NR One Dashboards with a simple NRQL request like:
```
-SELECT * FROM RokuSystem, RokuVideo
+SELECT * FROM RokuSystem, VideoAction, VideoErrorAction, VideoAdAction, VideoCustomAction
```
Will result in something like the following:
@@ -18,10 +24,7 @@ Will result in something like the following:
* [Installation](#installation)
* [Usage](#usage)
* [Agent API](#api)
- * [Data Model](#data-model)
- * [Roku System](#roku-system)
- * [Roku Video](#roku-video)
- * [Metrics](#metrics)
+ * [Data Model](#data-model)
* [Ad Tracking](#ad-track)
* [Testing](#testing)
* [Open Source License](#open-source)
@@ -416,7 +419,7 @@ Example:
nrSendVideoEvent(nr as Object, actionName as String, attr = invalid) as Void
Description:
- Send a video event, type RokuVideo.
+ Send a video event, type VideoAction.
Arguments:
nr: New Relic Agent object.
@@ -801,215 +804,27 @@ Example:
nrSendSummaryMetric(m.nr, "test", 2000, 5, 1000, 100, 200)
```
-
+**setUserId**
-### Data Model
+```
+setUserId(userId as String) as Void
+
+Description:
+ Sets userId.
+
+Arguments:
+ userId: attribute
+
+Return:
+ Nothing.
+
+Example:
+ setUserId("TEST_USER")
+```
-The agent generates two different event types: `RokuSystem` and `RokuVideo`.
-
-
-
-#### 1. RokuSystem
-
-This event groups all actions related to system tracking.
-
-#### 1.1 Actions
-
-| Action Name | Description |
-|---|---|
-| `BANDWIDTH_MINUTE` | Report the bandwidth every minute. |
-| `HTTP_CONNECT` | An HTTP request, generated by roSystemLog. |
-| `HTTP_COMPLETE` | An HTTP response, generated by roSystemLog. |
-| `HTTP_ERROR` | An HTTP error, generated by roSystemLog. |
-| `HTTP_REQUEST` | An HTTP request. Generated by nrSendHttpRequest function. |
-| `HTTP_RESPONSE` | An HTTP response. Generated by nrSendHttpResponse function. |
-| `APP_STARTED` | The app did start. Generated by nrAppStarted function. |
-| `SCENE_LOADED` | A scene did load. Generated by nrSceneLoaded function. |
-
-#### 1.2 Attributes
-
-There is a set of attributes common to all actions sent over a `RokuSystem` and others are specific to a certain action.
-
-#### 1.2.1 Common Attributes
-
-| Attribute Name | Description |
-|---|---|
-| `instrumentation.provider` | Always “media”. |
-| `instrumentation.name` | Always “roku”. |
-| `instrumentation.version` | Agent’s version. |
-| `newRelicAgent` | Always “RokuAgent”. |
-| `newRelicVersion` | Agent’s version. |
-| `sessionId` | Session ID, a hash that is generated every time the Roku app starts. |
-| `hdmiIsConnected` | Boolean. HDMI is connected or not. |
-| `hdmiHdcpVersion` | HDCP version. |
-| `uuid` | Roku Device UUID. |
-| `device` | Roku device name. |
-| `deviceGroup` | Always “Roku”. |
-| `deviceManufacturer` | Always “Roku”. |
-| `deviceModel` | Roku model. |
-| `deviceType` | Roku model type. |
-| `vendorName` | Roku model vendor. |
-| `modelNumber` | Roku model number. |
-| `vendorUsbName` | USB vendor. |
-| `screenSize` | Size of the Roku TV. |
-| `osName` | Always “RokuOS”. |
-| `osVersion` | Firmware version. |
-| `countryCode` | Country from where the current user is connected. |
-| `timeZone` | Current user’s timezone. |
-| `locale` | Current user’s locale. |
-| `memoryLevel` | Device memory level. |
-| `memLimitPercent` | Usage percentage of memory limit for the channel. Only reported if the memory monitor is enabled. |
-| `channelAvailMem` | Estimated kilobytes of memory available for the channel. Only reported if the memory monitor is enabled. |
-| `connectionType` | Network connection type (WiFi, etc). |
-| `displayType` | Type of display, screen, TV, etc. |
-| `displayMode` | Display mode. |
-| `displayAspectRatio` | Aspect ratio. |
-| `videoMode` | Video mode. |
-| `graphicsPlatform` | Graphics platform (OpenGL, etc). |
-| `timeSinceLastKeyPress` | Time since last keypress in the remote. Milliseconds. |
-| `appId` | Application ID. |
-| `appVersion` | Application version. |
-| `appName` | Application name. |
-| `appDevId` | Developer ID. |
-| `appBuild` | Application build number. |
-| `timeSinceLoad` | Time since NewRelic function call. Seconds. |
-| `uptime` | Uptime of the system since the last reboot. Seconds. |
-
-#### 1.2.2 Action Specific Attributes
-
-| Attribute Name | Description | Actions |
-|---|---|---|
-| `httpCode` | Response code. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR`, `HTTP_RESPONSE` |
-| `method` | HTTP method. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR`, `HTTP_REQUEST ` |
-| `origUrl` | Original URL of request. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR`, `HTTP_REQUEST`, `HTTP_RESPONSE` |
-| `domain` | Host part of `origUrl`. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR`, `HTTP_REQUEST`, `HTTP_RESPONSE` |
-| `status` | Current request status. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR` |
-| `targetIp` | Target IP address of request. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR` |
-| `url` | Actual URL of request. | `HTTP_COMPLETE`, `HTTP_CONNECT`, `HTTP_ERROR` |
-| `bytesDownloaded` | Number of bytes downloaded. | `HTTP_COMPLETE` |
-| `bytesUploaded` | Number of bytes uploaded. | `HTTP_COMPLETE` |
-| `connectTime` | Total connection time. | `HTTP_COMPLETE` |
-| `contentType` | Mime type of response body. | `HTTP_COMPLETE` |
-| `dnsLookupTime` | DNS lookup time. | `HTTP_COMPLETE` |
-| `downloadSpeed` | Download speed. | `HTTP_COMPLETE` |
-| `firstByteTime` | Time elapsed until the first bytes arrived. | `HTTP_COMPLETE` |
-| `transferTime` | Total transfer time. | `HTTP_COMPLETE` |
-| `uploadSpeed` | Upload speed. | `HTTP_COMPLETE` |
-| `bandwidth` | Bandwidth. | `BANDWIDTH_MINUTE` |
-| `lastExitOrTerminationReason` | The reason for the last app exit / termination. | `APP_STARTED` |
-| `splashTime` | The splash time in ms. | `APP_STARTED` |
-| `instantOnRunMode` | Value of `instant_on_run_mode` property sent to Main. | `APP_STARTED` |
-| `launchSource ` | Value of `source` property sent to Main. | `APP_STARTED` |
-| `httpResult` | Request final status. | `HTTP_RESPONSE` |
-| `http*` | Multiple attributes. All the header keys. | `HTTP_RESPONSE` |
-| `transferIdentity` | HTTP request identificator. | `HTTP_REQUEST`, `HTTP_RESPONSE` |
-| `sceneName` | Identifier of the scene. | `SCENE_LOADED` |
-| `timeSinceHttpRequest` | Time since `HTTP_REQUEST` in milliseconds. | `HTTP_RESPONSE` |
-
-
-
-#### 2. RokuVideo
-
-This event groups all actions related to video tracking.
-
-#### 2.1 Actions
-
-| Action Name | Description |
-|---|---|
-| `PLAYER_READY` | Player is ready to start working. It happens when the video agent is started. |
-| `CONTENT_REQUEST` | “Play” button pressed or autoplay activated. |
-| `CONTENT_START` | Video just started playing. |
-| `CONTENT_END` | Video ended playing. |
-| `CONTENT_PAUSE` | Video paused. |
-| `CONTENT_RESUME` | Video resumed. |
-| `CONTENT_BUFFER_START` | Video started buffering. |
-| `CONTENT_BUFFER_END` | Video ended buffering. |
-| `CONTENT_ERROR` | Video error happened. |
-| `CONTENT_HEARTBEAT` | Sent every 30 seconds between video start and video end. |
-| `LICENSE_STATUS` | Video has received a DRM license response |
-
-#### 2.2 Attributes
-
-There is a set of attributes common to all actions sent over a `RokuVideo` and others are specific to a certain action.
-
-#### 2.2.1 Common Attributes
-
-For video events, the common attributes include all `RokuSystem` common attributes (1.2.1) plus the video event ones. Here we will describe only the video common attributes.
-
-| Attribute Name | Description |
-|---|---|
-| `contentDuration` | Total video duration in milliseconds. |
-| `contentPlayhead` | Current video position in milliseconds. |
-| `contentIsMuted` | Video is muted or not. |
-| `contentSrc` | Video URL. |
-| `contentId` | Content ID, a CRC32 of contentSrc. |
-| `contentBitrate` | Video manifest bitrate. |
-| `contentMeasuredBitrate` | Video measured bitrate. |
-| `contentSegmentBitrate` | In case of segmented video sources (HLS, DASH), the current segment’s bitrate. |
-| `playerName` | Always “RokuVideoPlayer”. |
-| `playerVersion` | Current firmware version. |
-| `sessionDuration` | Time since the session started. |
-| `viewId` | sessionId + “-“ + video counter. |
-| `viewSession` | Copy of sessionId. |
-| `trackerName` | Always “rokutracker”. |
-| `trackerVersion` | Agent version. |
-| `numberOfVideos` | Number of videos played. |
-| `numberOfErrors` | Number of errors happened. |
-| `timeSinceLastHeartbeat` | Time since last heartbeat, in milliseconds. |
-| `timeSinceRequested` | Time since the video requested, in milliseconds. |
-| `timeSinceStarted` | Time since the video started, in milliseconds. |
-| `timeSinceTrackerReady` | Time since `PLAYER_READY`, in milliseconds. |
-| `totalPlaytime` | Total time the user spend seeing the video. |
-| `playtimeSinceLastEvent` | Total time the user spend seeing the video since last video event. |
-| `timeToStartStreaming` | The time in milliseconds from playback being started until the video actually began playing. |
-| `isPlaylist` | Content is a playlist. Boolean. |
-| `videoFormat` | Video format, a mime type. |
-
-#### 2.2.2 Action Specific Attributes
-
-| Attribute Name | Description | Actions |
-|---|---|---|
-| `timeSinceBufferBegin` | Time since video last video buffering began, in milliseconds. | `CONTENT_BUFFER_END` |
-| `timeSincePaused` | Time since the video was paused, in milliseconds. | `CONTENT_RESUME` |
-| `errorMessage` | Descriptive error message. | `CONTENT_ERROR` |
-| `errorCode` | Numeric error code. | `CONTENT_ERROR` |
-| `errorStr` | Detailed error message. | `CONTENT_ERROR` |
-| `errorClipId` | Property `clip_id` from Video object errorInfo. | `CONTENT_ERROR` |
-| `errorIgnored` | Property `ignored` from Video object errorInfo. | `CONTENT_ERROR` |
-| `errorSource` | Property `source` from Video object errorInfo. | `CONTENT_ERROR` |
-| `errorCategory` | Property `category` from Video object errorInfo. | `CONTENT_ERROR` |
-| `errorInfoCode` | Property `error_code` from Video object errorInfo. | `CONTENT_ERROR` |
-| `errorDebugMsg` | Property `dbgmsg` from Video object errorInfo. | `CONTENT_ERROR` |
-| `errorAttributes` | Property `error_attributes` from Video object errorInfo. | `CONTENT_ERROR` |
-| `licenseStatusDuration` | Property `duration` from Video object licenseStatus. | `CONTENT_ERROR`, `LICENSE_STATUS` |
-| `licenseStatusKeySystem` | Property `keySystem` from Video object licenseStatus. | `CONTENT_ERROR`, `LICENSE_STATUS` |
-| `licenseStatusResponse` | Property `response` from Video object licenseStatus. | `CONTENT_ERROR`, `LICENSE_STATUS` |
-| `licenseStatusStatus` | Property `status` from Video object licenseStatus. | `CONTENT_ERROR`, `LICENSE_STATUS` |
-| `isInitialBuffering` | Is the initial buffering event, and not a rebuffering. In playlists it only happens at the beginning, and not on every video. | `CONTENT_BUFFER_*` |
-
-
-#### 3. Metrics
-
-The Roku agent generates the following metrics OOTB:
-
-| Metric Name | Associated event | Metric type | Description |
-|---|---|---|---|
-| `roku.http.connect.count` | `HTTP_CONNECT` | count | Number of `HTTP_CONNECT` events generated in a period of time. |
-| `roku.http.complete.count` | `HTTP_COMPLETE` | count | Number of `HTTP_COMPLETE` events generated in a period of time. |
-| `roku.http.complete.connectTime` | `HTTP_COMPLETE` | gauge | Time taken to connect to the server in seconds. |
-| `roku.http.complete.dnsTime` | `HTTP_COMPLETE` | gauge | DNS name resolution time in seconds. |
-| `roku.http.complete.downSpeed` | `HTTP_COMPLETE` | gauge | Transfer download speed in bytes per second. |
-| `roku.http.complete.firstByteTime` | `HTTP_COMPLETE` | gauge | Time taken to receive the first byte from the server in seconds. |
-| `roku.http.complete.upSpeed` | `HTTP_COMPLETE` | gauge | Transfer upload speed in bytes per second. |
-| `roku.http.error.count` | `HTTP_ERROR` | count | Number of `HTTP_ERROR` events generated in a period of time. |
-| `roku.http.request.count` | `HTTP_REQUEST` | count | Number of `HTTP_REQUEST` events generated in a period of time. |
-| `roku.http.response.count` | `HTTP_RESPONSE` | count | Number of `HTTP_RESPONSE` events generated in a period of time. |
-| `roku.http.response.error.count` | `HTTP_RESPONSE` | count | Number of `HTTP_REQUEST` events generated in a period of time, that returned an error. |
-| `roku.http.response.time` | `HTTP_RESPONSE` | gauge | Time since request in milliseconds. |
-
-Each metric is associated with an event generated by the agent.
-
-All metrics include the attribute `domain`, that is the host of the HTTP request.
+
+### Data Model
+To understand which actions and attributes are captured and emitted by the Dash Player under different event types, see [DataModel.md](./DATAMODEL.md).
### Ad Tracking
@@ -1114,49 +929,6 @@ Where `m.top.tracker` is the tracker object passed to the task.
For a complete usage example, checkout files `VideoScene.brs` (function `setupVideoWithIMA()`) and `imasdk.brs` in the present repo.
-#### Data Model
-
-**Actions**
-
-| Action Name | Description |
-|---|---|
-| `AD_BREAK_START` | An Ad Break has started. |
-| `AD_BREAK_END` | An Ad Break has ended. |
-| `AD_REQUEST` | Ad requested. |
-| `AD_START` | Ad started. |
-| `AD_PAUSE` | Ad paused. |
-| `AD_RESUME` | Ad resumed. |
-| `AD_END` | Ad ended. |
-| `AD_QUARTILE` | Ad quartile happened. There are 3 quartile events during the ad playback. First happens after 25% of the ad is played. Second after 50% and third after 75%. |
-| `AD_SKIP` | Ad skipped. |
-| `AD_ERROR` | An error happened. |
-
-**Attributes**
-
-| Attribute Name | Description | Actions |
-|---|---|---|
-| `timeSinceAdBreakBegin` | Time since `AD_BREAK_START` happened, in milliseconds. | `AD_BREAK_END` |
-| `timeSinceAdStarted` | Time since `AD_START` happened, in milliseconds. | All `AD_` events. |
-| `timeSinceAdRequested` | Time since `AD_REQUEST` happened, in milliseconds. | All `AD_` events. |
-| `timeSinceAdPaused` | Time since `AD_PAUSE` happened, in milliseconds. | `AD_RESUME` |
-| `adTitle` | Title of current ad. | All `AD_` events. |
-| `adId` | ID of current Ad. | All `AD_` events. |
-| `adSystem` | Ad System of current Ad. | All `AD_` events. |
-| `adDuration` | Ad duration in milliseconds. | All `AD_` events. |
-| `adPosition` | Ad break position, "pre", "mid", "post" or "live". | All `AD_` events. |
-| `adSrc` | Stream source of current Ad. | All `AD_` events. |
-| `adCreativeId` | Creative ID of current Ad. | All `AD_` events. |
-| `adPartner` | Partner of current Ad. | All `AD_` events. |
-| `numberOfAds` | Number of started ads. | All `AD_` events. |
-| `adQuartile` | Quartile number: 1, 2 or 3. | `AD_QUARTILE`. |
-| `adErrorType` | Error type. | `AD_ERROR`. |
-| `adErrorCode` | Error code. | `AD_ERROR`. |
-| `adErrorMsg` | Error message. | `AD_ERROR`. |
-
-Not all events and attributes are supported in all Ad trackers.
-
-
-
### Testing
To run the unit tests, first copy the file `UnitTestFramework.brs` from [unit-testing-framework](https://github.com/rokudev/unit-testing-framework) to `source/testFramework/`. Then install the demo channel provided in the present repo and from a terminal run:
diff --git a/components/NewRelicAgent/NRAgent.brs b/components/NewRelicAgent/NRAgent.brs
index e6a172b..f23457d 100644
--- a/components/NewRelicAgent/NRAgent.brs
+++ b/components/NewRelicAgent/NRAgent.brs
@@ -17,6 +17,7 @@ sub init()
print " New Relic Agent for Roku v" + m.nrAgentVersion
print " Copyright 2019-2023 New Relic Inc. All Rights Reserved."
print "************************************************************"
+ InitializeLastEventTimestamps()
end sub
'=========================='
@@ -243,15 +244,15 @@ function nrAppStarted(aa as Object) as Void
"instantOnRunMode": aa["instant_on_run_mode"],
"launchSource": aa["source"]
}
- nrSendCustomEvent("RokuSystem", "APP_STARTED", attr)
+ nrSendSystemEvent("RokuSystem", "APP_STARTED", attr)
end function
function nrSceneLoaded(sceneName as String) as Void
- nrSendCustomEvent("RokuSystem", "SCENE_LOADED", {"sceneName": sceneName})
+ nrSendSystemEvent("RokuSystem", "SCENE_LOADED", {"sceneName": sceneName})
end function
-function nrSendCustomEvent(eventType as String, actionName as String, attr = invalid as Object) as Void
- nrLog("nrSendCustomEvent")
+function nrSendSystemEvent(eventType as String, actionName as String, attr = invalid as Object) as Void
+ nrLog("nrSendSystemEvent")
ev = nrCreateEvent(eventType, actionName)
ev = nrAddCustomAttributes(ev)
if attr <> invalid
@@ -260,12 +261,8 @@ function nrSendCustomEvent(eventType as String, actionName as String, attr = inv
nrRecordEvent(ev)
end function
-function nrSendSystemEvent(actionName as String, attr = invalid) as Void
- nrSendCustomEvent("RokuSystem", actionName, attr)
-end function
-
function nrSendVideoEvent(actionName as String, attr = invalid) as Void
- ev = nrCreateEvent("RokuVideo", actionName)
+ ev = nrCreateEvent("VideoAction", actionName)
ev = nrAddVideoAttributes(ev)
ev = nrAddCustomAttributes(ev)
if type(attr) = "roAssociativeArray"
@@ -280,6 +277,41 @@ function nrSendVideoEvent(actionName as String, attr = invalid) as Void
end if
end function
+function nrSendErrorEvent(actionName as String, ctx as Dynamic, attr = invalid) as Void
+ ev = nrCreateEvent("VideoErrorAction", actionName)
+ ev = nrAddVideoAttributes(ev)
+ ev = nrAddCustomAttributes(ev)
+ if type(attr) = "roAssociativeArray"
+ ev.Append(attr)
+ end if
+ nrRecordEvent(ev)
+end function
+
+function nrSendCustomEvent(actionName as String, ctx as Dynamic, attr = invalid) as Void
+ ev = nrCreateEvent("VideoCustomAction", actionName)
+ ' Check if ctx contains attributes other than adpartner with value "raf"
+ hasOtherAdAttributes = false
+ if ctx <> invalid and type(ctx) = "roAssociativeArray"
+ for each key in ctx
+ if key <> "adpartner" or (key = "adpartner" and ctx[key] <> "raf")
+ hasOtherAdAttributes = true
+ exit for
+ end if
+ end for
+ end if
+ ' Add RAF attributes only if there are other attributes present
+ if hasOtherAdAttributes
+ ev = nrAddRAFAttributes(ev, ctx)
+ else
+ ev = nrAddVideoAttributes(ev)
+ end if
+ ev = nrAddCustomAttributes(ev)
+ if type(attr) = "roAssociativeArray"
+ ev.Append(attr)
+ end if
+ nrRecordEvent(ev)
+end function
+
function nrSendHttpRequest(attr as Object) as Void
domain = nrExtractDomainFromUrl(attr["origUrl"])
attr["domain"] = domain
@@ -305,7 +337,7 @@ function nrSendHttpRequest(attr as Object) as Void
m.num_http_request_counters.AddReplace(domain, 1)
end if
- nrSendCustomEvent("RokuSystem", "HTTP_REQUEST", attr)
+ nrSendSystemEvent("RokuSystem", "HTTP_REQUEST", attr)
end function
function nrSendHttpResponse(attr as Object) as Void
@@ -337,7 +369,7 @@ function nrSendHttpResponse(attr as Object) as Void
end if
end if
- nrSendCustomEvent("RokuSystem", "HTTP_RESPONSE", attr)
+ nrSendSystemEvent("RokuSystem", "HTTP_RESPONSE", attr)
end function
function nrEnableHttpEvents() as Void
@@ -459,9 +491,9 @@ function nrTrackRAF(evtType = invalid as Dynamic, ctx = invalid as Dynamic) as V
else if evtType = "Error"
attr = {}
if ctx.errType <> invalid then attr.AddReplace("adErrorType", ctx.errType)
- if ctx.errCode <> invalid then attr.AddReplace("adErrorCode", ctx.errCode)
- if ctx.errMsg <> invalid then attr.AddReplace("adErrorMsg", ctx.errMsg)
- nrSendRAFEvent("AD_ERROR", ctx, attr)
+ if ctx.errCode <> invalid then attr.AddReplace("errorCode", ctx.errCode)
+ if ctx.errMsg <> invalid then attr.AddReplace("errorName", ctx.errMsg)
+ nrSendErrorEvent("AD_ERROR", ctx, attr)
end if
else if ctx <> invalid and ctx.time <> invalid and ctx.duration <> invalid
'Time progress event
@@ -723,8 +755,9 @@ function nrAddBaseAttributes(ev as Object) as Object
ev.AddReplace("hdmiIsConnected", hdmi.IsConnected())
ev.AddReplace("hdmiHdcpVersion", hdmi.GetHdcpVersion())
dev = CreateObject("roDeviceInfo")
- ev.AddReplace("uuid", dev.GetChannelClientId()) 'GetDeviceUniqueId is deprecated, so we use GetChannelClientId
- ev.AddReplace("device", dev.GetModelDisplayName())
+ ev.AddReplace("deviceUuid", dev.GetChannelClientId()) 'GetDeviceUniqueId is deprecated, so we use GetChannelClientId
+ ev.AddReplace("deviceSize", "xLarge")
+ ev.AddReplace("deviceName", dev.GetModelDisplayName())
ev.AddReplace("deviceGroup", "Roku")
ev.AddReplace("deviceManufacturer", "Roku")
ev.AddReplace("deviceModel", dev.GetModel())
@@ -745,7 +778,7 @@ function nrAddBaseAttributes(ev as Object) as Object
ev.AddReplace("connectionType", dev.GetConnectionType())
'ev.AddReplace("ipAddress", dev.GetExternalIp())
ev.AddReplace("displayType", dev.GetDisplayType())
- ev.AddReplace("displayMode", dev.GetDisplayMode())
+ ev.AddReplace("contentRenditionName", dev.GetDisplayMode())
ev.AddReplace("displayAspectRatio", dev.GetDisplayAspectRatio())
ev.AddReplace("videoMode", dev.GetVideoMode())
ev.AddReplace("graphicsPlatform", dev.GetGraphicsPlatform())
@@ -784,6 +817,9 @@ function nrAddCustomAttributes(ev as Object) as Object
actionName = ev["actionName"]
actionCustomAttr = m.nrCustomAttributes[actionName]
if actionCustomAttr <> invalid then ev.Append(actionCustomAttr)
+ ' Calculate and add elapsed time for the action
+ elapsedTime = nrCalculateElapsedTime(actionName)
+ ev.AddReplace("elapsedTime", elapsedTime)
return ev
end function
@@ -800,6 +836,37 @@ function nrAddCommonHTTPAttr(info as Object) as Object
return attr
end function
+function nrCalculateElapsedTime(actionName as String) as Integer
+ currentTime = CreateObject("roDateTime")
+ currentTimestamp = currentTime.AsSeconds()
+ if m.lastEventTimestamps[actionName] <> invalid
+ timeSinceLastEvent = (currentTimestamp - m.lastEventTimestamps[actionName]) * 1000
+ elapsedTime = timeSinceLastEvent
+ else
+ elapsedTime=0
+ end if
+ m.lastEventTimestamps[actionName] = currentTimestamp
+ return elapsedTime
+end function
+
+function nrCalculateBufferType(actionName as String) as String
+ bufferType = "connection" ' Default buffer type
+ if m.nrTimeSinceStarted = 0
+ m.nrIsInitialBuffering = true
+ bufferType = "initial"
+ else
+ m.nrIsInitialBuffering = false
+ if m.nrLastVideoState = "paused"
+ bufferType = "pause"
+ else if m.nrLastVideoState = "seeking"
+ bufferType = "seek"
+ else
+ bufferType = "connection"
+ end if
+ end if
+ return bufferType
+end function
+
function nrSendHTTPError(info as Object) as Void
attr = nrAddCommonHTTPAttr(info)
domain = attr["domain"]
@@ -811,8 +878,7 @@ function nrSendHTTPError(info as Object) as Void
else
m.num_http_error_counters.AddReplace(domain, 1)
end if
-
- nrSendCustomEvent("RokuSystem", "HTTP_ERROR", attr)
+ nrSendErrorEvent("HTTP_ERROR", attr)
end function
function nrSendHTTPConnect(info as Object) as Void
@@ -827,7 +893,7 @@ function nrSendHTTPConnect(info as Object) as Void
m.num_http_connect_counters.AddReplace(domain, 1)
end if
- if m.http_events_enabled then nrSendCustomEvent("RokuSystem", "HTTP_CONNECT", attr)
+ if m.http_events_enabled then nrSendSystemEvent("RokuSystem", "HTTP_CONNECT", attr)
end function
function nrSendHTTPComplete(info as Object) as Void
@@ -854,7 +920,7 @@ function nrSendHTTPComplete(info as Object) as Void
m.num_http_complete_counters.AddReplace(domain, 1)
end if
- if m.http_events_enabled then nrSendCustomEvent("RokuSystem", "HTTP_COMPLETE", attr)
+ if m.http_events_enabled then nrSendSystemEvent("RokuSystem", "HTTP_COMPLETE", attr)
domain = nrExtractDomainFromUrl(attr["origUrl"])
nrSendMetric("roku.http.complete.connectTime", attr["connectTime"], {"domain": domain})
@@ -868,7 +934,7 @@ function nrSendBandwidth(info as Object) as Void
attr = {
"bandwidth": info["bandwidth"]
}
- nrSendCustomEvent("RokuSystem", "BANDWIDTH_MINUTE", attr)
+ nrSendSystemEvent("RokuSystem", "BANDWIDTH_MINUTE", attr)
end function
'TODO: Testing endpoint. If nrRegion is not US or EU, use it as endpoint. Deprecate the "TEST" region and "m.testServer".
@@ -911,6 +977,30 @@ end function
' Video functions '
'================='
+sub InitializeLastEventTimestamps()
+ m.lastEventTimestamps = {
+ "CONTENT_REQUEST": invalid,
+ "CONTENT_START": invalid,
+ "CONTENT_END": invalid,
+ "CONTENT_PAUSE": invalid,
+ "CONTENT_RESUME": invalid,
+ "CONTENT_BUFFER_START": invalid,
+ "CONTENT_BUFFER_END": invalid,
+ "HTTP_ERROR": invalid,
+ "CONTENT_ERROR": invalid,
+ "AD_ERROR": invalid,
+ "AD_BREAK_START": invalid,
+ "AD_BREAK_END": invalid,
+ "AD_REQUEST": invalid,
+ "AD_START": invalid,
+ "AD_END": invalid,
+ "AD_PAUSE": invalid,
+ "AD_RESUME": invalid,
+ "AD_QUARTILE": invalid,
+ "AD_SKIP": invalid
+ }
+end sub
+
function nrSendPlayerReady() as Void
m.nrTimeSinceTrackerReady = m.nrTimer.TotalMilliseconds()
nrSendVideoEvent("PLAYER_READY")
@@ -957,7 +1047,7 @@ function nrSendBufferStart() as Void
else
m.nrIsInitialBuffering = false
end if
- nrSendVideoEvent("CONTENT_BUFFER_START", {"isInitialBuffering": m.nrIsInitialBuffering})
+ nrSendVideoEvent("CONTENT_BUFFER_START", {"isInitialBuffering": m.nrIsInitialBuffering, "bufferType": nrCalculateBufferType("CONTENT_BUFFER_START")})
nrPausePlaytime()
m.nrPlaytimeSinceLastEvent = invalid
end function
@@ -968,14 +1058,14 @@ function nrSendBufferEnd() as Void
else
m.nrIsInitialBuffering = false
end if
- nrSendVideoEvent("CONTENT_BUFFER_END", {"isInitialBuffering": m.nrIsInitialBuffering})
+ nrSendVideoEvent("CONTENT_BUFFER_END", {"isInitialBuffering": m.nrIsInitialBuffering, "bufferType": nrCalculateBufferType("CONTENT_BUFFER_END")})
nrResumePlaytime()
m.nrPlaytimeSinceLastEvent = CreateObject("roTimespan")
end function
function nrSendError(video as Object) as Void
attr = {
- "errorMessage": video.errorMsg,
+ "errorName": video.errorMsg,
"errorCode": video.errorCode
}
if video.errorStr <> invalid
@@ -987,7 +1077,7 @@ function nrSendError(video as Object) as Void
attr.append({
"errorClipId": video.errorInfo.clipid,
"errorIgnored": video.errorInfo.ignored,
- "errorSource": video.errorInfo.source,
+ "backtrace": video.errorInfo.source,
"errorCategory": video.errorInfo.category,
"errorInfoCode": video.errorInfo.errcode,
"errorDrmInfoCode": video.errorInfo.drmerrcode,
@@ -999,7 +1089,7 @@ function nrSendError(video as Object) as Void
attr.append(getLicenseStatusAttributes(video.licenseStatus))
end if
- nrSendVideoEvent("CONTENT_ERROR", attr)
+ nrSendErrorEvent("CONTENT_ERROR", attr)
end function
function nrSendBackupVideoEvent(actionName as String, attr = invalid) as Void
@@ -1062,6 +1152,7 @@ function nrAddVideoAttributes(ev as Object) as Object
ev.AddReplace("contentDuration", m.nrVideoObject.duration * 1000)
ev.AddReplace("contentPlayhead", m.nrVideoObject.position * 1000)
ev.AddReplace("contentIsMuted", m.nrVideoObject.mute)
+ ev.AddReplace("contentIsFullscreen","true")
streamUrl = nrGenerateStreamUrl()
ev.AddReplace("contentSrc", streamUrl)
'Generate Id from Src (hashing it)
@@ -1120,8 +1211,15 @@ function nrAddVideoAttributes(ev as Object) as Object
if m.nrTotalAdPlaytime > 0
ev.AddReplace("totalAdPlaytime", m.nrTotalAdPlaytime)
end if
-
- return ev
+ contentNode = m.nrVideoObject.content.getChild(m.nrVideoObject.contentIndex)
+ ' Check if contentNode is valid
+ if contentNode <> invalid
+ contentTitle = contentNode.title
+ if contentTitle <> invalid
+ ev.AddReplace("contentTitle", contentTitle)
+ end if
+ end if
+return ev
end function
'=============='
@@ -1170,7 +1268,7 @@ function nrAddRAFAttributes(ev as Object, ctx as Dynamic) as Object
end function
function nrSendRAFEvent(actionName as String, ctx as Dynamic, attr = invalid) as Void
- ev = nrCreateEvent("RokuVideo", actionName)
+ ev = nrCreateEvent("VideoAdAction", actionName)
ev = nrAddVideoAttributes(ev)
ev = nrAddRAFAttributes(ev, ctx)
ev = nrAddCustomAttributes(ev)
diff --git a/components/NewRelicAgent/NRAgent.xml b/components/NewRelicAgent/NRAgent.xml
index ac5a5b3..d78dcca 100644
--- a/components/NewRelicAgent/NRAgent.xml
+++ b/components/NewRelicAgent/NRAgent.xml
@@ -23,9 +23,10 @@
-
+
+
diff --git a/components/VideoScene.brs b/components/VideoScene.brs
index c12d8d4..5f81a80 100644
--- a/components/VideoScene.brs
+++ b/components/VideoScene.brs
@@ -3,6 +3,8 @@
sub init()
print "INIT VideoScene"
m.top.setFocus(true)
+ 'Uncomment the following line to set a user ID
+ 'setUserId("TEST_USER")
end sub
function nrRefUpdated()
@@ -45,6 +47,11 @@ function updateCustomAttr() as Void
'Set a list of custom attributes to CONTENT_HEARTBEAT actions
dict = {"key0":"val0", "key1":"val1"}
nrSetCustomAttributeList(m.nr, dict, "CONTENT_HEARTBEAT")
+ nrSetCustomAttribute(m.nr,"enduser.id", m.userId)
+end function
+
+function setUserId(userId as String) as Void
+ m.userId = userId
end function
function setupSingleVideo() as void
diff --git a/source/Main.brs b/source/Main.brs
index e94c9f9..33a9b58 100644
--- a/source/Main.brs
+++ b/source/Main.brs
@@ -40,7 +40,7 @@ sub Main(aa as Object)
'Send APP_STARTED event
nrAppStarted(m.nr, aa)
'Send a custom system
- nrSendSystemEvent(m.nr, "TEST_ACTION")
+ nrSendSystemEvent(m.nr, "RokuSystem","TEST_ACTION")
'Define multiple domain substitutions
nrAddDomainSubstitution(m.nr, "^www\.google\.com$", "Google COM")
diff --git a/source/NewRelicAgent.brs b/source/NewRelicAgent.brs
index e75b6e0..55e8c80 100644
--- a/source/NewRelicAgent.brs
+++ b/source/NewRelicAgent.brs
@@ -123,26 +123,26 @@ function nrSceneLoaded(nr as Object, sceneName as String) as Void
nr.callFunc("nrSceneLoaded", sceneName)
end function
-' Send a custom event.
+' Send a system event, type RokuSystem.
'
' @param nr New Relic Agent object.
' @param eventType Event type.
' @param actionName Action name.
' @param attr (optional) Attributes associative array.
-function nrSendCustomEvent(nr as Object, eventType as String, actionName as String, attr = invalid as Object) as Void
- nr.callFunc("nrSendCustomEvent", eventType, actionName, attr)
+function nrSendSystemEvent(nr as Object, eventType as String, actionName as String, attr = invalid as Object) as Void
+ nr.callFunc("nrSendSystemEvent", eventType, actionName, attr)
end function
-' Send a system event, type RokuSystem.
+' Send a custom event, type VideoCustomAction.
'
' @param nr New Relic Agent object.
' @param actionName Action name.
' @param attr (optional) Attributes associative array.
-function nrSendSystemEvent(nr as Object, actionName as String, attr = invalid) as Void
- nr.callFunc("nrSendSystemEvent", actionName, attr)
+function nrSendCustomEvent(nr as Object, actionName as String, attr = invalid as Object) as Void
+ nr.callFunc("nrSendCustomEvent", actionName, attr)
end function
-' Send a video event, type RokuVideo.
+' Send a video event, type VideoAction.
'
' @param nr New Relic Agent object.
' @param actionName Action name.