summaryrefslogtreecommitdiff
path: root/u
diff options
context:
space:
mode:
authorElizabeth <me@liz.coffee>2025-06-02 18:07:31 -0700
committerElizabeth <me@liz.coffee>2025-06-02 18:07:31 -0700
commitd9c418425b035f00c950e6a83df9470d7af80413 (patch)
tree07c7445d7800a6ac6a3cf6b404ebcf4e27aad245 /u
parent98f5c21aa65bbbca01a186a754249335b4afef57 (diff)
downloadci-d9c418425b035f00c950e6a83df9470d7af80413.tar.gz
ci-d9c418425b035f00c950e6a83df9470d7af80413.zip
Use log traceable in metric traceable
Diffstat (limited to 'u')
-rw-r--r--u/fn/either.ts188
-rw-r--r--u/process/argv.ts10
-rw-r--r--u/server/activity/fourohfour.ts9
-rw-r--r--u/server/request.ts11
-rw-r--r--u/server/response.ts10
-rw-r--r--u/trace/itrace.ts46
-rw-r--r--u/trace/logger.ts4
-rw-r--r--u/trace/metrics.ts4
-rw-r--r--u/trace/trace.ts32
9 files changed, 158 insertions, 156 deletions
diff --git a/u/fn/either.ts b/u/fn/either.ts
index 124557c..bf90f16 100644
--- a/u/fn/either.ts
+++ b/u/fn/either.ts
@@ -4,115 +4,111 @@ type IEitherTag = "IEither";
const iEitherTag: IEitherTag = "IEither";
export interface _Either<LeftT, RightT, T> {
- readonly isLeft: LeftT;
- readonly isRight: RightT;
- readonly value: T;
+ readonly isLeft: LeftT;
+ readonly isRight: RightT;
+ readonly value: T;
}
export type Left<E> = _Either<true, false, E>;
export type Right<T> = _Either<false, true, T>;
export interface IEither<E, T> {
- readonly _tag: IEitherTag;
-
- mapBoth: <_E, _T>(
- errBranch: Mapper<E, _E>,
- okBranch: Mapper<T, _T>,
- ) => IEither<_E, _T>;
- fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T;
- moveRight: <_T>(t: _T) => IEither<E, _T>;
- mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
- mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
- flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
- flatMapAsync: <_T>(
- mapper: Mapper<T, Promise<IEither<E, _T>>>,
- ) => Promise<IEither<E, _T>>;
+ readonly _tag: IEitherTag;
+
+ mapBoth: <_E, _T>(
+ errBranch: Mapper<E, _E>,
+ okBranch: Mapper<T, _T>,
+ ) => IEither<_E, _T>;
+ fold: <_T>(folder: Mapper<Left<E> | Right<T>, _T>) => _T;
+ moveRight: <_T>(t: _T) => IEither<E, _T>;
+ mapRight: <_T>(mapper: Mapper<T, _T>) => IEither<E, _T>;
+ mapLeft: <_E>(mapper: Mapper<E, _E>) => IEither<_E, T>;
+ flatMap: <_T>(mapper: Mapper<T, IEither<E, _T>>) => IEither<E, _T>;
+ flatMapAsync: <_T>(
+ mapper: Mapper<T, Promise<IEither<E, _T>>>,
+ ) => Promise<IEither<E, _T>>;
}
export class Either<E, T> implements IEither<E, T> {
- private readonly self: Left<E> | Right<T>;
-
- private constructor(
- err?: E,
- ok?: T,
- public readonly _tag: IEitherTag = iEitherTag,
- ) {
- this.self = <Left<E> | Right<T>>{
- isLeft: typeof err !== "undefined",
- isRight: typeof ok !== "undefined",
- value: typeof err !== "undefined" ? err : ok!,
- };
+ private readonly self: Left<E> | Right<T>;
+
+ private constructor(
+ err?: E,
+ ok?: T,
+ public readonly _tag: IEitherTag = iEitherTag,
+ ) {
+ this.self = <Left<E> | Right<T>>{
+ isLeft: typeof err !== "undefined",
+ isRight: typeof ok !== "undefined",
+ value: typeof err !== "undefined" ? err : ok!,
+ };
+ }
+
+ public moveRight<_T>(t: _T) {
+ return this.mapRight(() => t);
+ }
+
+ public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T {
+ return folder(this.self);
+ }
+
+ public mapBoth<_E, _T>(
+ errBranch: Mapper<E, _E>,
+ okBranch: Mapper<T, _T>,
+ ): IEither<_E, _T> {
+ if (this.self.isLeft) return Either.left(errBranch(this.self.value));
+ return Either.right(okBranch(this.self.value));
+ }
+
+ public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
+ if (this.self.isRight) return mapper(this.self.value);
+ return Either.left<E, _T>(this.self.value);
+ }
+
+ public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
+ if (this.self.isRight) return Either.right<E, _T>(mapper(this.self.value));
+ return Either.left<E, _T>(this.self.value);
+ }
+
+ public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
+ if (this.self.isLeft) return Either.left<_E, T>(mapper(this.self.value));
+ return Either.right<_E, T>(this.self.value);
+ }
+
+ public async flatMapAsync<_T>(
+ mapper: Mapper<T, Promise<IEither<E, _T>>>,
+ ): Promise<IEither<E, _T>> {
+ if (this.self.isLeft) {
+ return Promise.resolve(Either.left<E, _T>(this.self.value));
}
-
- public moveRight<_T>(t: _T) {
- return this.mapRight(() => t);
- }
-
- public fold<_T>(folder: Mapper<Left<E> | Right<T>, _T>): _T {
- return folder(this.self);
- }
-
- public mapBoth<_E, _T>(
- errBranch: Mapper<E, _E>,
- okBranch: Mapper<T, _T>,
- ): IEither<_E, _T> {
- if (this.self.isLeft) return Either.left(errBranch(this.self.value));
- return Either.right(okBranch(this.self.value));
- }
-
- public flatMap<_T>(mapper: Mapper<T, IEither<E, _T>>): IEither<E, _T> {
- if (this.self.isRight) return mapper(this.self.value);
- return Either.left<E, _T>(this.self.value);
- }
-
- public mapRight<_T>(mapper: Mapper<T, _T>): IEither<E, _T> {
- if (this.self.isRight)
- return Either.right<E, _T>(mapper(this.self.value));
- return Either.left<E, _T>(this.self.value);
- }
-
- public mapLeft<_E>(mapper: Mapper<E, _E>): IEither<_E, T> {
- if (this.self.isLeft)
- return Either.left<_E, T>(mapper(this.self.value));
- return Either.right<_E, T>(this.self.value);
- }
-
- public async flatMapAsync<_T>(
- mapper: Mapper<T, Promise<IEither<E, _T>>>,
- ): Promise<IEither<E, _T>> {
- if (this.self.isLeft) {
- return Promise.resolve(Either.left<E, _T>(this.self.value));
- }
- return await mapper(this.self.value).catch((err) =>
- Either.left<E, _T>(err),
- );
- }
-
- static left<E, T>(e: E): IEither<E, T> {
- return new Either<E, T>(e, undefined);
- }
- static right<E, T>(t: T): IEither<E, T> {
- return new Either<E, T>(undefined, t);
- }
-
- static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
- try {
- return Either.right<E, T>(s());
- } catch (e) {
- return Either.left<E, T>(e as E);
- }
+ return await mapper(this.self.value).catch((err) =>
+ Either.left<E, _T>(err),
+ );
+ }
+
+ static left<E, T>(e: E): IEither<E, T> {
+ return new Either<E, T>(e, undefined);
+ }
+ static right<E, T>(t: T): IEither<E, T> {
+ return new Either<E, T>(undefined, t);
+ }
+
+ static fromFailable<E, T>(s: Supplier<T>): IEither<E, T> {
+ try {
+ return Either.right<E, T>(s());
+ } catch (e) {
+ return Either.left<E, T>(e as E);
}
+ }
- static async fromFailableAsync<E, T>(
- s: Promise<T>,
- ): Promise<IEither<E, T>> {
- try {
- return Either.right<E, T>(await s);
- } catch (e) {
- return Either.left<E, T>(e as E);
- }
+ static async fromFailableAsync<E, T>(s: Promise<T>): Promise<IEither<E, T>> {
+ try {
+ return Either.right<E, T>(await s);
+ } catch (e) {
+ return Either.left<E, T>(e as E);
}
+ }
}
export const isEither = <E, T>(o: unknown): o is IEither<E, T> => {
- return isObject(o) && "_tag" in o && o._tag === "IEither";
+ return isObject(o) && "_tag" in o && o._tag === "IEither";
};
diff --git a/u/process/argv.ts b/u/process/argv.ts
index 7190531..8e85477 100644
--- a/u/process/argv.ts
+++ b/u/process/argv.ts
@@ -37,11 +37,11 @@ export const argv = <K extends string, V extends string>(
.map((arg) => [arg, getArg(arg, argv)] as [K, IEither<Error, V>])
.map(([arg, specified]): [K, IEither<Error, V>] => [
arg,
- specified.fold(({ isLeft, isRight, value}): IEither<Error, V> => {
- if (isRight) {
- return Either.right(value);
- }
- const hasDefaultVal = isLeft && defaultArgs && arg in defaultArgs;
+ specified.fold(({ isLeft, isRight, value }): IEither<Error, V> => {
+ if (isRight) {
+ return Either.right(value);
+ }
+ const hasDefaultVal = isLeft && defaultArgs && arg in defaultArgs;
if (hasDefaultVal) {
return Either.right(defaultArgs[arg]!);
}
diff --git a/u/server/activity/fourohfour.ts b/u/server/activity/fourohfour.ts
index ed8c7eb..33cfe5f 100644
--- a/u/server/activity/fourohfour.ts
+++ b/u/server/activity/fourohfour.ts
@@ -7,12 +7,13 @@ import {
} from "@emprespresso/pengueno";
const messages = [
- "D: Meow-t found! Your API call ran away!",
- "404-bidden! But like...in a cute way >:3 !",
- ":o Your data went on a paw-sible vacation!",
+ "D: meow-t found! your api call ran away!",
+ "404-bidden! but like...in a cute way >:3 !",
+ ":< your data went on a paw-sible vacation!",
"uwu~ not found, but found our hearts instead!",
];
-const randomFourOhFour = () => messages[Math.random() * messages.length];
+const randomFourOhFour = () =>
+ messages[Math.floor(Math.random() * messages.length)];
export interface IFourOhFourActivity {
fourOhFour: IActivity;
diff --git a/u/server/request.ts b/u/server/request.ts
index c857f88..5dd9d7b 100644
--- a/u/server/request.ts
+++ b/u/server/request.ts
@@ -1,4 +1,5 @@
-import { LogMetricTraceable } from "@emprespresso/pengueno";
+import { LogMetricTraceable, LogTraceable } from "@emprespresso/pengueno";
+import { TraceUtil } from "../trace/util.ts";
const greetings = [
"hewwo :D",
@@ -39,9 +40,11 @@ export class PenguenoRequest extends Request {
const id = crypto.randomUUID();
const url = new URL(request.url);
const { pathname } = url;
- const traceSupplier = () => `[${id} <- ${request.method}'d @ ${pathname}]`;
- return LogMetricTraceable.from(
+ const logTraceable = LogTraceable.of(
new PenguenoRequest(url, { ...request }, id, new Date()),
- ).bimap((_request) => [_request.get(), traceSupplier]);
+ ).bimap(
+ TraceUtil.withTrace(`Id=${id} Method=${request.method} Path=${pathname}`),
+ );
+ return LogMetricTraceable.ofLogTraceable(logTraceable);
}
}
diff --git a/u/server/response.ts b/u/server/response.ts
index 4531157..629dbb5 100644
--- a/u/server/response.ts
+++ b/u/server/response.ts
@@ -28,12 +28,12 @@ const getResponse = (
};
};
-const ResponseCodeMetrics = [1, 2, 3, 4, 5].map((x) =>
+const ResponseCodeMetrics = [0, 1, 2, 3, 4, 5].map((x) =>
Metric.fromName(`response.${x}xx`),
);
export const getResponseMetric = (status: number) => {
- const index = Math.floor(status / 100) + 1;
- return ResponseCodeMetrics[index] ?? ResponseCodeMetrics[5 - 1];
+ const index = Math.floor(status / 100);
+ return ResponseCodeMetrics[index] ?? ResponseCodeMetrics[5];
};
export class PenguenoResponse extends Response {
@@ -67,7 +67,9 @@ export class JsonResponse extends PenguenoResponse {
super(
req,
JSON.stringify(
- e.fold(({ isLeft, value }) => (isLeft ? { error: value } : { ok: value })),
+ e.fold(({ isLeft, value }) =>
+ isLeft ? { error: value } : { ok: value },
+ ),
),
optsWithJsonContentType,
);
diff --git a/u/trace/itrace.ts b/u/trace/itrace.ts
index ed707c5..35164b5 100644
--- a/u/trace/itrace.ts
+++ b/u/trace/itrace.ts
@@ -9,29 +9,29 @@ export interface ITrace<TraceWith> {
}
export type ITraceableTuple<T, TraceWith> = [T, BaseTraceWith | TraceWith];
-export type ITraceableMapper<T, U, TraceWith, W = ITraceable<T, TraceWith>> = (
+export type ITraceableMapper<T, _T, TraceWith, W = ITraceable<T, TraceWith>> = (
w: W,
-) => U;
+) => _T;
export interface ITraceable<T, Trace = BaseTraceWith> {
readonly trace: ITrace<Trace>;
get: Supplier<T>;
- move: <U>(u: U) => ITraceable<U, Trace>;
- map: <U>(mapper: ITraceableMapper<T, U, Trace>) => ITraceable<U, Trace>;
- bimap: <U>(
+ move: <_T>(u: _T) => ITraceable<_T, Trace>;
+ map: <_T>(mapper: ITraceableMapper<T, _T, Trace>) => ITraceable<_T, Trace>;
+ bimap: <_T>(
mapper: ITraceableMapper<
T,
- ITraceableTuple<U, Array<Trace> | Trace>,
+ ITraceableTuple<_T, Array<Trace> | Trace>,
Trace
>,
- ) => ITraceable<U, Trace>;
+ ) => ITraceable<_T, Trace>;
peek: (peek: ITraceableMapper<T, void, Trace>) => ITraceable<T, Trace>;
- flatMap: <U>(
- mapper: ITraceableMapper<T, ITraceable<U, Trace>, Trace>,
- ) => ITraceable<U, Trace>;
- flatMapAsync<U>(
- mapper: ITraceableMapper<T, Promise<ITraceable<U, Trace>>, Trace>,
- ): ITraceable<Promise<U>, Trace>;
+ flatMap: <_T>(
+ mapper: ITraceableMapper<T, ITraceable<_T, Trace>, Trace>,
+ ) => ITraceable<_T, Trace>;
+ flatMapAsync<_T>(
+ mapper: ITraceableMapper<T, Promise<ITraceable<_T, Trace>>, Trace>,
+ ): ITraceable<Promise<_T>, Trace>;
}
export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> {
@@ -40,20 +40,20 @@ export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> {
public readonly trace: ITrace<TraceWith>,
) {}
- public map<U>(mapper: ITraceableMapper<T, U, TraceWith>) {
+ public map<_T>(mapper: ITraceableMapper<T, _T, TraceWith>) {
const result = mapper(this);
return new TraceableImpl(result, this.trace);
}
- public flatMap<U>(
- mapper: ITraceableMapper<T, ITraceable<U, TraceWith>, TraceWith>,
- ): ITraceable<U, TraceWith> {
+ public flatMap<_T>(
+ mapper: ITraceableMapper<T, ITraceable<_T, TraceWith>, TraceWith>,
+ ): ITraceable<_T, TraceWith> {
return mapper(this);
}
- public flatMapAsync<U>(
- mapper: ITraceableMapper<T, Promise<ITraceable<U, TraceWith>>, TraceWith>,
- ): ITraceable<Promise<U>, TraceWith> {
+ public flatMapAsync<_T>(
+ mapper: ITraceableMapper<T, Promise<ITraceable<_T, TraceWith>>, TraceWith>,
+ ): ITraceable<Promise<_T>, TraceWith> {
return new TraceableImpl(
mapper(this).then((t) => t.get()),
this.trace,
@@ -65,14 +65,14 @@ export class TraceableImpl<T, TraceWith> implements ITraceable<T, TraceWith> {
return this;
}
- public move<Tt>(t: Tt): ITraceable<Tt, TraceWith> {
+ public move<_T>(t: _T): ITraceable<_T, TraceWith> {
return this.map(() => t);
}
- public bimap<U>(
+ public bimap<_T>(
mapper: ITraceableMapper<
T,
- ITraceableTuple<U, Array<TraceWith> | TraceWith>,
+ ITraceableTuple<_T, Array<TraceWith> | TraceWith>,
TraceWith
>,
) {
diff --git a/u/trace/logger.ts b/u/trace/logger.ts
index 5890545..4f29839 100644
--- a/u/trace/logger.ts
+++ b/u/trace/logger.ts
@@ -95,8 +95,8 @@ export class LogTrace implements ITrace<LogTraceSupplier> {
level: Math.max(logLevelOrder.indexOf(val), acc.level),
};
}
- const prefix = [acc.line, val].join(" ");
- return { ...acc, prefix };
+ const line = [acc.line, val].join(" ");
+ return { ...acc, line };
},
{ line: "", level: -1 },
);
diff --git a/u/trace/metrics.ts b/u/trace/metrics.ts
index 69322b9..822fc38 100644
--- a/u/trace/metrics.ts
+++ b/u/trace/metrics.ts
@@ -8,8 +8,8 @@ import {
} from "@emprespresso/pengueno";
export enum Unit {
- COUNT,
- MILLISECONDS,
+ COUNT = "COUNT",
+ MILLISECONDS = "MILLISECONDS",
}
export interface IMetric {
diff --git a/u/trace/trace.ts b/u/trace/trace.ts
index 03605c2..6cad5b0 100644
--- a/u/trace/trace.ts
+++ b/u/trace/trace.ts
@@ -1,6 +1,7 @@
import {
isMetricsTraceSupplier,
type ITrace,
+ type ITraceable,
type ITraceWith,
LogTrace,
type LogTraceSupplier,
@@ -12,16 +13,14 @@ import {
export class LogTraceable<T> extends TraceableImpl<T, LogTraceSupplier> {
public static LogTrace = new LogTrace();
- static from<T>(t: T) {
+ static of<T>(t: T) {
return new LogTraceable(t, LogTraceable.LogTrace);
}
}
const getEmbeddedMetricConsumer =
- (logTrace: LogTrace) => (metrics: Array<MetricValue>) =>
- logTrace
- .addTrace("<metrics>")
- .trace(JSON.stringify(metrics, null, 2) + "</metrics>");
+ (logTrace: ITrace<LogTraceSupplier>) => (metrics: Array<MetricValue>) =>
+ logTrace.trace(`<metrics>${JSON.stringify(metrics, null)}</metrics>`);
export class EmbeddedMetricsTraceable<T> extends TraceableImpl<
T,
MetricsTraceSupplier
@@ -30,11 +29,8 @@ export class EmbeddedMetricsTraceable<T> extends TraceableImpl<
getEmbeddedMetricConsumer(LogTraceable.LogTrace),
);
- static from<T>(t: T) {
- return new EmbeddedMetricsTraceable(
- t,
- EmbeddedMetricsTraceable.MetricsTrace,
- );
+ static of<T>(t: T, metricsTrace = EmbeddedMetricsTraceable.MetricsTrace) {
+ return new EmbeddedMetricsTraceable(t, metricsTrace);
}
}
@@ -72,12 +68,16 @@ export class LogMetricTraceable<T> extends TraceableImpl<
T,
MetricsTraceSupplier | LogTraceSupplier
> {
- public static LogMetricTrace = new LogMetricTrace(
- LogTraceable.LogTrace,
- EmbeddedMetricsTraceable.MetricsTrace,
- );
+ static ofLogTraceable<T>(t: ITraceable<T, LogTraceSupplier>) {
+ const metricsTrace = new MetricsTrace(getEmbeddedMetricConsumer(t.trace));
+ return new LogMetricTraceable(
+ t.get(),
+ new LogMetricTrace(t.trace, metricsTrace),
+ );
+ }
- static from<T>(t: T) {
- return new LogMetricTraceable(t, LogMetricTraceable.LogMetricTrace);
+ static of<T>(t: T) {
+ const logTrace = LogTraceable.of(t);
+ return LogMetricTraceable.ofLogTraceable(logTrace);
}
}