Skip to content

Resource Hook Integration Guide (SDK version >= 3.3.0)

Overview

Resource Hook allows you to append request-level business context to automatically collected resource events.

Use cases:

  • Writing business context before the request is sent
  • Adding additional fields after the response is received
  • Ensuring the final resource event includes both sets of data

This capability supports both fetch and XMLHttpRequest.

How It Works

  1. Create a tracker ID with createResourceTrackerId()
  2. Attach this ID to the request header x-rum-resource-id
  3. Use setResourceContext() to write pre-request context
  4. Use appendResourceContext() to append post-response context
  5. Call finishResource() to trigger the final tracked resource upload

If the request does not carry x-rum-resource-id, the SDK falls back to the normal automatic resource collection flow.

Public API

const resourceId = DATAFLUX_RUM.createResourceTrackerId()

DATAFLUX_RUM.setResourceContext(resourceId, { order_id: '123' })
DATAFLUX_RUM.appendResourceContext(resourceId, { result: 'success' })
DATAFLUX_RUM.finishResource(resourceId)
DATAFLUX_RUM.getResource(resourceId)

API semantics:

  • createResourceTrackerId() Creates a new tracker ID
  • setResourceContext(resourceId, context) Overwrites the current tracker's context
  • appendResourceContext(resourceId, context) Appends additional fields to the current tracker's context
  • finishResource(resourceId) Signals that the tracked resource is ready to complete. If the request has already finished, the resource is immediately uploaded; if not, the SDK waits until the request completes before uploading
  • getResource(resourceId) Returns a snapshot of the current tracker, primarily for debugging

Fetch Example

const resourceId = window.DATAFLUX_RUM.createResourceTrackerId()

window.DATAFLUX_RUM.setResourceContext(resourceId, {
  order_id: '123',
  scene: 'checkout'
})

fetch('/api/order/detail', {
  headers: {
    'x-rum-resource-id': resourceId
  }
})
  .then((response) => {
    window.DATAFLUX_RUM.appendResourceContext(resourceId, {
      result: 'success',
      response_status: response.status
    })
    window.DATAFLUX_RUM.finishResource(resourceId)
    return response
  })
  .catch((error) => {
    window.DATAFLUX_RUM.appendResourceContext(resourceId, {
      result: 'error',
      error_message: error.message
    })
    window.DATAFLUX_RUM.finishResource(resourceId)
    throw error
  })

XHR Example

const resourceId = window.DATAFLUX_RUM.createResourceTrackerId()

window.DATAFLUX_RUM.setResourceContext(resourceId, {
  order_id: '123',
  scene: 'checkout'
})

const xhr = new XMLHttpRequest()
xhr.open('GET', '/api/order/detail', true)
xhr.setRequestHeader('x-rum-resource-id', resourceId)

xhr.addEventListener('load', () => {
  window.DATAFLUX_RUM.appendResourceContext(resourceId, {
    result: 'success',
    response_status: xhr.status
  })
  window.DATAFLUX_RUM.finishResource(resourceId)
})

xhr.addEventListener('error', () => {
  window.DATAFLUX_RUM.appendResourceContext(resourceId, {
    result: 'error',
    error_message: 'xhr_error'
  })
  window.DATAFLUX_RUM.finishResource(resourceId)
})

xhr.send()

Trace Scenario Example

If the same request also needs to inject a trace ID, keep x-rum-resource-id and ensure the request URL is already configured in the tracing allowlist. The CDN example below uses the default ddtrace; to explicitly specify a different type, refer to the traceType description in the initialization parameters.

window.DATAFLUX_RUM.init({
  // ...
  allowedTracingUrls: [window.location.origin]
})

Then send the tracked request as usual:

const resourceId = window.DATAFLUX_RUM.createResourceTrackerId()

window.DATAFLUX_RUM.setResourceContext(resourceId, {
  scene: 'checkout'
})

fetch('/api/order/detail', {
  headers: {
    'x-rum-resource-id': resourceId
  }
})
  .then((response) => {
    window.DATAFLUX_RUM.appendResourceContext(resourceId, {
      trace_expected: 'true',
      response_status: response.status
    })
    window.DATAFLUX_RUM.finishResource(resourceId)
    return response
  })

The rawRumEvent._gc in the final tracker snapshot may contain traceId and spanId.

Debugging

You can inspect the current tracker snapshot at any time:

const snapshot = window.DATAFLUX_RUM.getResource(resourceId)
console.log(snapshot)

Typical snapshot structure:

{
  trackerId: 'uuid',
  status: 'request_collected',
  context: {
    order_id: '123',
    result: 'success'
  },
  resource: {
    type: 'fetch',
    url: '/api/order/detail',
    method: 'GET',
    status: 200
  },
  rawRumEvent: {
    type: 'resource',
    _gc: {
      traceId: '...',
      spanId: '...'
    }
  }
}

Possible status values:

  • created
  • request_collected
  • finished
  • flushed
  • timeout_flushed
  • cleared

Timeout Behavior

If the application does not call finishResource(), the SDK automatically flushes the tracked resource after 30s.

A common misunderstanding:

  • This 30s starts counting after the request completes
  • Not from the start of the request

The actual timeline:

  1. Request starts
  2. Request completes
  3. SDK associates it with the resource via x-rum-resource-id
  4. If finishResource() has not been called by then, the SDK waits at most 30s
  5. After the timeout, the resource is uploaded with status timeout_flushed

This prevents tracked requests from remaining pending indefinitely while still giving application code a window to attach post-response context after the request finishes.

Timeline Details

  • If finishResource() is called before the request completes, the SDK does not upload immediately. It marks the tracker as finished and waits until the request actually completes to flush.
  • If finishResource() is called after the request completes, the SDK flushes immediately.
  • If finishResource() is never called, the SDK follows the "wait 30s after request completion and then auto-flush" logic described above.

Notes

  • Business requests must allow the custom header x-rum-resource-id
  • If the request does not carry this header, it automatically falls back to normal resource collection
  • If the header contains a tracker ID that does not exist, it also falls back to normal resource collection
  • getResource() is primarily for debugging and should not be relied upon as a business logic dependency

Feedback

Is this page helpful?