Portal Community

Route and Component

// Route in App.tsx
<Route path="/hooks" element={<HooksPage />} />

// HooksPage source: packages/app-pages-react/src/HooksPage.tsx
export function HooksPage(): React.ReactElement {
  return <HooksMonitor
    className="page-container"
    showSettings={true}
    pollInterval={500}
    maxLogs={100}
  />
}

// HooksMonitor from: @edge-stream/observability-react

HooksMonitor — How It Works

// HooksMonitor polls LoggingService every 500ms:
useEffect(() => {
  const interval = setInterval(() => {
    const logs = loggingService.getRecentLogs(maxLogs);  // maxLogs = 100
    setLogs(logs);
  }, pollInterval);  // pollInterval = 500ms

  return () => clearInterval(interval);
}, [maxLogs, pollInterval]);

// Flattens hook logs from all message activity logs:
const allHookLogs = logs.flatMap((msg) => msg.hookLogs || []);

// Stats computed from allHookLogs:
const stats = {
  total:   allHookLogs.length,
  success: allHookLogs.filter((h) => h.success).length,
  failed:  allHookLogs.filter((h) => !h.success).length,
};

HookLog Entry Fields

FieldTypeDescription
hookNamestringName of the hook class (e.g. HookActivityLogger, ValidationHook)
prioritynumberExecution priority — lower number runs first
successbooleanWhether the hook returned HookResult.Continue or threw
durationMsnumberHook execution time in milliseconds
resultHookResultContinue, Stop, StopAndRespond, Pause
errorstring?Error message if the hook threw or returned a failure result
topicstringThe message topic that triggered this hook invocation
messageIdstringCorrelates this hook log to a specific envelope via IEnvelope.meta.id

Filter by Hook Name

// The filter input performs case-insensitive substring match on hookName:
const filtered = allHookLogs.filter((log) =>
  log.hookName.toLowerCase().includes(filterText.toLowerCase())
);

// Example filters:
// "validation"      → shows only ValidationHook invocations
// "decrypt"         → shows only DecryptHook invocations
// "logger"          → shows only HookActivityLogger invocations
// ""                → shows all (no filter)

Settings Panel

When showSettings={true}, a settings panel allows adjusting poll interval and max log count without reloading:

// Settings exposed when showSettings is true:
// Poll Interval (ms) — default 500
// Max Logs           — default 100

// Changing these updates the useEffect interval and the getRecentLogs() call limit.
// Setting max logs to 0 shows all logs in the ring buffer (may be slow on high-traffic servers).

Standard Hook Priority Order

The Hooks Panel clearly shows the priority order in which hooks execute. In a standard EdgeStream pipeline:

PriorityHookPurpose
5HookActivityLoggerRecords message activity — must run first to capture all hook results
90DecryptHookDecrypts encrypted envelope body
95VerifySignatureHookValidates message signature
100ValidationHookSchema validation against registered message types
110NormalizationHookNormalizes envelope structure and topic casing
120–199Pre-processing hooksCustom hooks: rate limiting, authentication enrichment, deduplication
200–299Processing hooksDomain hooks: WorkflowEventPlugin, AgentMessagePlugin, UiActionPlugin
300+Post-processing hooksAudit, forwarding, external platform hooks (Splunk, Datadog)

Hooks Reference Panel

The Hooks Reference at /hooks-reference shows all registered hook classes with documentation. This is read-only; it lists every hook available in the hook library with its priority, description, and configuration options:

// Route in App.tsx
<Route path="/hooks-reference" element={<HooksReferencePage />} />

// HooksReferencePage: packages/app-pages-react/src/HooksReferencePage.tsx
// Sidebar label in App.tsx: "Available Hooks"

// Also available at /help/hooks:
<Route path="/help/hooks" element={<HooksLibraryPage />} />
// HooksLibraryPage: packages/app-pages-react/src/HooksLibraryPage.tsx

Enabling Hook Logging in Your App

To populate the Hooks Panel (and Activity Stream), you must add HookActivityLogger to your pipeline. Without it, no hook logs are written to the in-memory ring buffer.

import { HookActivityLogger } from 'edge-stream-js';

// Add as the first hook (priority 5) so it captures all subsequent hook results:
server.incomingPipeline.addHook(new HookActivityLogger());

// HookActivityLogger is included automatically in EdgeStream DevTools.
// In your own app: add it manually during development, remove for production
// (or replace with an external observability hook from observability-hooks-js).
Production Consideration HookActivityLogger keeps an in-memory ring buffer of message activity. On high-throughput servers, this can consume memory. Set a reasonable buffer size or disable it in production and use an external platform hook (DatadogHook, SplunkLogHook, etc.) instead.