49 lines · 1.4 KB · TypeScript
RawDownload
import * as Cause from "effect/Cause";import * as Exit from "effect/Exit"; export type MetricAttributeValue = string;export type MetricAttributes = Readonly<Record<string, MetricAttributeValue>>;export type ObservabilityOutcome = "success" | "failure" | "interrupt"; export function compactMetricAttributes(  attributes: Readonly<Record<string, unknown>>,): MetricAttributes {  return Object.fromEntries(    Object.entries(attributes).flatMap(([key, value]) => {      if (value === undefined || value === null) {        return [];      }      if (typeof value === "string") {        return [[key, value]];      }      if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {        return [[key, String(value)]];      }      return [];    }),  );} export function outcomeFromExit(exit: Exit.Exit<unknown, unknown>): ObservabilityOutcome {  if (Exit.isSuccess(exit)) {    return "success";  }  return Cause.hasInterruptsOnly(exit.cause) ? "interrupt" : "failure";} export function normalizeModelMetricLabel(model: string | null | undefined): string | undefined {  const normalized = model?.trim().toLowerCase();  if (!normalized) {    return undefined;  }  if (normalized.includes("gpt")) {    return "gpt";  }  if (normalized.includes("claude")) {    return "claude";  }  if (normalized.includes("gemini")) {    return "gemini";  }  return "other";}