EdgeAIG's picture
download
raw
6.48 kB
/**
* Low-level devtools client and tracer wiring over the current `Socket`.
*
* `DevToolsClient` speaks the devtools NDJSON protocol used by the unstable
* devtools integration. It sends span starts, span events, span completions,
* ping messages, and metric snapshots through a socket, then exposes tracer
* layers that forward telemetry while preserving the current tracer's behavior.
*
* @since 4.0.0
*/
import * as Cause from "../../Cause.js";
import * as Context from "../../Context.js";
import * as Deferred from "../../Deferred.js";
import * as Effect from "../../Effect.js";
import * as Fiber from "../../Fiber.js";
import * as Layer from "../../Layer.js";
import * as Metric from "../../Metric.js";
import * as Queue from "../../Queue.js";
import * as Schema from "../../Schema.js";
import * as Stream from "../../Stream.js";
import * as Tracer from "../../Tracer.js";
import * as Ndjson from "../encoding/Ndjson.js";
import * as Socket from "../socket/Socket.js";
import * as DevToolsSchema from "./DevToolsSchema.js";
const RequestSchema = /*#__PURE__*/Schema.toCodecJson(DevToolsSchema.Request);
const ResponseSchema = /*#__PURE__*/Schema.toCodecJson(DevToolsSchema.Response);
/**
* Service for sending span and span-event telemetry to the Effect devtools
* connection.
*
* @category services
* @since 4.0.0
*/
export class DevToolsClient extends /*#__PURE__*/Context.Service()("effect/devtools/DevToolsClient") {}
const makeEffect = /*#__PURE__*/Effect.gen(function* () {
const socket = yield* Socket.Socket;
const services = yield* Effect.context();
const requests = yield* Queue.unbounded();
const connected = yield* Deferred.make();
const offerMetricsSnapshot = Effect.sync(() => {
Queue.offerUnsafe(requests, toMetricsSnapshot(services));
});
const handleResponse = response => {
switch (response._tag) {
case "MetricsRequest":
{
return offerMetricsSnapshot;
}
case "Pong":
{
return Effect.void;
}
}
};
const fiber = yield* Stream.fromQueue(requests).pipe(Stream.pipeThroughChannel(Ndjson.duplexSchemaString(Socket.toChannelString(socket), {
inputSchema: RequestSchema,
outputSchema: ResponseSchema
})), Stream.onFirst(() => Deferred.completeWith(connected, Effect.void)), Stream.runForEach(handleResponse), Effect.forkDetach);
yield* Effect.addFinalizer(() => offerMetricsSnapshot.pipe(Effect.andThen(Effect.flatMap(Effect.fiberId, id => Queue.failCause(requests, Cause.interrupt(id)))), Effect.andThen(Fiber.await(fiber))));
yield* Effect.suspend(() => Queue.offer(requests, {
_tag: "Ping"
})).pipe(Effect.delay("3 seconds"), Effect.forever, Effect.forkScoped);
yield* Deferred.await(connected).pipe(Effect.timeoutOption("1 second"), Effect.asVoid);
return DevToolsClient.of({
sendUnsafe(request) {
Queue.offerUnsafe(requests, request);
}
});
});
const toMetricsSnapshot = context => ({
_tag: "MetricsSnapshot",
metrics: Metric.snapshotUnsafe(context)
});
/**
* Creates a devtools client over the current `Socket`, speaking the devtools
* NDJSON protocol, sending periodic pings, and responding to metrics snapshot
* requests.
*
* **When to use**
*
* Use when you already have a `Socket` and need the low-level `DevToolsClient`
* service to exchange devtools telemetry directly.
*
* **Details**
*
* The effect requires `Scope` because it starts background fibers for the socket
* stream and heartbeat.
*
* **Gotchas**
*
* `make` creates only the client service; tracing is installed separately.
*
* @see {@link layer} for providing the client as a layer
* @see {@link makeTracer} for creating a tracer after a `DevToolsClient` is available
* @see {@link layerTracer} for creating the client from the current `Socket` and installing the tracer as a layer
*
* @category constructors
* @since 4.0.0
*/
export const make = /*#__PURE__*/makeEffect.pipe(/*#__PURE__*/Effect.annotateLogs({
module: "DevTools",
service: "Client"
}));
/**
* Layer that provides `DevToolsClient` using the current `Socket`.
*
* **When to use**
*
* Use to provide the low-level `DevToolsClient` service over an existing
* `Socket` for custom devtools integrations that send telemetry through the
* client directly.
*
* **Details**
*
* It delegates to `make`, so it speaks the devtools NDJSON protocol over the
* provided `Socket`, sends periodic pings, responds to metrics snapshot
* requests, and finalizes its background fibers when the layer scope closes.
*
* **Gotchas**
*
* This layer only provides the client. It does not install the devtools tracer
* by itself.
*
* @see {@link make} for constructing the client as a scoped effect instead of a layer
* @see {@link layerTracer} for a higher-level layer that creates the client and installs the devtools tracer
*
* @category layers
* @since 4.0.0
*/
export const layer = /*#__PURE__*/Layer.effect(DevToolsClient, make);
const makeTracerEffect = /*#__PURE__*/Effect.gen(function* () {
const client = yield* DevToolsClient;
const currentTracer = yield* Effect.tracer;
return Tracer.make({
span(options) {
const span = currentTracer.span(options);
client.sendUnsafe(span);
const oldEvent = span.event;
span.event = function (name, startTime, attributes) {
client.sendUnsafe({
_tag: "SpanEvent",
traceId: span.traceId,
spanId: span.spanId,
name,
startTime,
attributes
});
return oldEvent.call(this, name, startTime, attributes);
};
const oldEnd = span.end;
span.end = function (endTime, exit) {
oldEnd.call(this, endTime, exit);
client.sendUnsafe(span);
};
return span;
},
context: currentTracer.context
});
});
/**
* Creates a tracer that delegates to the current tracer while sending span
* starts, span events, and span ends to `DevToolsClient`.
*
* @category constructors
* @since 4.0.0
*/
export const makeTracer = /*#__PURE__*/makeTracerEffect.pipe(/*#__PURE__*/Effect.annotateLogs({
module: "DevTools",
service: "Tracer"
}));
/**
* Layer that creates a `DevToolsClient` from the current `Socket` and installs
* the devtools tracer.
*
* @category layers
* @since 4.0.0
*/
export const layerTracer = /*#__PURE__*/Layer.effect(Tracer.Tracer, makeTracer).pipe(/*#__PURE__*/Layer.provide(layer));
//# sourceMappingURL=DevToolsClient.js.map

Xet Storage Details

Size:
6.48 kB
·
Xet hash:
b293f21b2398fb15fec21c2d1f4d68bb17a80e485c693e6037daa234dd43d616

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.