Skip to content

Trace timeline ​

<scope-trace> displays span timing, hierarchy, viewport controls and pinned details. The lightweight createTrace factory accepts the same document.

Trace

Loading interactive chart…

Parallel spans with exact nanosecond timestamps.

Hover to read · Click to select

<scope-trace id="chart">
  <nav slot="toolbar" class="chart-controls" aria-label="Chart controls"></nav>
</scope-trace>

<script type="module">
  import '@scopedb/scopeview/register';
  import chartDocument from './chart.js';

  const chart = document.querySelector('#chart');
  const toolbar = chart.querySelector('[slot="toolbar"]');
  const labels = {
  "zoom-in": "+",
  "zoom-out": "−"
};

  function renderToolbar() {
    const controls = chart.controls;
    for (const button of toolbar.querySelectorAll('[data-action]')) {
      if (!controls.some((control) => control.action === button.dataset.action)) button.remove();
    }
    for (const control of controls) {
      let button = toolbar.querySelector('[data-action="' + control.action + '"]');
      if (!button) {
        button = document.createElement('button');
        button.type = 'button';
        button.dataset.action = control.action;
        button.addEventListener('click', () => chart.performAction(control.action));
        toolbar.append(button);
      }
      button.textContent = labels[control.action] || control.label;
      button.setAttribute('aria-label', control.label);
      button.disabled = control.disabled;
      if (control.expanded !== undefined) button.setAttribute('aria-expanded', String(control.expanded));
      else button.removeAttribute('aria-expanded');
    }
  }

  chart.addEventListener('scope-controls-change', renderToolbar);
  chart.configure({
  dismissOnOutside: false
});
  chart.document = chartDocument;
  renderToolbar();
</script>

<style>
  #chart {
    color-scheme: light;
    --scope-chart-height: 260px;
    --color-text-primary: #202b38;
    --color-text-secondary: #657286;
    --color-text-tertiary: #7b8798;
    --color-surface: #ffffff;
    --color-border: #dce3eb;
    --color-border-light: #edf0f4;
  }
.chart-controls[slot="toolbar"] {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  margin-top: 12px;
  padding: 8px 0;
  border-top: 1px solid var(--color-border-light);
  font-size: var(--scope-chart-tooltip-font-size, 12px);
  line-height: 1.4;
}
.chart-controls[slot="toolbar"] button {
  border: 0;
  border-radius: var(--radius-chart-control, 4px);
  padding: 5px 8px;
  font: inherit;
  color: var(--color-text-secondary);
  background: transparent;
  cursor: pointer;
}
.chart-controls[slot="toolbar"] button:hover:not(:disabled),
.chart-controls[slot="toolbar"] button[aria-expanded="true"] {
  color: var(--color-text-primary);
  background: var(--color-surface-hover);
}
.chart-controls[slot="toolbar"] button:disabled {
  opacity: 0.45;
  cursor: default;
}
.chart-controls[slot="toolbar"] button:focus-visible {
  outline: 2px solid var(--color-text-brand, #0876dd);
  outline-offset: 1px;
}

</style>

Copy the example ​

Follow Run an example for project setup and the development server. Save this example's index.html, chart.js and data.json together. Replace the span array in data.json; keep the trace document's configuration in chart.js. The mount file includes a custom toolbar. Remove its slot="toolbar" content to use the built-in controls.

Each span needs id, name, startTimeNs and endTimeNs. Nanoseconds are integer strings. Use parentId for parentage, service for color identity and status: 'error' for failures. Set coverage to describe the supplied snapshot. See trace documents for exact timing, warnings and limits.

Read and navigate ​

Hover for the compact duration reading; click or press Enter to pin complete details below the controls. Another span stays hoverable. Arrow keys inspect and Home/End jump; Escape dismisses. Drag pans, Ctrl/Command-wheel zooms, and the toolbar offers zoom/reset actions. The component scrolls rows when the hierarchy exceeds its height.

To reveal an initial span, register a one-time ready listener before assigning the document:

ts
import type { ScopeTraceElement } from '@scopedb/scopeview/element';

export function revealSpan(chart: ScopeTraceElement, id: string) {
  chart.addEventListener('scope-ready', () => chart.focusNode(id, { pin: true }), { once: true });
}

Inspection events contain original spans in detail.sources. Uncovered time reflects supplied direct children, so partial traces cannot establish complete exclusive time. See component API for viewport/collapse methods and view state for preserving a reading across updates.