Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  plugin-load-profile.ts

  Sprache: JAVA
 

Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/**
 * Shared probe primitives for plugin-load profiling.
 *
 * All plugin-load probes — across `src/plugins/loader.ts`,
 * `src/plugins/source-loader.ts`, and `src/plugin-sdk/channel-entry-contract.ts`
 * — emit a single line per measurement to stderr in the form:
 *
 *     [plugin-load-profile] phase=<X> plugin=<Y> elapsedMs=<N> [extras…] source=<S>
 *
 * The same `OPENCLAW_PLUGIN_LOAD_PROFILE=1` env flag activates all probes.
 *
 * Tooling that scrapes these lines (e.g. PERF-STARTUP-PLAN.md profiling
 * methodology) depends on the field order being:
 *
 *   1. `phase=`
 *   2. `plugin=`
 *   3. `elapsedMs=`
 *   4. any caller-supplied extras (in declaration order)
 *   5. `source=` last
 *
 * Keep this contract stable — downstream parsers rely on it.
 */

export function shouldProfilePluginLoader(): boolean {
  return process.env.OPENCLAW_PLUGIN_LOAD_PROFILE === "1";
}

/**
 * An ordered list of `[key, value]` pairs appended between `elapsedMs=` and
 * `source=` on the emitted log line. Ordered tuples (not a record) so that
 * scrapers see a deterministic field order regardless of object iteration
 * quirks.
 */
export type PluginLoadProfileExtras = ReadonlyArray<readonly [string, number | string]>;

/** Per-call scope: which plugin and which source path the probe is for. */
export type PluginLoadProfileScope = {
  pluginId?: string;
  source: string;
};

/**
 * A scope-bound profiler — call it with a `phase` + sync `run` to time and
 * emit a `[plugin-load-profile]` line that already includes the bound
 * `pluginId` and `source`. Build one with `createProfiler(scope)`.
 */
export type PluginLoadProfiler = <T>(
  phase: string,
  run: () => T,
  extras?: PluginLoadProfileExtras,
) => T;

/**
 * Render a `[plugin-load-profile]` line. Exported so that callers needing
 * custom timing splits (e.g. dual-timer probes in
 * `channel-entry-contract.ts`) can build their own start/stop logic and
 * still emit a line in the canonical format.
 */
export function formatPluginLoadProfileLine(params: {
  phase: string;
  pluginId?: string;
  source: string;
  elapsedMs: number;
  extras?: PluginLoadProfileExtras;
}): string {
  const extras = (params.extras ?? [])
    .map(([k, v]) => `${k}=${typeof v === "number" ? v.toFixed(1) : v}`)
    .join(" ");
  const extrasFragment = extras ? ` ${extras}` : "";
  return (
    `[plugin-load-profile] phase=${params.phase} plugin=${params.pluginId ?? "(core)"}` +
    ` elapsedMs=${params.elapsedMs.toFixed(1)}${extrasFragment} source=${params.source}`
  );
}

/**
 * Time a single synchronous step and emit a `[plugin-load-profile]` line.
 * Use this when you only need to wrap one call:
 *
 * ```ts
 * const mod = withProfile(
 *   { pluginId: id, source },
 *   "phase-name",
 *   () => loadIt(),
 * );
 * ```
 *
 * For repeated calls that share the same `{ pluginId, source }` scope,
 * prefer `createProfiler(scope)` and call the returned profiler.
 *
 * When the env flag is unset, this runs `run()` directly with no timing
 * overhead. Errors propagate naturally; the log line is still emitted via
 * `try { … } finally { … }`.
 */
export function withProfile<T>(
  scope: PluginLoadProfileScope,
  phase: string,
  run: () => T,
  extras?: PluginLoadProfileExtras,
): T {
  if (!shouldProfilePluginLoader()) {
    return run();
  }
  const startMs = performance.now();
  try {
    return run();
  } finally {
    const elapsedMs = performance.now() - startMs;
    console.error(
      formatPluginLoadProfileLine({
        phase,
        pluginId: scope.pluginId,
        source: scope.source,
        elapsedMs,
        extras,
      }),
    );
  }
}

/**
 * Build a scope-bound profiler. Useful when several consecutive steps share
 * the same `{ pluginId, source }`:
 *
 * ```ts
 * const profile = createProfiler({ pluginId: id, source: importMetaUrl });
 * profile("phase-a", () => stepA());
 * const v = profile("phase-b", () => stepB());
 * ```
 *
 * Each call has the same semantics as `withProfile(scope, phase, run)`.
 */
export function createProfiler(scope: PluginLoadProfileScope): PluginLoadProfiler {
  return (phase, run, extras) => withProfile(scope, phase, run, extras);
}

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet am  2026-04-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge