From dd0ced2bbb177961534e2f68bf778ae780b1e815 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:21:18 +0000 Subject: [PATCH 01/12] The great rename --- src/transformers/otlp.ts | 186 ------------------ src/transformers/transformer.ts | 21 -- test/otlp-exporter.test.ts | 2 +- .../multiple-spans-attributes-and-events.ts | 2 +- .../scripts/otlp/multiple-spans-attributes.ts | 2 +- test/scripts/otlp/multiple-spans-events.ts | 2 +- test/scripts/otlp/multiple-spans.ts | 2 +- test/scripts/otlp/resource-attributes.ts | 2 +- .../otlp/single-span-attributes-and-events.ts | 2 +- test/scripts/otlp/single-span-attributes.ts | 2 +- test/scripts/otlp/single-span-events.ts | 2 +- test/scripts/otlp/single-span.ts | 2 +- .../otlp/span-span-attributes-and-events.ts | 2 +- test/scripts/otlp/span-span-attributes.ts | 2 +- test/scripts/otlp/span-span-events.ts | 2 +- test/scripts/otlp/span-span.ts | 2 +- test/scripts/zipkin/basic.ts | 2 +- .../multiple-spans-attributes-and-events.ts | 2 +- .../zipkin/multiple-spans-attributes.ts | 2 +- test/scripts/zipkin/multiple-spans-events.ts | 2 +- test/scripts/zipkin/multiple-spans.ts | 2 +- test/scripts/zipkin/resource-attributes.ts | 2 +- .../single-span-attributes-and-events.ts | 2 +- test/scripts/zipkin/single-span-attributes.ts | 2 +- test/scripts/zipkin/single-span-events.ts | 2 +- test/scripts/zipkin/single-span.ts | 2 +- .../zipkin/span-span-attributes-and-events.ts | 2 +- test/scripts/zipkin/span-span-attributes.ts | 2 +- test/scripts/zipkin/span-span-events.ts | 2 +- test/scripts/zipkin/span-span.ts | 2 +- test/utils/trace.ts | 2 +- test/zipkin-exporter.test.ts | 2 +- 32 files changed, 30 insertions(+), 237 deletions(-) delete mode 100644 src/transformers/otlp.ts delete mode 100644 src/transformers/transformer.ts diff --git a/src/transformers/otlp.ts b/src/transformers/otlp.ts deleted file mode 100644 index 2da9522..0000000 --- a/src/transformers/otlp.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { Span, Trace } from 'src/tracing'; -import { TraceTransformer } from './transformer'; -import type { Attribute, Attributes } from 'src/types'; - -export interface OtlpJson { - resourceSpans: OtlpResourceSpan[]; -} - -export interface OtlpResourceSpan { - resource: OtlpResource; - scopeSpans: OtlpScopeSpan[]; -} - -export interface OtlpResource { - attributes: OtlpAttribute[]; -} - -export interface OtlpScopeSpan { - scope: OtlpScope; - spans: OtlpSpan[]; -} - -export interface OtlpScope { - name: string; -} - -export interface OtlpSpan { - traceId: string; - spanId: string; - parentSpanId?: string; - name: string; - kind: number; - startTimeUnixNano: number; - endTimeUnixNano: number; - attributes: OtlpAttribute[]; - events: OtlpEvent[]; - status: OtlpStatus; - links: OtlpLink[]; -} - -export interface OtlpStatus { - code: number; -} - -export interface OtlpAttribute { - key: string; - value: OtlpValue; -} - -export interface OtlpValue { - stringValue?: string; - intValue?: number; - boolValue?: boolean; - doubleValue?: number; - - arrayValue?: { values: OtlpValue[] }; -} - -export interface OtlpEvent { - name: string; - timeUnixNano: number; - attributes: OtlpAttribute[]; -} - -export interface OtlpLink { - traceId: string; - spanId: string; - attributes: OtlpAttribute[]; -} - -export type TransformValue = (value: Attribute) => OtlpValue | null; - -export class OtlpTransformer extends TraceTransformer { - - transform(trace: Trace): OtlpJson { - return { - resourceSpans: [ - { - resource: { - attributes: this.transformAttributes( - { - ...trace.getTracerOptions().resource?.attributes, - }, - ), - }, - - scopeSpans: [ - { - scope: { - name: trace.getTracerOptions().serviceName, - }, - spans: this.collectSpans(trace).map((span) => this.transformSpan(span)), - }, - ], - }, - ], - }; - } - - transformAttributes(attributes: Attributes): OtlpAttribute[] { - const transformed: OtlpAttribute[] = []; - - const transformValue: TransformValue = (value: Attribute) => { - if (Array.isArray(value)) { - const values: OtlpValue[] = []; - - for (const val of value) { - const transformed = transformValue(val); - if (transformed) { - values.push(transformed); - } - } - - return { arrayValue: { values } }; - } else { - if (typeof value === 'string') { - return { stringValue: value }; - } else if (typeof value === 'number') { - if (Number.isInteger(value)) { - return { intValue: value }; - } else { - return { doubleValue: value }; - } - } else if (typeof value === 'boolean') { - return { boolValue: value }; - } else { - console.error('Unsupported value type: ' + typeof value); - return null; - } - } - }; - - for (const [key, value] of Object.entries(attributes)) { - const transformedValue = transformValue(value); - if (transformedValue === null) continue; // Skip invalid values - - transformed.push({ - key: key, - value: transformedValue, - }); - } - - return transformed; - } - - transformSpan(span: Span): OtlpSpan { - const data = span.getData(); - - return { - traceId: data.traceId, - spanId: data.id, - parentSpanId: data.parentId, - name: data.name, - kind: 0, // TODO: Implement kind (https://opentelemetry.io/docs/reference/specification/trace/api/#spankind) - startTimeUnixNano: data.timestamp * 1e6, - endTimeUnixNano: (data.timestamp + data.duration) * 1e6, - attributes: this.transformAttributes(data.attributes), - events: data.events.map((event) => ( - { - name: event.name, - timeUnixNano: event.timestamp * 1e6, - attributes: this.transformAttributes(event.attributes || {}), - } - )), - status: data.status, - links: data.links.map((link) => ({ - traceId: link.context.traceId, - spanId: link.context.spanId, - attributes: this.transformAttributes(link.attributes), - })), - }; - } - - collectSpans(span: Span): Span[] { - const spans = []; - - spans.push(span); - - // Go through children and collect them all - for (const childSpan of span.getChildSpans()) { - spans.push(...this.collectSpans(childSpan)); - } - - return spans; - } -} diff --git a/src/transformers/transformer.ts b/src/transformers/transformer.ts deleted file mode 100644 index e31dce2..0000000 --- a/src/transformers/transformer.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Span, Trace } from 'src/tracing'; - -export class TraceTransformer { - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - transform(trace: Trace): object { - throw new Error('Transformer has not implemented `transform()` function'); - } - - collectSpans(span: Span): Span[] { - const spans = []; - - spans.push(span); - // Go through children and collect them all - for (const childSpan of span.getChildSpans()) { - spans.push(...this.collectSpans(childSpan)); - } - - return spans; - } -} diff --git a/test/otlp-exporter.test.ts b/test/otlp-exporter.test.ts index aacf193..71ade1e 100644 --- a/test/otlp-exporter.test.ts +++ b/test/otlp-exporter.test.ts @@ -1,4 +1,4 @@ -import { OtlpJson } from 'src/transformers/otlp'; +import { OtlpJson } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest'; import { UnstableDevWorker } from 'wrangler'; diff --git a/test/scripts/otlp/multiple-spans-attributes-and-events.ts b/test/scripts/otlp/multiple-spans-attributes-and-events.ts index 180f2ef..f09ba79 100644 --- a/test/scripts/otlp/multiple-spans-attributes-and-events.ts +++ b/test/scripts/otlp/multiple-spans-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/multiple-spans-attributes.ts b/test/scripts/otlp/multiple-spans-attributes.ts index 67d351e..b942e4f 100644 --- a/test/scripts/otlp/multiple-spans-attributes.ts +++ b/test/scripts/otlp/multiple-spans-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/multiple-spans-events.ts b/test/scripts/otlp/multiple-spans-events.ts index 26b5c64..13fd9c1 100644 --- a/test/scripts/otlp/multiple-spans-events.ts +++ b/test/scripts/otlp/multiple-spans-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/multiple-spans.ts b/test/scripts/otlp/multiple-spans.ts index b27286f..f82617b 100644 --- a/test/scripts/otlp/multiple-spans.ts +++ b/test/scripts/otlp/multiple-spans.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/resource-attributes.ts b/test/scripts/otlp/resource-attributes.ts index 3300b7f..4fa4cbb 100644 --- a/test/scripts/otlp/resource-attributes.ts +++ b/test/scripts/otlp/resource-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/otlp/single-span-attributes-and-events.ts b/test/scripts/otlp/single-span-attributes-and-events.ts index fe7e3ac..abd45d2 100644 --- a/test/scripts/otlp/single-span-attributes-and-events.ts +++ b/test/scripts/otlp/single-span-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/otlp/single-span-attributes.ts b/test/scripts/otlp/single-span-attributes.ts index 6465f0b..d501383 100644 --- a/test/scripts/otlp/single-span-attributes.ts +++ b/test/scripts/otlp/single-span-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/otlp/single-span-events.ts b/test/scripts/otlp/single-span-events.ts index 6edb257..adefda2 100644 --- a/test/scripts/otlp/single-span-events.ts +++ b/test/scripts/otlp/single-span-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/otlp/single-span.ts b/test/scripts/otlp/single-span.ts index 8438389..d555ff2 100644 --- a/test/scripts/otlp/single-span.ts +++ b/test/scripts/otlp/single-span.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/otlp/span-span-attributes-and-events.ts b/test/scripts/otlp/span-span-attributes-and-events.ts index e856020..bdef4c8 100644 --- a/test/scripts/otlp/span-span-attributes-and-events.ts +++ b/test/scripts/otlp/span-span-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/span-span-attributes.ts b/test/scripts/otlp/span-span-attributes.ts index 03f0b03..d6ea92f 100644 --- a/test/scripts/otlp/span-span-attributes.ts +++ b/test/scripts/otlp/span-span-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/span-span-events.ts b/test/scripts/otlp/span-span-events.ts index 51462be..d49c31c 100644 --- a/test/scripts/otlp/span-span-events.ts +++ b/test/scripts/otlp/span-span-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/otlp/span-span.ts b/test/scripts/otlp/span-span.ts index 81c5164..4dfd402 100644 --- a/test/scripts/otlp/span-span.ts +++ b/test/scripts/otlp/span-span.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/basic.ts b/test/scripts/zipkin/basic.ts index bf16cd2..259f674 100644 --- a/test/scripts/zipkin/basic.ts +++ b/test/scripts/zipkin/basic.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; interface Env {} diff --git a/test/scripts/zipkin/multiple-spans-attributes-and-events.ts b/test/scripts/zipkin/multiple-spans-attributes-and-events.ts index 50ff713..dd072a6 100644 --- a/test/scripts/zipkin/multiple-spans-attributes-and-events.ts +++ b/test/scripts/zipkin/multiple-spans-attributes-and-events.ts @@ -1,4 +1,4 @@ -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; import { createTrace } from 'src/trace'; diff --git a/test/scripts/zipkin/multiple-spans-attributes.ts b/test/scripts/zipkin/multiple-spans-attributes.ts index a5590d3..ad5a48b 100644 --- a/test/scripts/zipkin/multiple-spans-attributes.ts +++ b/test/scripts/zipkin/multiple-spans-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/multiple-spans-events.ts b/test/scripts/zipkin/multiple-spans-events.ts index 9f51247..099bdda 100644 --- a/test/scripts/zipkin/multiple-spans-events.ts +++ b/test/scripts/zipkin/multiple-spans-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/multiple-spans.ts b/test/scripts/zipkin/multiple-spans.ts index ed8b83b..724d139 100644 --- a/test/scripts/zipkin/multiple-spans.ts +++ b/test/scripts/zipkin/multiple-spans.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/resource-attributes.ts b/test/scripts/zipkin/resource-attributes.ts index cdd665d..1a00eae 100644 --- a/test/scripts/zipkin/resource-attributes.ts +++ b/test/scripts/zipkin/resource-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/zipkin/single-span-attributes-and-events.ts b/test/scripts/zipkin/single-span-attributes-and-events.ts index dd04352..70ae701 100644 --- a/test/scripts/zipkin/single-span-attributes-and-events.ts +++ b/test/scripts/zipkin/single-span-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/zipkin/single-span-attributes.ts b/test/scripts/zipkin/single-span-attributes.ts index 049e5e7..c74b579 100644 --- a/test/scripts/zipkin/single-span-attributes.ts +++ b/test/scripts/zipkin/single-span-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/zipkin/single-span-events.ts b/test/scripts/zipkin/single-span-events.ts index 4fcb6dc..d299f8f 100644 --- a/test/scripts/zipkin/single-span-events.ts +++ b/test/scripts/zipkin/single-span-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/zipkin/single-span.ts b/test/scripts/zipkin/single-span.ts index 7183996..fa985d4 100644 --- a/test/scripts/zipkin/single-span.ts +++ b/test/scripts/zipkin/single-span.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env {} diff --git a/test/scripts/zipkin/span-span-attributes-and-events.ts b/test/scripts/zipkin/span-span-attributes-and-events.ts index 78a35c0..d846f4f 100644 --- a/test/scripts/zipkin/span-span-attributes-and-events.ts +++ b/test/scripts/zipkin/span-span-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/span-span-attributes.ts b/test/scripts/zipkin/span-span-attributes.ts index 6fb85d1..c4b41b9 100644 --- a/test/scripts/zipkin/span-span-attributes.ts +++ b/test/scripts/zipkin/span-span-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/span-span-events.ts b/test/scripts/zipkin/span-span-events.ts index 660a63b..a40a01a 100644 --- a/test/scripts/zipkin/span-span-events.ts +++ b/test/scripts/zipkin/span-span-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/scripts/zipkin/span-span.ts b/test/scripts/zipkin/span-span.ts index 860864c..6f7cde2 100644 --- a/test/scripts/zipkin/span-span.ts +++ b/test/scripts/zipkin/span-span.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/transformers/zipkin'; +import { ZipkinTransformer } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { diff --git a/test/utils/trace.ts b/test/utils/trace.ts index 974a04e..0d3780b 100644 --- a/test/utils/trace.ts +++ b/test/utils/trace.ts @@ -1,6 +1,6 @@ import { expect } from 'vitest'; import { UnstableDevWorker } from 'wrangler'; -import { OtlpJson } from '../../src/transformers/otlp'; +import { OtlpJson } from '../../src/exporters/otlp'; export async function requestAndGetTrace( devWorker: UnstableDevWorker, diff --git a/test/zipkin-exporter.test.ts b/test/zipkin-exporter.test.ts index a0b755c..ac0ec30 100644 --- a/test/zipkin-exporter.test.ts +++ b/test/zipkin-exporter.test.ts @@ -1,4 +1,4 @@ -import { ZipkinJson } from 'src/transformers/zipkin'; +import { ZipkinJson } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest'; import { UnstableDevWorker } from 'wrangler'; From 677dbd376695c3f1088721d71f69f2f717791c0c Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:22:16 +0000 Subject: [PATCH 02/12] The great rename part 2 --- src/exporters/otlp.ts | 261 ++++++++++++++++++++++ src/{transformers => exporters}/zipkin.ts | 17 +- src/index.ts | 5 +- test/scripts/otlp/basic.ts | 2 +- 4 files changed, 279 insertions(+), 6 deletions(-) create mode 100644 src/exporters/otlp.ts rename src/{transformers => exporters}/zipkin.ts (73%) diff --git a/src/exporters/otlp.ts b/src/exporters/otlp.ts new file mode 100644 index 0000000..17527ca --- /dev/null +++ b/src/exporters/otlp.ts @@ -0,0 +1,261 @@ +import { Span, Trace } from 'src/tracing'; +import { isHex, hexToNumber, numberToHex } from 'src/utils/hex'; +import { Exporter } from './exporter'; +import type { Attribute, Attributes, SpanContext } from 'src/types'; + +export interface OtlpJson { + resourceSpans: OtlpResourceSpan[]; +} + +export interface OtlpResourceSpan { + resource: OtlpResource; + scopeSpans: OtlpScopeSpan[]; +} + +export interface OtlpResource { + attributes: OtlpAttribute[]; +} + +export interface OtlpScopeSpan { + scope: OtlpScope; + spans: OtlpSpan[]; +} + +export interface OtlpScope { + name: string; +} + +export interface OtlpSpan { + traceId: string; + spanId: string; + parentSpanId?: string; + name: string; + kind: number; + startTimeUnixNano: number; + endTimeUnixNano: number; + attributes: OtlpAttribute[]; + events: OtlpEvent[]; + status: OtlpStatus; + links: OtlpLink[]; +} + +export interface OtlpStatus { + code: number; +} + +export interface OtlpAttribute { + key: string; + value: OtlpValue; +} + +export interface OtlpValue { + stringValue?: string; + intValue?: number; + boolValue?: boolean; + doubleValue?: number; + + arrayValue?: { values: OtlpValue[] }; +} + +export interface OtlpEvent { + name: string; + timeUnixNano: number; + attributes: OtlpAttribute[]; +} + +export interface OtlpLink { + traceId: string; + spanId: string; + attributes: OtlpAttribute[]; +} + +export type TransformValue = (value: Attribute) => OtlpValue | null; + +const VERSION = 0; + +// Flags +const SAMPLED = 1 << 0; + +interface ParentTraceInfo { + traceparent?: string; + tracestate?: string; +} + +export class OtlpExporter extends Exporter { + + #parentTraceInfo: ParentTraceInfo; + + constructor() { + super(); + this.#parentTraceInfo = {}; + } + + transform(trace: Trace): OtlpJson { + return { + resourceSpans: [ + { + resource: { + attributes: this.transformAttributes( + { + ...trace.getTracerOptions().resource?.attributes, + }, + ), + }, + + scopeSpans: [ + { + scope: { + name: trace.getTracerOptions().serviceName, + }, + spans: this.collectSpans(trace).map((span) => this.transformSpan(span)), + }, + ], + }, + ], + }; + } + + transformAttributes(attributes: Attributes): OtlpAttribute[] { + const transformed: OtlpAttribute[] = []; + + const transformValue: TransformValue = (value: Attribute) => { + if (Array.isArray(value)) { + const values: OtlpValue[] = []; + + for (const val of value) { + const transformed = transformValue(val); + if (transformed) { + values.push(transformed); + } + } + + return { arrayValue: { values } }; + } else { + if (typeof value === 'string') { + return { stringValue: value }; + } else if (typeof value === 'number') { + if (Number.isInteger(value)) { + return { intValue: value }; + } else { + return { doubleValue: value }; + } + } else if (typeof value === 'boolean') { + return { boolValue: value }; + } else { + console.error('Unsupported value type: ' + typeof value); + return null; + } + } + }; + + for (const [key, value] of Object.entries(attributes)) { + const transformedValue = transformValue(value); + if (transformedValue === null) continue; // Skip invalid values + + transformed.push({ + key: key, + value: transformedValue, + }); + } + + return transformed; + } + + transformSpan(span: Span): OtlpSpan { + const data = span.getData(); + + return { + traceId: data.traceId, + spanId: data.id, + parentSpanId: data.parentId, + name: data.name, + kind: 0, // TODO: Implement kind (https://opentelemetry.io/docs/reference/specification/trace/api/#spankind) + startTimeUnixNano: data.timestamp * 1e6, + endTimeUnixNano: (data.timestamp + data.duration) * 1e6, + attributes: this.transformAttributes(data.attributes), + events: data.events.map((event) => ( + { + name: event.name, + timeUnixNano: event.timestamp * 1e6, + attributes: this.transformAttributes(event.attributes || {}), + } + )), + status: data.status, + links: data.links.map((link) => ({ + traceId: link.context.traceId, + spanId: link.context.spanId, + attributes: this.transformAttributes(link.attributes), + })), + }; + } + + injectContextHeaders(span: Span): Record { + const flags = 0; + // TODO: Implement sampling + // if (sampled) flags |= SAMPLED + + return { + traceparent: `${numberToHex(VERSION, 2)}-${span.getTraceId()}-${span.getSpanId()}-${numberToHex(flags)}`, + }; + } + + readContextHeaders(headers: Headers): SpanContext | null { + const traceparent = headers.get('traceparent'); + if (traceparent === null) return null; + + const parts = traceparent.split('-'); + + // We expect at least 4 parts for version 0 + // --- + if (parts.length < 4) { + return null; + } + + const version = hexToNumber(parts[0]); + const traceId = parts[1]; + const spanId = parts[2]; + const flags = parts[3]; + + // Field validation failed + if (version === null + || parts[0].length !== 2 // Version needs to be 2 hex chars + || traceId.length !== 32 + || !isHex(traceId) + || spanId.length !== 16 + || !isHex(spanId) + || flags.length !== 2 + || !isHex(flags) + ) { + return null; + } + + // Valid :) + this.#parentTraceInfo.traceparent = traceparent; + + // https://www.w3.org/TR/trace-context/#tracestate-header + const tracestate = headers.get('tracestate'); + if (tracestate !== null) { + this.#parentTraceInfo.tracestate = tracestate; + } + + return { traceId, spanId }; + } + + collectSpans(span: Span): Span[] { + const spans = []; + + spans.push(span); + + // Go through children and collect them all + for (const childSpan of span.getChildSpans()) { + spans.push(...this.collectSpans(childSpan)); + } + + return spans; + } +} + +/** + * @deprecated Use OtlpExporter + */ +export class OtlpTransformer extends OtlpExporter {} diff --git a/src/transformers/zipkin.ts b/src/exporters/zipkin.ts similarity index 73% rename from src/transformers/zipkin.ts rename to src/exporters/zipkin.ts index 8c84c5e..0170ab8 100644 --- a/src/transformers/zipkin.ts +++ b/src/exporters/zipkin.ts @@ -1,5 +1,6 @@ -import { Trace } from 'src/tracing'; -import { TraceTransformer } from './transformer'; +import { Span, Trace } from 'src/tracing'; +import { generateSpanId } from 'src/utils/rand'; +import { Exporter } from './exporter'; export type ZipkinJson = ZipkinSpan[]; @@ -28,7 +29,7 @@ export interface ZipkinAnnotation { value: string; } -export class ZipkinTransformer extends TraceTransformer { +export class ZipkinTransformer extends Exporter { transform(trace: Trace): ZipkinJson { const spans: ZipkinJson = []; @@ -63,4 +64,14 @@ export class ZipkinTransformer extends TraceTransformer { return spans; } + + getContextHeaders(span: Span): Record { + // https://github.com/openzipkin/b3-propagation + return { + 'X-B3-TraceId': span.getTraceId(), + 'X-B3-ParentSpanId': span.getSpanId(), + 'X-B3-SpanId': generateSpanId(), // TODO: Figure out what I want to do here + 'X-B3-Sampled': '1', // TODO: Implement sampling + }; + } } diff --git a/src/index.ts b/src/index.ts index b65b58e..471e0c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ export * from './trace'; export * from './tracing'; -export * from './transformers/otlp'; -export * from './transformers/zipkin'; +export * from './exporters/otlp'; +export * from './exporters/zipkin'; export * from './utils/constants'; +export * from './types'; diff --git a/test/scripts/otlp/basic.ts b/test/scripts/otlp/basic.ts index e6b356c..b005eb1 100644 --- a/test/scripts/otlp/basic.ts +++ b/test/scripts/otlp/basic.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { OtlpTransformer } from 'src/transformers/otlp'; +import { OtlpTransformer } from 'src/exporters/otlp'; interface Env {} From 434dd837b984a96a824bb97b257935c56caa5af4 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:25:31 +0000 Subject: [PATCH 03/12] Add initial context passing + tracedFetch --- src/exporters/exporter.ts | 42 +++++++++++++++++++++++++++++++++++++++ src/trace.ts | 9 +++++++++ src/tracing.ts | 37 ++++++++++++++++++++++++++++++---- src/types.ts | 12 ++++++++--- 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 src/exporters/exporter.ts diff --git a/src/exporters/exporter.ts b/src/exporters/exporter.ts new file mode 100644 index 0000000..45a3e6c --- /dev/null +++ b/src/exporters/exporter.ts @@ -0,0 +1,42 @@ +import { Span, Trace } from 'src/tracing'; +import { SpanContext } from 'src/types'; + +export class Exporter { + + /** + * Transform a Trace into a JSON object which will be sent to the collector. + * + * @param trace The Trace which needs to be transformed + * @returns The transformed Trace + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + transform(trace: Trace): object { + throw new Error('Transformer has not implemented `transform()` function'); + } + + /** + * Get the headers containing the trace context, these will be passed on to other services + * so that they can continue the trace. + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + injectContextHeaders(span: Span): Record { + return {}; + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + readContextHeaders(headers: Headers): SpanContext | null { + return null; + } + + collectSpans(span: Span): Span[] { + const spans = []; + + spans.push(span); + // Go through children and collect them all + for (const childSpan of span.getChildSpans()) { + spans.push(...this.collectSpans(childSpan)); + } + + return spans; + } +} diff --git a/src/trace.ts b/src/trace.ts index 0967709..0554e24 100644 --- a/src/trace.ts +++ b/src/trace.ts @@ -49,3 +49,12 @@ export function traceFn( span.end(); return value; } + +export function tracedFetch( + parent: Span, + request: string | Request, + requestInit?: RequestInit | Request, + spanOpts?: SpanCreationOptions, +): Promise { + return parent.tracedFetch(request, requestInit, spanOpts); +} diff --git a/src/tracing.ts b/src/tracing.ts index 05c5609..b13ccac 100644 --- a/src/tracing.ts +++ b/src/tracing.ts @@ -1,5 +1,5 @@ -import { OtlpTransformer } from './transformers/otlp'; -import { ATTRIBUTE_NAME } from './utils/constants'; +import { OtlpTransformer } from './exporters/otlp'; +import { ATTRIBUTE_NAME, SPAN_NAME } from './utils/constants'; import { generateSpanId, generateTraceId } from './utils/rand'; import { traceFn } from './trace'; import { SpanBuilder } from './builder'; @@ -33,11 +33,19 @@ export function getDefaultAttributes(opts: TracerOptions): Attributes { } export class Span { - + + #trace: Trace; #span: SpanData; #childSpans: Span[]; constructor(traceId: string, name: string, spanOptions?: SpanCreationOptions) { + // TODO: Figure out how I want to do this + const trace = this instanceof Trace ? this : spanOptions?.trace; + if (!trace) { + throw new Error('No Trace provided for Span'); + } + + this.#trace = trace; this.#span = { traceId: traceId, name, @@ -75,16 +83,37 @@ export class Span { startSpan(name: string, spanOptions?: SpanCreationOptions): Span { const span = new Span(this.#span.traceId, name, spanOptions); + span.#trace = this.#trace; // TODO: I hate this, fix. span.#span.parentId = this.getSpanId(); this.#childSpans.push(span); return span; } + injectPropagation(req: Request) { + // TODO: Figure out a better way to get the exporter in these situations + const exporter = this.#trace.getTracerOptions().collector.exporter ?? new OtlpTransformer(); + + for (const [name, value] of Object.entries(exporter.injectContextHeaders(this))) { + req.headers.append(name, value); + } + } + trace(name: string, fn: TracedFn, opts?: SpanCreationOptions): T { return traceFn(this, name, fn, opts); } + tracedFetch( + request: string | Request, + requestInit?: RequestInit | Request, + spanOpts?: SpanCreationOptions, + ): Promise { + const tracedRequest = new Request(request, requestInit); + this.injectPropagation(tracedRequest); + + return traceFn(this, SPAN_NAME.FETCH, () => fetch(tracedRequest), spanOpts); + } + buildSpan(name: string) { return new SpanBuilder(this, name); } @@ -114,7 +143,7 @@ export class Trace extends Span { ) { super( tracerOptions.traceContext?.traceId ?? generateTraceId(), - 'Request (fetch event)', + 'Request', { parentId: tracerOptions.traceContext?.spanId, ...spanOptions, diff --git a/src/types.ts b/src/types.ts index 13bd515..fe430a7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,5 @@ -import { StatusCode } from './tracing'; -import { TraceTransformer } from './transformers/transformer'; +import { StatusCode, Trace } from './tracing'; +import { Exporter } from './exporters/exporter'; export interface TraceData { // 8 bit field currently only used to indicate sampling @@ -66,6 +66,8 @@ export interface SpanCreationOptions { // https://www.w3.org/TR/trace-context/#parent-id parentId?: string; + trace?: Trace; + // The creation time of the span, epoch unix timestamp // https://opentelemetry.io/docs/reference/specification/trace/api/#timestamp timestamp?: number; @@ -126,7 +128,11 @@ export interface TracerOptions { export interface CollectorOptions { url: string; headers?: HeadersInit; - transformer?: TraceTransformer; + /** + * @deprecated Use `exporter` instead + */ + transformer?: Exporter; + exporter?: Exporter; } export interface ResourceOptions { From 95359d33a99f8145398deb8079126e3bdc475130 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:29:43 +0000 Subject: [PATCH 04/12] Fix trace being passed --- src/tracing.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tracing.ts b/src/tracing.ts index b13ccac..4af8ce1 100644 --- a/src/tracing.ts +++ b/src/tracing.ts @@ -82,8 +82,10 @@ export class Span { } startSpan(name: string, spanOptions?: SpanCreationOptions): Span { - const span = new Span(this.#span.traceId, name, spanOptions); - span.#trace = this.#trace; // TODO: I hate this, fix. + const span = new Span(this.#span.traceId, name, { + trace: this.#trace, + ...spanOptions, + }); span.#span.parentId = this.getSpanId(); this.#childSpans.push(span); From b71cd2eba1ac9257334432cf8d65b7e1dbfff317 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:39:52 +0000 Subject: [PATCH 05/12] hex util --- src/utils/hex.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/utils/hex.ts diff --git a/src/utils/hex.ts b/src/utils/hex.ts new file mode 100644 index 0000000..fb3f2f3 --- /dev/null +++ b/src/utils/hex.ts @@ -0,0 +1,19 @@ +const HEX_REGEX = /[a-f0-9]+/g; + +export function isHex(str: string) { + return HEX_REGEX.test(str); +} + +export function hexToNumber(str: string) { + return parseInt(str, 16); +} + +export function numberToHex(num: number, length?: number) { + let hex = num.toString(16); + + if (length && hex.length < length) { + hex = '0'.repeat(length - hex.length) + hex; + } + + return hex; +} From e99e4168e4a823fb25d78d89e56249b454af46a8 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:42:28 +0000 Subject: [PATCH 06/12] Renamed root span in tests; --- test/api.test.ts | 24 ++++++++++++------------ test/otlp-exporter.test.ts | 26 +++++++++++++------------- test/zipkin-exporter.test.ts | 30 +++++++++++++++--------------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/test/api.test.ts b/test/api.test.ts index d31ccdd..777b232 100644 --- a/test/api.test.ts +++ b/test/api.test.ts @@ -132,7 +132,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); }); @@ -184,7 +184,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); }); @@ -231,7 +231,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate custom attributes @@ -268,7 +268,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate status @@ -300,7 +300,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate events @@ -334,7 +334,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate links @@ -461,7 +461,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate builder span @@ -486,7 +486,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate builder span @@ -566,7 +566,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate builder span @@ -596,7 +596,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate builder span @@ -624,7 +624,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate builder span @@ -662,7 +662,7 @@ describe('API', () => { const span = resourceSpan.scopeSpans[0].spans[0]; // Validate root span - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.endTimeUnixNano).not.toBe(0); // Validate builder span diff --git a/test/otlp-exporter.test.ts b/test/otlp-exporter.test.ts index 71ade1e..ea069a1 100644 --- a/test/otlp-exporter.test.ts +++ b/test/otlp-exporter.test.ts @@ -51,7 +51,7 @@ describe('Test OTLP Exporter', () => { const span = resourceSpan.scopeSpans[0].spans[0]; expect(span.traceId).toBe(traceId); - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); }); describe('Resource', () => { @@ -163,7 +163,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // Child span @@ -202,7 +202,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // Child span @@ -243,7 +243,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // Child span @@ -296,7 +296,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // Child span @@ -354,7 +354,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -402,7 +402,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -454,7 +454,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -524,7 +524,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -600,7 +600,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -649,7 +649,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -702,7 +702,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span @@ -773,7 +773,7 @@ describe('Test OTLP Exporter', () => { // Root span const rootSpan = spans[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.endTimeUnixNano).not.toBe(0); // First child span diff --git a/test/zipkin-exporter.test.ts b/test/zipkin-exporter.test.ts index ac0ec30..cdd2cfc 100644 --- a/test/zipkin-exporter.test.ts +++ b/test/zipkin-exporter.test.ts @@ -44,7 +44,7 @@ describe('Test Zipkin Exporter', () => { const span = trace[0]; expect(span.traceId).toBe(traceId); - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.localEndpoint.serviceName).toBe('zipkin-basic'); }); @@ -66,7 +66,7 @@ describe('Test Zipkin Exporter', () => { const span = trace[0]; expect(span.traceId).toBe(traceId); - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.localEndpoint.serviceName).toBe('zipkin-basic'); // Check attributes @@ -94,7 +94,7 @@ describe('Test Zipkin Exporter', () => { const span = trace[0]; expect(span.traceId).toBe(traceId); - expect(span.name).toBe('Request (fetch event)'); + expect(span.name).toBe('Request'); expect(span.localEndpoint.serviceName).toBe('resource-attributes'); // Check attributes @@ -131,7 +131,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('single-span'); // Child span @@ -163,7 +163,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('single-span-attributes'); // Child span @@ -196,7 +196,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('single-span-events'); // Child span @@ -235,7 +235,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('single-span-attributes-and-events'); // Child span @@ -279,7 +279,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('multiple-spans'); // First child span @@ -320,7 +320,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('multiple-spans-attributes'); // First child span @@ -363,7 +363,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('multiple-spans-events'); // First child span @@ -416,7 +416,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('multiple-spans-attributes-and-events'); // First child span @@ -473,7 +473,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('span-span'); // First child span @@ -515,7 +515,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('span-span-attributes'); // First child span @@ -559,7 +559,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('span-span-events'); // First child span @@ -613,7 +613,7 @@ describe('Test Zipkin Exporter', () => { // Root span const rootSpan = trace[0]; expect(rootSpan.traceId).toBe(traceId); - expect(rootSpan.name).toBe('Request (fetch event)'); + expect(rootSpan.name).toBe('Request'); expect(rootSpan.localEndpoint.serviceName).toBe('span-span-attributes-and-events'); // First child span From 823fc280adff5f4bb3b1ae4d6026aa3926583ac6 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:43:37 +0000 Subject: [PATCH 07/12] Only run push on main --- .github/workflows/push.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4790601..eb5831e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,4 +1,7 @@ -on: push +on: + push: + branches: + - main jobs: test: From 42fd2f59466029ef7386b6e9457b985fa728c220 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 16:49:24 +0000 Subject: [PATCH 08/12] Rename ZipkinTransformer to ZipkinExporter --- src/exporters/zipkin.ts | 4 +++- test/scripts/zipkin/basic.ts | 4 ++-- test/scripts/zipkin/multiple-spans-attributes-and-events.ts | 4 ++-- test/scripts/zipkin/multiple-spans-attributes.ts | 4 ++-- test/scripts/zipkin/multiple-spans-events.ts | 4 ++-- test/scripts/zipkin/multiple-spans.ts | 4 ++-- test/scripts/zipkin/resource-attributes.ts | 4 ++-- test/scripts/zipkin/single-span-attributes-and-events.ts | 4 ++-- test/scripts/zipkin/single-span-attributes.ts | 4 ++-- test/scripts/zipkin/single-span-events.ts | 4 ++-- test/scripts/zipkin/single-span.ts | 4 ++-- test/scripts/zipkin/span-span-attributes-and-events.ts | 4 ++-- test/scripts/zipkin/span-span-attributes.ts | 4 ++-- test/scripts/zipkin/span-span-events.ts | 4 ++-- test/scripts/zipkin/span-span.ts | 4 ++-- 15 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/exporters/zipkin.ts b/src/exporters/zipkin.ts index 0170ab8..0573555 100644 --- a/src/exporters/zipkin.ts +++ b/src/exporters/zipkin.ts @@ -29,7 +29,7 @@ export interface ZipkinAnnotation { value: string; } -export class ZipkinTransformer extends Exporter { +export class ZipkinExporter extends Exporter { transform(trace: Trace): ZipkinJson { const spans: ZipkinJson = []; @@ -75,3 +75,5 @@ export class ZipkinTransformer extends Exporter { }; } } + +export class ZipkinTransformer extends ZipkinExporter {} diff --git a/test/scripts/zipkin/basic.ts b/test/scripts/zipkin/basic.ts index 259f674..5093117 100644 --- a/test/scripts/zipkin/basic.ts +++ b/test/scripts/zipkin/basic.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; interface Env {} @@ -9,7 +9,7 @@ export default { serviceName: 'zipkin-basic', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/multiple-spans-attributes-and-events.ts b/test/scripts/zipkin/multiple-spans-attributes-and-events.ts index dd072a6..2ad8f9c 100644 --- a/test/scripts/zipkin/multiple-spans-attributes-and-events.ts +++ b/test/scripts/zipkin/multiple-spans-attributes-and-events.ts @@ -1,4 +1,4 @@ -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; import { createTrace } from 'src/trace'; @@ -12,7 +12,7 @@ export default { serviceName: 'multiple-spans-attributes-and-events', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/multiple-spans-attributes.ts b/test/scripts/zipkin/multiple-spans-attributes.ts index ad5a48b..8fe9012 100644 --- a/test/scripts/zipkin/multiple-spans-attributes.ts +++ b/test/scripts/zipkin/multiple-spans-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'multiple-spans-attributes', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/multiple-spans-events.ts b/test/scripts/zipkin/multiple-spans-events.ts index 099bdda..a5b4d41 100644 --- a/test/scripts/zipkin/multiple-spans-events.ts +++ b/test/scripts/zipkin/multiple-spans-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'multiple-spans-events', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/multiple-spans.ts b/test/scripts/zipkin/multiple-spans.ts index 724d139..806b32d 100644 --- a/test/scripts/zipkin/multiple-spans.ts +++ b/test/scripts/zipkin/multiple-spans.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'multiple-spans', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/resource-attributes.ts b/test/scripts/zipkin/resource-attributes.ts index 1a00eae..6efc2ce 100644 --- a/test/scripts/zipkin/resource-attributes.ts +++ b/test/scripts/zipkin/resource-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME } from 'src/utils/constants'; interface Env {} @@ -10,7 +10,7 @@ export default { serviceName: 'resource-attributes', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, resource: { attributes: { diff --git a/test/scripts/zipkin/single-span-attributes-and-events.ts b/test/scripts/zipkin/single-span-attributes-and-events.ts index 70ae701..e8e0964 100644 --- a/test/scripts/zipkin/single-span-attributes-and-events.ts +++ b/test/scripts/zipkin/single-span-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} @@ -10,7 +10,7 @@ export default { serviceName: 'single-span-attributes-and-events', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/single-span-attributes.ts b/test/scripts/zipkin/single-span-attributes.ts index c74b579..158bd1b 100644 --- a/test/scripts/zipkin/single-span-attributes.ts +++ b/test/scripts/zipkin/single-span-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env {} @@ -10,7 +10,7 @@ export default { serviceName: 'single-span-attributes', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/single-span-events.ts b/test/scripts/zipkin/single-span-events.ts index d299f8f..e1d1c39 100644 --- a/test/scripts/zipkin/single-span-events.ts +++ b/test/scripts/zipkin/single-span-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env {} @@ -10,7 +10,7 @@ export default { serviceName: 'single-span-events', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/single-span.ts b/test/scripts/zipkin/single-span.ts index fa985d4..58e274a 100644 --- a/test/scripts/zipkin/single-span.ts +++ b/test/scripts/zipkin/single-span.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env {} @@ -10,7 +10,7 @@ export default { serviceName: 'single-span', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/span-span-attributes-and-events.ts b/test/scripts/zipkin/span-span-attributes-and-events.ts index d846f4f..0c8f06a 100644 --- a/test/scripts/zipkin/span-span-attributes-and-events.ts +++ b/test/scripts/zipkin/span-span-attributes-and-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'span-span-attributes-and-events', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/span-span-attributes.ts b/test/scripts/zipkin/span-span-attributes.ts index c4b41b9..2fa1f8d 100644 --- a/test/scripts/zipkin/span-span-attributes.ts +++ b/test/scripts/zipkin/span-span-attributes.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { ATTRIBUTE_NAME, SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'span-span-attributes', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/span-span-events.ts b/test/scripts/zipkin/span-span-events.ts index a40a01a..a3a477a 100644 --- a/test/scripts/zipkin/span-span-events.ts +++ b/test/scripts/zipkin/span-span-events.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'span-span-events', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); diff --git a/test/scripts/zipkin/span-span.ts b/test/scripts/zipkin/span-span.ts index 6f7cde2..1f75a21 100644 --- a/test/scripts/zipkin/span-span.ts +++ b/test/scripts/zipkin/span-span.ts @@ -1,5 +1,5 @@ import { createTrace } from 'src/trace'; -import { ZipkinTransformer } from 'src/exporters/zipkin'; +import { ZipkinExporter } from 'src/exporters/zipkin'; import { SPAN_NAME } from 'src/utils/constants'; interface Env { @@ -12,7 +12,7 @@ export default { serviceName: 'span-span', collector: { url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint - transformer: new ZipkinTransformer(), + transformer: new ZipkinExporter(), }, }); From b6bf554e389b7849f4e8c284a4b85c75591d343b Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 19:32:36 +0000 Subject: [PATCH 09/12] Write initial tests for OTLP --- package-lock.json | 951 +++++++++++++----- package.json | 4 +- patches/wrangler+2.8.1.patch | 17 + src/exporters/otlp.ts | 2 +- src/trace.ts | 11 +- src/tracing.ts | 8 +- src/types.ts | 4 +- src/utils/hex.ts | 2 +- test/otlp-exporter.test.ts | 108 +- test/scripts/otlp/propagation/basic-fetch.ts | 41 + test/scripts/otlp/propagation/test-id.ts | 21 + test/scripts/otlp/propagation/traced-fetch.ts | 34 + 12 files changed, 943 insertions(+), 260 deletions(-) create mode 100644 patches/wrangler+2.8.1.patch create mode 100644 test/scripts/otlp/propagation/basic-fetch.ts create mode 100644 test/scripts/otlp/propagation/test-id.ts create mode 100644 test/scripts/otlp/propagation/traced-fetch.ts diff --git a/package-lock.json b/package-lock.json index 6b663b7..a0288fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "workers-tracing", - "version": "0.1.1", + "version": "0.1.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "workers-tracing", - "version": "0.1.1", + "version": "0.1.3", "license": "MIT", "devDependencies": { "@changesets/changelog-github": "^0.4.8", @@ -17,8 +17,9 @@ "esbuild-plugin-replace": "^1.3.0", "eslint": "^8.30.0", "eslint-plugin-import": "^2.26.0", + "patch-package": "^6.5.1", "vitest": "^0.26.2", - "wrangler": "^2.6.2" + "wrangler": "^2.8.1" } }, "node_modules/@babel/code-frame": { @@ -1348,13 +1349,13 @@ } }, "node_modules/@miniflare/cache": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.10.0.tgz", - "integrity": "sha512-nzEqFVPnD7Yf0HMDv7gCPpf4NSXfjhc+zg3gSwUS4Dad5bWV10B1ujTZW6HxQulW3CBHIg616mTjXIiaimVuEQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.11.0.tgz", + "integrity": "sha512-L/kc9AzidPwFuk2fwHpAEePi0kNBk6FWUq3ln+9beRCDrPEpfVrDRFpNleF1NFZz5//oeVMuo8F0IVUQGzR7+Q==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "http-cache-semantics": "^4.1.0", "undici": "5.9.1" }, @@ -1363,12 +1364,12 @@ } }, "node_modules/@miniflare/cli-parser": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.10.0.tgz", - "integrity": "sha512-NAiCtqlHTUKCmV+Jl9af+ixGmMhiGhIyIfr/vCdbismNEBxEsrQGg3sQYTNfvCkdHtODurQqayQreFq21OuEow==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.11.0.tgz", + "integrity": "sha512-JUmyRzEGAS6CouvXJwBh8p44onfw3KRpfq5JGXEuHModOGjTp6li7PQyCTNPV2Hv/7StAXWnTFGXeAqyDHuTig==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0", + "@miniflare/shared": "2.11.0", "kleur": "^4.1.4" }, "engines": { @@ -1376,15 +1377,15 @@ } }, "node_modules/@miniflare/core": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.10.0.tgz", - "integrity": "sha512-Jx1M5oXQua0jzsJVdZSq07baVRmGC/6JkglrPQGAlZ7gQ1sunVZzq9fjxFqj0bqfEuYS0Wy6+lvK4rOAHISIjw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.11.0.tgz", + "integrity": "sha512-UFMFiCG0co36VpZkgFrSBnrxo71uf1x+cjlzzJi3khmMyDlnLu4RuIQsAqvKbYom6fi3G9Q8lTgM7JuOXFyjhw==", "dev": true, "dependencies": { "@iarna/toml": "^2.2.5", - "@miniflare/queues": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/watcher": "2.10.0", + "@miniflare/queues": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/watcher": "2.11.0", "busboy": "^1.6.0", "dotenv": "^10.0.0", "kleur": "^4.1.4", @@ -1397,27 +1398,27 @@ } }, "node_modules/@miniflare/d1": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.10.0.tgz", - "integrity": "sha512-mOYZSmpTthH0tmFTQ+O9G0Q+iDAd7oiUtoIBianlKa9QiqYAoO7EBUPy6kUgDHXapOcN5Ri1u3J5UTpxXvw3qg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.11.0.tgz", + "integrity": "sha512-aDdBVQZ2C0Zs3+Y9ZbRctmuQxozPfpumwJ/6NG6fBadANvune/hW7ddEoxyteIEU9W3IgzVj8s4by4VvasX90A==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0" + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0" }, "engines": { "node": ">=16.7" } }, "node_modules/@miniflare/durable-objects": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.10.0.tgz", - "integrity": "sha512-gU45f52gveFtCasm0ixYnt0mHI1lHrPomtmF+89oZGKBzOqUfO5diDs6wmoRSnovOWZCwtmwQGRoorAQN7AmoA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.11.0.tgz", + "integrity": "sha512-0cKJaMgraTEU1b4kqK8cjD2oTeOjA6QU3Y+lWiZT/k1PMHZULovrSFnjii7qZ8npf4VHSIN6XYPxhyxRyEM65Q==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/storage-memory": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/storage-memory": "2.11.0", "undici": "5.9.1" }, "engines": { @@ -1425,13 +1426,13 @@ } }, "node_modules/@miniflare/html-rewriter": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.10.0.tgz", - "integrity": "sha512-hCdG99L8+Ros4dn3B5H37PlQPBH0859EoRslzNTd4jzGIkwdiawpJvrvesL8056GjbUjeJN1zh7OPBRuMgyGLw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.11.0.tgz", + "integrity": "sha512-olTqmuYTHnoTNtiA0vjQ/ixRfbwgPzDrAUbtXDCYW45VFbHfDVJrJGZX3Jg0HpSlxy86Zclle1SUxGbVDzxsBg==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "html-rewriter-wasm": "^0.4.1", "undici": "5.9.1" }, @@ -1440,14 +1441,14 @@ } }, "node_modules/@miniflare/http-server": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.10.0.tgz", - "integrity": "sha512-cm6hwkONucll93yoY8dteMp//Knvmb7n6zAgeHrtuNYKn//lAL6bRY//VLTttrMmfWxZFi1C7WpOeCv8Mn6/ug==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.11.0.tgz", + "integrity": "sha512-sMLcrDFzqqAvnQmAUH0hRTo8sBjW79VZYfnIH5FAGSGcKX6kdAGs9RStdYZ4CftQCBAEQScX0KBsMx5FwJRe9Q==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/web-sockets": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/web-sockets": "2.11.0", "kleur": "^4.1.4", "selfsigned": "^2.0.0", "undici": "5.9.1", @@ -1459,36 +1460,36 @@ } }, "node_modules/@miniflare/kv": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.10.0.tgz", - "integrity": "sha512-3+u1lO77FnlS0lQ6b1VgM1E/ZgQ/zy/FU+SdBG5LUOIiv3x522VYHOApeJLnSEo0KtZUB22Ni0fWQM6DgpaREg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.11.0.tgz", + "integrity": "sha512-3m9dL2HBBN170V1JvwjjucR5zl4G3mlcsV6C1E7A2wLl2Z2TWvIx/tSY9hrhkD96dFnejwJ9qmPMbXMMuynhjg==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" }, "engines": { "node": ">=16.13" } }, "node_modules/@miniflare/queues": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.10.0.tgz", - "integrity": "sha512-WKdO6qI9rfS96KlCjazzPFf+qj6DPov4vONyf18+jzbRjRJh/xwWSk1/1h5A+gDPwVNG8TsNRPh9DW5OKBGNjw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.11.0.tgz", + "integrity": "sha512-fLHjdrNLKhn0LZM/aii/9GsAttFd+lWlGzK8HOg1R0vhfKBwEub4zntjMmOfFbDm1ntc21tdMK7n3ldUphwh5w==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" }, "engines": { "node": ">=16.7" } }, "node_modules/@miniflare/r2": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.10.0.tgz", - "integrity": "sha512-uC1CCWbwM1t8DdpZgrveg6+CkZLfTq+wUMqs20BC5rCT8u8UyRv6ZVRQ7pTPiswLyt1oYDTXsZJK7tjV0U0zew==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.11.0.tgz", + "integrity": "sha512-MKuyJ/gGNsK3eWbGdygvozqcyaZhM3C6NGHvoaZwH503dwN569j5DpatTWiHGFeDeSu64VqcIsGehz05GDUaag==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0", + "@miniflare/shared": "2.11.0", "undici": "5.9.1" }, "engines": { @@ -1496,25 +1497,25 @@ } }, "node_modules/@miniflare/runner-vm": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.10.0.tgz", - "integrity": "sha512-oTsHitQdQ1B1kT3G/6n9AEXsMd/sT1D8tLGzc7Xr79ZrxYxwRO0ATF3cdkxk4dUjUqg/RUqvOJV4YjJGyqvctg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.11.0.tgz", + "integrity": "sha512-bkVSuvCf5+VylqN8lTiLxIYqYcKFbl+BywZGwGQndPC/3wh42J00mM0jw4hRbvXgwuBhlUyCVpEXtYlftFFT/g==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" }, "engines": { "node": ">=16.13" } }, "node_modules/@miniflare/scheduler": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.10.0.tgz", - "integrity": "sha512-eGt2cZFE/yo585nT8xINQwdbTotZfeRIh6FUWmZkbva1i5SW0zTiOojr5a95vAGBF3TzwWGsUuzJpLhBB69a/g==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.11.0.tgz", + "integrity": "sha512-DPdzINhdWeS99eIicGoluMsD4pLTTAWNQbgCv3CTwgdKA3dxdvMSCkNqZzQLiALzvk9+rSfj46FlH++HE7o7/w==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "cron-schedule": "^3.0.4" }, "engines": { @@ -1522,9 +1523,9 @@ } }, "node_modules/@miniflare/shared": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.10.0.tgz", - "integrity": "sha512-GDSweEhJ3nNtStGm6taZGUNytM0QTQ/sjZSedAKyF1/aHRaZUcD9cuKAMgIbSpKfvgGdLMNS7Bhd8jb249TO7g==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.11.0.tgz", + "integrity": "sha512-fWMqq3ZkWAg+k7CnyzMV/rZHugwn+/JxvVzCxrtvxzwotTN547THlOxgZe8JAP23U9BiTxOfpTfnLvFEjAmegw==", "dev": true, "dependencies": { "@types/better-sqlite3": "^7.6.0", @@ -1537,64 +1538,64 @@ } }, "node_modules/@miniflare/sites": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.10.0.tgz", - "integrity": "sha512-1NVAT6+JS2OubL+pOOR5E/6MMddxQHWMi/yIDSumyyfXmj7Sm7n5dE1FvNPetggMP4f8+AjoyT9AYvdd1wkspQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.11.0.tgz", + "integrity": "sha512-qbefKdWZUJgsdLf+kCw03sn3h/92LZgJAbkOpP6bCrfWkXlJ37EQXO4KWdhn4Ghc7A6GwU1s1I/mdB64B3AewQ==", "dev": true, "dependencies": { - "@miniflare/kv": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/storage-file": "2.10.0" + "@miniflare/kv": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/storage-file": "2.11.0" }, "engines": { "node": ">=16.13" } }, "node_modules/@miniflare/storage-file": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.10.0.tgz", - "integrity": "sha512-K/cRIWiTl4+Z+VO6tl4VfuYXA3NLJgvGPV+BCRYD7uTKuPYHqDMErtD1BI1I7nc3WJhwIXfzJrAR3XXhSKKWQQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.11.0.tgz", + "integrity": "sha512-beWF/lTX74x7AiaSB+xQxywPSNdhtEKvqDkRui8eOJ5kqN2o4UaleLKQGgqmCw3WyHRIsckV7If1qpbNiLtWMw==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0", - "@miniflare/storage-memory": "2.10.0" + "@miniflare/shared": "2.11.0", + "@miniflare/storage-memory": "2.11.0" }, "engines": { "node": ">=16.13" } }, "node_modules/@miniflare/storage-memory": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.10.0.tgz", - "integrity": "sha512-ZATU+qZtJ9yG0umgTrOEUi9SU//YyDb8nYXMgqT4JHODYA3RTz1SyyiQSOOz589upJPdu1LN+0j8W24WGRwwxQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.11.0.tgz", + "integrity": "sha512-s0AhPww7fq/Jz80NbPb+ffhcVRKnfPi7H1dHTRTre2Ud23EVJjAWl2gat42x8NOT/Fu3/o/7A72DWQQJqfO98A==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" }, "engines": { "node": ">=16.13" } }, "node_modules/@miniflare/watcher": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.10.0.tgz", - "integrity": "sha512-X9CFYYyszfSYDzs07KhbWC2i08Dpyh3D60fPonYZcoZAfa5h9eATHUdRGvNCdax7awYp4b8bvU8upAI//OPlMg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.11.0.tgz", + "integrity": "sha512-RUfjz2iYcsQXLcGySemJl98CJ2iierbWsPGWZhIVZI+NNhROkEy77g/Q+lvP2ATwexG3/dUSfdJ3P8aH+sI4Ig==", "dev": true, "dependencies": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" }, "engines": { "node": ">=16.13" } }, "node_modules/@miniflare/web-sockets": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.10.0.tgz", - "integrity": "sha512-W+PrapdQqNEEFeD+amENgPQWcETGDp7OEh6JAoSzCRhHA0OoMe8DG0xb5a5+2FjGW/J7FFKsv84wkURpmFT4dQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.11.0.tgz", + "integrity": "sha512-NC8RKrmxrO0hZmwpzn5g4hPGA2VblnFTIBobmWoxuK95eW49zfs7dtE/PyFs+blsGv3CjTIjHVSQ782K+C6HFA==", "dev": true, "dependencies": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "undici": "5.9.1", "ws": "^8.2.2" }, @@ -1899,6 +1900,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, "node_modules/acorn": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", @@ -2061,6 +2068,15 @@ "node": "*" } }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3498,6 +3514,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/find-yarn-workspace-root2": { "version": "1.2.16", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", @@ -3863,9 +3888,9 @@ "dev": true }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/human-id": { @@ -4067,6 +4092,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4254,6 +4294,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4342,6 +4394,15 @@ "node": ">=0.10.0" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -4587,28 +4648,28 @@ } }, "node_modules/miniflare": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.10.0.tgz", - "integrity": "sha512-WPveqChVDdmDGv+wFqXjFqEZlZ5/aBlAKX37h/e4TAjl2XsK5nPfQATP8jZXwNDEC5iE29bYZymOqeZkp+t7OA==", - "dev": true, - "dependencies": { - "@miniflare/cache": "2.10.0", - "@miniflare/cli-parser": "2.10.0", - "@miniflare/core": "2.10.0", - "@miniflare/d1": "2.10.0", - "@miniflare/durable-objects": "2.10.0", - "@miniflare/html-rewriter": "2.10.0", - "@miniflare/http-server": "2.10.0", - "@miniflare/kv": "2.10.0", - "@miniflare/queues": "2.10.0", - "@miniflare/r2": "2.10.0", - "@miniflare/runner-vm": "2.10.0", - "@miniflare/scheduler": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/sites": "2.10.0", - "@miniflare/storage-file": "2.10.0", - "@miniflare/storage-memory": "2.10.0", - "@miniflare/web-sockets": "2.10.0", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.11.0.tgz", + "integrity": "sha512-QA18I1VQXdCo4nBtPJUcUDxW8c9xbc5ex5F61jwhkGVOISSnYdEheolESmjr8MYk28xwi0XD1ozS4rLaTONd+w==", + "dev": true, + "dependencies": { + "@miniflare/cache": "2.11.0", + "@miniflare/cli-parser": "2.11.0", + "@miniflare/core": "2.11.0", + "@miniflare/d1": "2.11.0", + "@miniflare/durable-objects": "2.11.0", + "@miniflare/html-rewriter": "2.11.0", + "@miniflare/http-server": "2.11.0", + "@miniflare/kv": "2.11.0", + "@miniflare/queues": "2.11.0", + "@miniflare/r2": "2.11.0", + "@miniflare/runner-vm": "2.11.0", + "@miniflare/scheduler": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/sites": "2.11.0", + "@miniflare/storage-file": "2.11.0", + "@miniflare/storage-memory": "2.11.0", + "@miniflare/web-sockets": "2.11.0", "kleur": "^4.1.4", "semiver": "^1.1.0", "source-map-support": "^0.5.20", @@ -4621,7 +4682,7 @@ "node": ">=16.13" }, "peerDependencies": { - "@miniflare/storage-redis": "2.10.0", + "@miniflare/storage-redis": "2.11.0", "cron-schedule": "^3.0.4", "ioredis": "^4.27.9" }, @@ -4738,6 +4799,12 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -4913,6 +4980,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -5041,6 +5124,177 @@ "integrity": "sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==", "dev": true }, + "node_modules/patch-package": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz", + "integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==", + "dev": true, + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^1.10.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=10", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/patch-package/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/patch-package/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/patch-package/node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/patch-package/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/patch-package/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/patch-package/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/patch-package/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/patch-package/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/patch-package/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/patch-package/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/patch-package/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -6708,21 +6962,21 @@ } }, "node_modules/wrangler": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.6.2.tgz", - "integrity": "sha512-+in4oEQXDs6+vE+1c6niBd3IrW1DMRTbauR6G0u3TpD6UaXOLwLdBxRLEbN3m82dN+WNm7l1MbFZrKc/TnWjhw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.8.1.tgz", + "integrity": "sha512-O4wUr6/FUpk9KVstOUVYbiiZcWc1jKo7q0FfdwEjnMB3oN7Ofs6cIiX++Lzj1ldFSCOw2/aW3UYgixch6B2WCA==", "dev": true, "dependencies": { "@cloudflare/kv-asset-handler": "^0.2.0", "@esbuild-plugins/node-globals-polyfill": "^0.1.1", "@esbuild-plugins/node-modules-polyfill": "^0.1.4", - "@miniflare/core": "2.10.0", - "@miniflare/d1": "2.10.0", - "@miniflare/durable-objects": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/d1": "2.11.0", + "@miniflare/durable-objects": "2.11.0", "blake3-wasm": "^2.1.5", "chokidar": "^3.5.3", "esbuild": "0.14.51", - "miniflare": "2.10.0", + "miniflare": "2.11.0", "nanoid": "^3.3.3", "path-to-regexp": "^6.2.0", "selfsigned": "^2.0.1", @@ -6808,16 +7062,16 @@ "dev": true }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", + "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", "dev": true, "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -6849,6 +7103,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", @@ -7904,37 +8167,37 @@ } }, "@miniflare/cache": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.10.0.tgz", - "integrity": "sha512-nzEqFVPnD7Yf0HMDv7gCPpf4NSXfjhc+zg3gSwUS4Dad5bWV10B1ujTZW6HxQulW3CBHIg616mTjXIiaimVuEQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.11.0.tgz", + "integrity": "sha512-L/kc9AzidPwFuk2fwHpAEePi0kNBk6FWUq3ln+9beRCDrPEpfVrDRFpNleF1NFZz5//oeVMuo8F0IVUQGzR7+Q==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "http-cache-semantics": "^4.1.0", "undici": "5.9.1" } }, "@miniflare/cli-parser": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.10.0.tgz", - "integrity": "sha512-NAiCtqlHTUKCmV+Jl9af+ixGmMhiGhIyIfr/vCdbismNEBxEsrQGg3sQYTNfvCkdHtODurQqayQreFq21OuEow==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.11.0.tgz", + "integrity": "sha512-JUmyRzEGAS6CouvXJwBh8p44onfw3KRpfq5JGXEuHModOGjTp6li7PQyCTNPV2Hv/7StAXWnTFGXeAqyDHuTig==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0", + "@miniflare/shared": "2.11.0", "kleur": "^4.1.4" } }, "@miniflare/core": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.10.0.tgz", - "integrity": "sha512-Jx1M5oXQua0jzsJVdZSq07baVRmGC/6JkglrPQGAlZ7gQ1sunVZzq9fjxFqj0bqfEuYS0Wy6+lvK4rOAHISIjw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.11.0.tgz", + "integrity": "sha512-UFMFiCG0co36VpZkgFrSBnrxo71uf1x+cjlzzJi3khmMyDlnLu4RuIQsAqvKbYom6fi3G9Q8lTgM7JuOXFyjhw==", "dev": true, "requires": { "@iarna/toml": "^2.2.5", - "@miniflare/queues": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/watcher": "2.10.0", + "@miniflare/queues": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/watcher": "2.11.0", "busboy": "^1.6.0", "dotenv": "^10.0.0", "kleur": "^4.1.4", @@ -7944,48 +8207,48 @@ } }, "@miniflare/d1": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.10.0.tgz", - "integrity": "sha512-mOYZSmpTthH0tmFTQ+O9G0Q+iDAd7oiUtoIBianlKa9QiqYAoO7EBUPy6kUgDHXapOcN5Ri1u3J5UTpxXvw3qg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/d1/-/d1-2.11.0.tgz", + "integrity": "sha512-aDdBVQZ2C0Zs3+Y9ZbRctmuQxozPfpumwJ/6NG6fBadANvune/hW7ddEoxyteIEU9W3IgzVj8s4by4VvasX90A==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0" + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0" } }, "@miniflare/durable-objects": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.10.0.tgz", - "integrity": "sha512-gU45f52gveFtCasm0ixYnt0mHI1lHrPomtmF+89oZGKBzOqUfO5diDs6wmoRSnovOWZCwtmwQGRoorAQN7AmoA==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.11.0.tgz", + "integrity": "sha512-0cKJaMgraTEU1b4kqK8cjD2oTeOjA6QU3Y+lWiZT/k1PMHZULovrSFnjii7qZ8npf4VHSIN6XYPxhyxRyEM65Q==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/storage-memory": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/storage-memory": "2.11.0", "undici": "5.9.1" } }, "@miniflare/html-rewriter": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.10.0.tgz", - "integrity": "sha512-hCdG99L8+Ros4dn3B5H37PlQPBH0859EoRslzNTd4jzGIkwdiawpJvrvesL8056GjbUjeJN1zh7OPBRuMgyGLw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.11.0.tgz", + "integrity": "sha512-olTqmuYTHnoTNtiA0vjQ/ixRfbwgPzDrAUbtXDCYW45VFbHfDVJrJGZX3Jg0HpSlxy86Zclle1SUxGbVDzxsBg==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "html-rewriter-wasm": "^0.4.1", "undici": "5.9.1" } }, "@miniflare/http-server": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.10.0.tgz", - "integrity": "sha512-cm6hwkONucll93yoY8dteMp//Knvmb7n6zAgeHrtuNYKn//lAL6bRY//VLTttrMmfWxZFi1C7WpOeCv8Mn6/ug==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.11.0.tgz", + "integrity": "sha512-sMLcrDFzqqAvnQmAUH0hRTo8sBjW79VZYfnIH5FAGSGcKX6kdAGs9RStdYZ4CftQCBAEQScX0KBsMx5FwJRe9Q==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/web-sockets": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/web-sockets": "2.11.0", "kleur": "^4.1.4", "selfsigned": "^2.0.0", "undici": "5.9.1", @@ -7994,57 +8257,57 @@ } }, "@miniflare/kv": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.10.0.tgz", - "integrity": "sha512-3+u1lO77FnlS0lQ6b1VgM1E/ZgQ/zy/FU+SdBG5LUOIiv3x522VYHOApeJLnSEo0KtZUB22Ni0fWQM6DgpaREg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.11.0.tgz", + "integrity": "sha512-3m9dL2HBBN170V1JvwjjucR5zl4G3mlcsV6C1E7A2wLl2Z2TWvIx/tSY9hrhkD96dFnejwJ9qmPMbXMMuynhjg==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" } }, "@miniflare/queues": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.10.0.tgz", - "integrity": "sha512-WKdO6qI9rfS96KlCjazzPFf+qj6DPov4vONyf18+jzbRjRJh/xwWSk1/1h5A+gDPwVNG8TsNRPh9DW5OKBGNjw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/queues/-/queues-2.11.0.tgz", + "integrity": "sha512-fLHjdrNLKhn0LZM/aii/9GsAttFd+lWlGzK8HOg1R0vhfKBwEub4zntjMmOfFbDm1ntc21tdMK7n3ldUphwh5w==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" } }, "@miniflare/r2": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.10.0.tgz", - "integrity": "sha512-uC1CCWbwM1t8DdpZgrveg6+CkZLfTq+wUMqs20BC5rCT8u8UyRv6ZVRQ7pTPiswLyt1oYDTXsZJK7tjV0U0zew==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/r2/-/r2-2.11.0.tgz", + "integrity": "sha512-MKuyJ/gGNsK3eWbGdygvozqcyaZhM3C6NGHvoaZwH503dwN569j5DpatTWiHGFeDeSu64VqcIsGehz05GDUaag==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0", + "@miniflare/shared": "2.11.0", "undici": "5.9.1" } }, "@miniflare/runner-vm": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.10.0.tgz", - "integrity": "sha512-oTsHitQdQ1B1kT3G/6n9AEXsMd/sT1D8tLGzc7Xr79ZrxYxwRO0ATF3cdkxk4dUjUqg/RUqvOJV4YjJGyqvctg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.11.0.tgz", + "integrity": "sha512-bkVSuvCf5+VylqN8lTiLxIYqYcKFbl+BywZGwGQndPC/3wh42J00mM0jw4hRbvXgwuBhlUyCVpEXtYlftFFT/g==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" } }, "@miniflare/scheduler": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.10.0.tgz", - "integrity": "sha512-eGt2cZFE/yo585nT8xINQwdbTotZfeRIh6FUWmZkbva1i5SW0zTiOojr5a95vAGBF3TzwWGsUuzJpLhBB69a/g==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.11.0.tgz", + "integrity": "sha512-DPdzINhdWeS99eIicGoluMsD4pLTTAWNQbgCv3CTwgdKA3dxdvMSCkNqZzQLiALzvk9+rSfj46FlH++HE7o7/w==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "cron-schedule": "^3.0.4" } }, "@miniflare/shared": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.10.0.tgz", - "integrity": "sha512-GDSweEhJ3nNtStGm6taZGUNytM0QTQ/sjZSedAKyF1/aHRaZUcD9cuKAMgIbSpKfvgGdLMNS7Bhd8jb249TO7g==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.11.0.tgz", + "integrity": "sha512-fWMqq3ZkWAg+k7CnyzMV/rZHugwn+/JxvVzCxrtvxzwotTN547THlOxgZe8JAP23U9BiTxOfpTfnLvFEjAmegw==", "dev": true, "requires": { "@types/better-sqlite3": "^7.6.0", @@ -8054,52 +8317,52 @@ } }, "@miniflare/sites": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.10.0.tgz", - "integrity": "sha512-1NVAT6+JS2OubL+pOOR5E/6MMddxQHWMi/yIDSumyyfXmj7Sm7n5dE1FvNPetggMP4f8+AjoyT9AYvdd1wkspQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.11.0.tgz", + "integrity": "sha512-qbefKdWZUJgsdLf+kCw03sn3h/92LZgJAbkOpP6bCrfWkXlJ37EQXO4KWdhn4Ghc7A6GwU1s1I/mdB64B3AewQ==", "dev": true, "requires": { - "@miniflare/kv": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/storage-file": "2.10.0" + "@miniflare/kv": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/storage-file": "2.11.0" } }, "@miniflare/storage-file": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.10.0.tgz", - "integrity": "sha512-K/cRIWiTl4+Z+VO6tl4VfuYXA3NLJgvGPV+BCRYD7uTKuPYHqDMErtD1BI1I7nc3WJhwIXfzJrAR3XXhSKKWQQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.11.0.tgz", + "integrity": "sha512-beWF/lTX74x7AiaSB+xQxywPSNdhtEKvqDkRui8eOJ5kqN2o4UaleLKQGgqmCw3WyHRIsckV7If1qpbNiLtWMw==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0", - "@miniflare/storage-memory": "2.10.0" + "@miniflare/shared": "2.11.0", + "@miniflare/storage-memory": "2.11.0" } }, "@miniflare/storage-memory": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.10.0.tgz", - "integrity": "sha512-ZATU+qZtJ9yG0umgTrOEUi9SU//YyDb8nYXMgqT4JHODYA3RTz1SyyiQSOOz589upJPdu1LN+0j8W24WGRwwxQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.11.0.tgz", + "integrity": "sha512-s0AhPww7fq/Jz80NbPb+ffhcVRKnfPi7H1dHTRTre2Ud23EVJjAWl2gat42x8NOT/Fu3/o/7A72DWQQJqfO98A==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" } }, "@miniflare/watcher": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.10.0.tgz", - "integrity": "sha512-X9CFYYyszfSYDzs07KhbWC2i08Dpyh3D60fPonYZcoZAfa5h9eATHUdRGvNCdax7awYp4b8bvU8upAI//OPlMg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.11.0.tgz", + "integrity": "sha512-RUfjz2iYcsQXLcGySemJl98CJ2iierbWsPGWZhIVZI+NNhROkEy77g/Q+lvP2ATwexG3/dUSfdJ3P8aH+sI4Ig==", "dev": true, "requires": { - "@miniflare/shared": "2.10.0" + "@miniflare/shared": "2.11.0" } }, "@miniflare/web-sockets": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.10.0.tgz", - "integrity": "sha512-W+PrapdQqNEEFeD+amENgPQWcETGDp7OEh6JAoSzCRhHA0OoMe8DG0xb5a5+2FjGW/J7FFKsv84wkURpmFT4dQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.11.0.tgz", + "integrity": "sha512-NC8RKrmxrO0hZmwpzn5g4hPGA2VblnFTIBobmWoxuK95eW49zfs7dtE/PyFs+blsGv3CjTIjHVSQ782K+C6HFA==", "dev": true, "requires": { - "@miniflare/core": "2.10.0", - "@miniflare/shared": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/shared": "2.11.0", "undici": "5.9.1", "ws": "^8.2.2" } @@ -8303,6 +8566,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, "acorn": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", @@ -8414,6 +8683,12 @@ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -9432,6 +9707,15 @@ "path-exists": "^4.0.0" } }, + "find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "requires": { + "micromatch": "^4.0.2" + } + }, "find-yarn-workspace-root2": { "version": "1.2.16", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", @@ -9700,9 +9984,9 @@ "dev": true }, "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "human-id": { @@ -9850,6 +10134,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -9971,6 +10261,15 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -10046,6 +10345,15 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11" + } + }, "kleur": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", @@ -10229,28 +10537,28 @@ "dev": true }, "miniflare": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.10.0.tgz", - "integrity": "sha512-WPveqChVDdmDGv+wFqXjFqEZlZ5/aBlAKX37h/e4TAjl2XsK5nPfQATP8jZXwNDEC5iE29bYZymOqeZkp+t7OA==", - "dev": true, - "requires": { - "@miniflare/cache": "2.10.0", - "@miniflare/cli-parser": "2.10.0", - "@miniflare/core": "2.10.0", - "@miniflare/d1": "2.10.0", - "@miniflare/durable-objects": "2.10.0", - "@miniflare/html-rewriter": "2.10.0", - "@miniflare/http-server": "2.10.0", - "@miniflare/kv": "2.10.0", - "@miniflare/queues": "2.10.0", - "@miniflare/r2": "2.10.0", - "@miniflare/runner-vm": "2.10.0", - "@miniflare/scheduler": "2.10.0", - "@miniflare/shared": "2.10.0", - "@miniflare/sites": "2.10.0", - "@miniflare/storage-file": "2.10.0", - "@miniflare/storage-memory": "2.10.0", - "@miniflare/web-sockets": "2.10.0", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.11.0.tgz", + "integrity": "sha512-QA18I1VQXdCo4nBtPJUcUDxW8c9xbc5ex5F61jwhkGVOISSnYdEheolESmjr8MYk28xwi0XD1ozS4rLaTONd+w==", + "dev": true, + "requires": { + "@miniflare/cache": "2.11.0", + "@miniflare/cli-parser": "2.11.0", + "@miniflare/core": "2.11.0", + "@miniflare/d1": "2.11.0", + "@miniflare/durable-objects": "2.11.0", + "@miniflare/html-rewriter": "2.11.0", + "@miniflare/http-server": "2.11.0", + "@miniflare/kv": "2.11.0", + "@miniflare/queues": "2.11.0", + "@miniflare/r2": "2.11.0", + "@miniflare/runner-vm": "2.11.0", + "@miniflare/scheduler": "2.11.0", + "@miniflare/shared": "2.11.0", + "@miniflare/sites": "2.11.0", + "@miniflare/storage-file": "2.11.0", + "@miniflare/storage-memory": "2.11.0", + "@miniflare/web-sockets": "2.11.0", "kleur": "^4.1.4", "semiver": "^1.1.0", "source-map-support": "^0.5.20", @@ -10339,6 +10647,12 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -10462,6 +10776,16 @@ "mimic-fn": "^4.0.0" } }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -10554,6 +10878,137 @@ "integrity": "sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==", "dev": true }, + "patch-package": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz", + "integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==", + "dev": true, + "requires": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "cross-spawn": "^6.0.5", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "is-ci": "^2.0.0", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^5.6.0", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^1.10.2" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -11765,22 +12220,22 @@ "dev": true }, "wrangler": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.6.2.tgz", - "integrity": "sha512-+in4oEQXDs6+vE+1c6niBd3IrW1DMRTbauR6G0u3TpD6UaXOLwLdBxRLEbN3m82dN+WNm7l1MbFZrKc/TnWjhw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.8.1.tgz", + "integrity": "sha512-O4wUr6/FUpk9KVstOUVYbiiZcWc1jKo7q0FfdwEjnMB3oN7Ofs6cIiX++Lzj1ldFSCOw2/aW3UYgixch6B2WCA==", "dev": true, "requires": { "@cloudflare/kv-asset-handler": "^0.2.0", "@esbuild-plugins/node-globals-polyfill": "^0.1.1", "@esbuild-plugins/node-modules-polyfill": "^0.1.4", - "@miniflare/core": "2.10.0", - "@miniflare/d1": "2.10.0", - "@miniflare/durable-objects": "2.10.0", + "@miniflare/core": "2.11.0", + "@miniflare/d1": "2.11.0", + "@miniflare/durable-objects": "2.11.0", "blake3-wasm": "^2.1.5", "chokidar": "^3.5.3", "esbuild": "0.14.51", "fsevents": "~2.3.2", - "miniflare": "2.10.0", + "miniflare": "2.11.0", "nanoid": "^3.3.3", "path-to-regexp": "^6.2.0", "selfsigned": "^2.0.1", @@ -11842,9 +12297,9 @@ "dev": true }, "ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", + "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", "dev": true, "requires": {} }, @@ -11866,6 +12321,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, "yargs": { "version": "17.6.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", diff --git a/package.json b/package.json index 2f443ca..733760c 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "jaeger" ], "scripts": { + "postinstall": "patch-package", "build": "npm run build:esm && npm run build:cjs && npm run build:types", "build:esm": "node build.js esm", "build:cjs": "node build.js cjs", @@ -55,7 +56,8 @@ "esbuild-plugin-replace": "^1.3.0", "eslint": "^8.30.0", "eslint-plugin-import": "^2.26.0", + "patch-package": "^6.5.1", "vitest": "^0.26.2", - "wrangler": "^2.6.2" + "wrangler": "^2.8.1" } } diff --git a/patches/wrangler+2.8.1.patch b/patches/wrangler+2.8.1.patch new file mode 100644 index 0000000..7656ecc --- /dev/null +++ b/patches/wrangler+2.8.1.patch @@ -0,0 +1,17 @@ +diff --git a/node_modules/wrangler/wrangler-dist/cli.js b/node_modules/wrangler/wrangler-dist/cli.js +index 03ad293..78577e8 100644 +--- a/node_modules/wrangler/wrangler-dist/cli.js ++++ b/node_modules/wrangler/wrangler-dist/cli.js +@@ -144677,7 +144677,11 @@ function parseRequestInput(readyAddress, readyPort, input, init, protocol = "htt + input = `${protocol}://${readyAddress}:${readyPort}${input.pathname}`; + } else if (typeof input === "string") { + try { +- input = `${protocol}://${readyAddress}:${readyPort}${new URL(input).pathname}`; ++ const url = new URL(input); ++ url.protocol = `${protocol}:`; ++ url.hostname = readyAddress; ++ url.port = readyPort; ++ input = url.toString(); + } catch { + input = `${protocol}://${readyAddress}:${readyPort}${input}`; + } diff --git a/src/exporters/otlp.ts b/src/exporters/otlp.ts index 17527ca..242c640 100644 --- a/src/exporters/otlp.ts +++ b/src/exporters/otlp.ts @@ -195,7 +195,7 @@ export class OtlpExporter extends Exporter { // if (sampled) flags |= SAMPLED return { - traceparent: `${numberToHex(VERSION, 2)}-${span.getTraceId()}-${span.getSpanId()}-${numberToHex(flags)}`, + traceparent: `${numberToHex(VERSION, 2)}-${span.getTraceId()}-${span.getSpanId()}-${numberToHex(flags, 2)}`, }; } diff --git a/src/trace.ts b/src/trace.ts index 0554e24..ac5da0a 100644 --- a/src/trace.ts +++ b/src/trace.ts @@ -1,3 +1,4 @@ +import { OtlpExporter } from './exporters/otlp'; import { Span, Trace } from './tracing'; import { CfWithTrace, SpanContext, SpanCreationOptions, TracedFn, TracerOptions } from './types'; @@ -23,6 +24,12 @@ export function createTrace( } } + const exporter = tracerOptions.collector.exporter ?? new OtlpExporter(); + const context = exporter.readContextHeaders(req.headers); + if (context !== null) { + parentContext = context; + } + const trace = new Trace(ctx, { traceContext: parentContext, ...tracerOptions, @@ -39,13 +46,13 @@ export function traceFn( ): T { const span = parent.startSpan(name, opts); - const value = fn(); + const value = fn(span); if (value instanceof Promise) { value.finally(() => span.end()); return value; } - + span.end(); return value; } diff --git a/src/tracing.ts b/src/tracing.ts index 4af8ce1..524c9dd 100644 --- a/src/tracing.ts +++ b/src/tracing.ts @@ -110,10 +110,12 @@ export class Span { requestInit?: RequestInit | Request, spanOpts?: SpanCreationOptions, ): Promise { - const tracedRequest = new Request(request, requestInit); - this.injectPropagation(tracedRequest); + return traceFn(this, SPAN_NAME.FETCH, (span) => { + const tracedRequest = new Request(request, requestInit); - return traceFn(this, SPAN_NAME.FETCH, () => fetch(tracedRequest), spanOpts); + span.injectPropagation(tracedRequest); + return fetch(tracedRequest); + }, spanOpts); } buildSpan(name: string) { diff --git a/src/types.ts b/src/types.ts index fe430a7..2232bbb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { StatusCode, Trace } from './tracing'; +import { Span, StatusCode, Trace } from './tracing'; import { Exporter } from './exporters/exporter'; export interface TraceData { @@ -143,4 +143,4 @@ export type CfWithTrace = IncomingRequestCfProperties & { traceContext?: SpanContext; } -export type TracedFn = (...args: unknown[]) => T; +export type TracedFn = (span: Span) => T; diff --git a/src/utils/hex.ts b/src/utils/hex.ts index fb3f2f3..3813469 100644 --- a/src/utils/hex.ts +++ b/src/utils/hex.ts @@ -1,4 +1,4 @@ -const HEX_REGEX = /[a-f0-9]+/g; +const HEX_REGEX = /[a-f0-9]+/; export function isHex(str: string) { return HEX_REGEX.test(str); diff --git a/test/otlp-exporter.test.ts b/test/otlp-exporter.test.ts index ea069a1..074f452 100644 --- a/test/otlp-exporter.test.ts +++ b/test/otlp-exporter.test.ts @@ -8,6 +8,8 @@ import { startCollector, startWorker } from './utils/worker'; let devWorker: UnstableDevWorker; let collectorWorker: UnstableDevWorker; +const SCRIPT_PATH = 'test/scripts/otlp'; + describe('Test OTLP Exporter', () => { beforeAll(async () => { collectorWorker = await startCollector({ port: 4318 }); @@ -27,7 +29,7 @@ describe('Test OTLP Exporter', () => { } }); - test('Basic trace should transform correctly', async () => { + test.skip('Basic trace should transform correctly', async () => { devWorker = await startWorker('test/scripts/otlp/basic.ts'); const res = await devWorker.fetch('http://worker/test'); @@ -54,7 +56,7 @@ describe('Test OTLP Exporter', () => { expect(span.name).toBe('Request'); }); - describe('Resource', () => { + describe.skip('Resource', () => { test('Default attributes are put on resource', async () => { devWorker = await startWorker('test/scripts/otlp/basic.ts'); @@ -134,7 +136,7 @@ describe('Test OTLP Exporter', () => { }); }); - describe('Single span', () => { + describe.skip('Single span', () => { test('You can add a single span', async () => { devWorker = await startWorker('test/scripts/otlp/single-span.ts'); @@ -323,7 +325,7 @@ describe('Test OTLP Exporter', () => { }); }); - describe('Multiple spans', () => { + describe.skip('Multiple spans', () => { test('You can add multiple spans', async () => { devWorker = await startWorker('test/scripts/otlp/multiple-spans.ts', { kv: [ { binding: 'KV', id: '' } ], @@ -569,7 +571,7 @@ describe('Test OTLP Exporter', () => { }); }); - describe('Child of child span', () => { + describe.skip('Child of child span', () => { test('You can add a child to a child span', async () => { devWorker = await startWorker('test/scripts/otlp/span-span.ts', { kv: [ { binding: 'KV', id: '' } ], @@ -818,4 +820,100 @@ describe('Test OTLP Exporter', () => { .toStrictEqual({ key: ATTRIBUTE_NAME.KV_KEY, value: { stringValue: 'abc' } }); }); }); + + describe('Propagation', () => { + test('Can pass context in fetch', async () => { + devWorker = await startWorker(`${SCRIPT_PATH}/propagation/test-id.ts`); + + const worker = await startWorker(`${SCRIPT_PATH}/propagation/basic-fetch.ts`); + + const res = await worker.fetch(`http://worker/?address=${devWorker.address}&port=${devWorker.port}`); + + expect(res.status).toBe(200); + + const traceId = res.headers.get('trace-id'); + if (traceId === null) { + expect(traceId).not.toBeNull(); + return; + } + const spanId = res.headers.get('span-id'); + if (spanId === null) { + expect(spanId).not.toBeNull(); + return; + } + const fetchedTraceId = res.headers.get('fetched-trace-id'); + if (fetchedTraceId === null) { + expect(fetchedTraceId).not.toBeNull(); + return; + } + const fetchedParentId = res.headers.get('fetched-parent-id'); + if (fetchedParentId === null) { + expect(fetchedParentId).not.toBeNull(); + return; + } + + const trace = await getTrace(collectorWorker, traceId); + + // Validate the context was passed down + expect(fetchedTraceId).toBe(traceId); + expect(fetchedParentId).toBe(spanId); + + // Root + 1 child + expect(trace.resourceSpans.length).toBe(1); + const resourceSpan = trace.resourceSpans[0]; + + expect(resourceSpan.scopeSpans.length).toBe(1); + expect(resourceSpan.scopeSpans[0].scope.name).toBe('basic-fetch'); + expect(resourceSpan.scopeSpans[0].spans.length).toBe(2); + + await worker.stop(); + }); + + test('Context is passed in tracedFetch', async () => { + devWorker = await startWorker(`${SCRIPT_PATH}/propagation/test-id.ts`); + + const worker = await startWorker(`${SCRIPT_PATH}/propagation/traced-fetch.ts`); + + const res = await worker.fetch(`http://worker/?address=${devWorker.address}&port=${devWorker.port}`); + + expect(res.status).toBe(200); + + const traceId = res.headers.get('trace-id'); + if (traceId === null) { + expect(traceId).not.toBeNull(); + return; + } + const spanId = res.headers.get('span-id'); + if (spanId === null) { + expect(spanId).not.toBeNull(); + return; + } + const fetchedTraceId = res.headers.get('fetched-trace-id'); + if (fetchedTraceId === null) { + expect(fetchedTraceId).not.toBeNull(); + return; + } + const fetchedParentId = res.headers.get('fetched-parent-id'); + if (fetchedParentId === null) { + expect(fetchedParentId).not.toBeNull(); + return; + } + + const trace = await getTrace(collectorWorker, traceId); + + // Validate the context was passed down + expect(fetchedTraceId).toBe(traceId); + expect(fetchedParentId).toBe(spanId); + + // Root + 1 child + expect(trace.resourceSpans.length).toBe(1); + const resourceSpan = trace.resourceSpans[0]; + + expect(resourceSpan.scopeSpans.length).toBe(1); + expect(resourceSpan.scopeSpans[0].scope.name).toBe('traced-fetch'); + expect(resourceSpan.scopeSpans[0].spans.length).toBe(2); + + await worker.stop(); + }); + }); }); diff --git a/test/scripts/otlp/propagation/basic-fetch.ts b/test/scripts/otlp/propagation/basic-fetch.ts new file mode 100644 index 0000000..cdcabb6 --- /dev/null +++ b/test/scripts/otlp/propagation/basic-fetch.ts @@ -0,0 +1,41 @@ +import { createTrace } from 'src/trace'; +import { OtlpExporter } from 'src/exporters/otlp'; + +interface Env {} + +export default { + async fetch(req: Request, env: Env, ctx: ExecutionContext) { + const exporter = new OtlpExporter(); + const trace = createTrace(req, env, ctx, { + serviceName: 'basic-fetch', + collector: { + url: 'http://0.0.0.0:4318/v1/traces', // OTLP compatible Jaeger endpoint + exporter: exporter, + }, + }); + + const url = new URL(req.url); + const address = url.searchParams.get('address'); + const port = url.searchParams.get('port'); + + const span = trace.startSpan('fetch'); + const res = await fetch(`http://${address}:${port}/test`, { + headers: { + ...exporter.injectContextHeaders(span), + }, + }); + span.end(); + + const context = await res.json<{ traceId: string, parentId: string }>(); + + await trace.send(); + return new Response('ok', { + headers: { + 'trace-id': trace.getTraceId(), + 'span-id': span.getSpanId(), + 'fetched-trace-id': context.traceId, + 'fetched-parent-id': context.parentId, + }, + }); + }, +}; diff --git a/test/scripts/otlp/propagation/test-id.ts b/test/scripts/otlp/propagation/test-id.ts new file mode 100644 index 0000000..090fa00 --- /dev/null +++ b/test/scripts/otlp/propagation/test-id.ts @@ -0,0 +1,21 @@ +import { createTrace } from 'src/trace'; +import { OtlpExporter } from 'src/exporters/otlp'; + +interface Env {} + +export default { + async fetch(req: Request, env: Env, ctx: ExecutionContext) { + const trace = createTrace(req, env, ctx, { + serviceName: 'test-ids', + collector: { + url: 'http://0.0.0.0:4318/v1/traces', // OTLP compatible Jaeger endpoint + exporter: new OtlpExporter(), + }, + }); + + return Response.json({ + traceId: trace.getTraceId(), + parentId: trace.getData().parentId, + }); + }, +}; diff --git a/test/scripts/otlp/propagation/traced-fetch.ts b/test/scripts/otlp/propagation/traced-fetch.ts new file mode 100644 index 0000000..ea1d75c --- /dev/null +++ b/test/scripts/otlp/propagation/traced-fetch.ts @@ -0,0 +1,34 @@ +import { createTrace } from 'src/trace'; +import { OtlpExporter } from 'src/exporters/otlp'; + +interface Env {} + +export default { + async fetch(req: Request, env: Env, ctx: ExecutionContext) { + const exporter = new OtlpExporter(); + const trace = createTrace(req, env, ctx, { + serviceName: 'traced-fetch', + collector: { + url: 'http://0.0.0.0:4318/v1/traces', // OTLP compatible Jaeger endpoint + exporter: exporter, + }, + }); + + const url = new URL(req.url); + const address = url.searchParams.get('address'); + const port = url.searchParams.get('port'); + + const res = await trace.tracedFetch(`http://${address}:${port}/test`); + const context = await res.json<{ traceId: string, parentId: string }>(); + + await trace.send(); + return new Response('ok', { + headers: { + 'trace-id': trace.getTraceId(), + 'span-id': trace.getChildSpans()[0].getSpanId(), + 'fetched-trace-id': context.traceId, + 'fetched-parent-id': context.parentId, + }, + }); + }, +}; From 6ff7f89c58490a39ebc6647dc0cdb78351e9eea5 Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 21:00:35 +0000 Subject: [PATCH 10/12] Zipkin support and tests --- src/exporters/zipkin.ts | 27 +++- src/trace.ts | 9 ++ test/otlp-exporter.test.ts | 12 +- .../scripts/zipkin/propagation/basic-fetch.ts | 41 ++++++ test/scripts/zipkin/propagation/test-id.ts | 21 +++ .../zipkin/propagation/traced-fetch.ts | 34 +++++ test/zipkin-exporter.test.ts | 126 +++++++++++++++++- 7 files changed, 258 insertions(+), 12 deletions(-) create mode 100644 test/scripts/zipkin/propagation/basic-fetch.ts create mode 100644 test/scripts/zipkin/propagation/test-id.ts create mode 100644 test/scripts/zipkin/propagation/traced-fetch.ts diff --git a/src/exporters/zipkin.ts b/src/exporters/zipkin.ts index 0573555..989a6e2 100644 --- a/src/exporters/zipkin.ts +++ b/src/exporters/zipkin.ts @@ -1,6 +1,8 @@ import { Span, Trace } from 'src/tracing'; import { generateSpanId } from 'src/utils/rand'; +import { isHex } from 'src/utils/hex'; import { Exporter } from './exporter'; +import type { SpanContext } from 'src/types'; export type ZipkinJson = ZipkinSpan[]; @@ -65,15 +67,36 @@ export class ZipkinExporter extends Exporter { return spans; } - getContextHeaders(span: Span): Record { + injectContextHeaders(span: Span): Record { // https://github.com/openzipkin/b3-propagation + // https://github.com/openzipkin/b3-propagation#why-is-parentspanid-propagated return { 'X-B3-TraceId': span.getTraceId(), 'X-B3-ParentSpanId': span.getSpanId(), - 'X-B3-SpanId': generateSpanId(), // TODO: Figure out what I want to do here + 'X-B3-SpanId': generateSpanId(), 'X-B3-Sampled': '1', // TODO: Implement sampling }; } + + readContextHeaders(headers: Headers): SpanContext | null { + const traceId = headers.get('X-B3-TraceId'); + const spanId = headers.get('X-B3-ParentSpanId'); + + if (!traceId || !spanId) { + return null; + } + + // Validation + if ((traceId.length !== 32 && traceId.length !== 16) + || !isHex(traceId) + || spanId.length !== 16 + || !isHex(spanId) + ) { + return null; + } + + return { traceId, spanId }; + } } export class ZipkinTransformer extends ZipkinExporter {} diff --git a/src/trace.ts b/src/trace.ts index ac5da0a..b2f2ed4 100644 --- a/src/trace.ts +++ b/src/trace.ts @@ -30,6 +30,15 @@ export function createTrace( parentContext = context; } + // Set the `exporter` to `transformer` if defined to keep backwards compat + // Likewise, set the `transformer` if `exporter` is set + // TODO: Remove + if (tracerOptions.collector.transformer && !tracerOptions.collector.exporter) { + tracerOptions.collector.exporter = tracerOptions.collector.transformer; + } else if (tracerOptions.collector.exporter && !tracerOptions.collector.transformer) { + tracerOptions.collector.transformer = tracerOptions.collector.exporter; + } + const trace = new Trace(ctx, { traceContext: parentContext, ...tracerOptions, diff --git a/test/otlp-exporter.test.ts b/test/otlp-exporter.test.ts index 074f452..04d5623 100644 --- a/test/otlp-exporter.test.ts +++ b/test/otlp-exporter.test.ts @@ -29,7 +29,7 @@ describe('Test OTLP Exporter', () => { } }); - test.skip('Basic trace should transform correctly', async () => { + test('Basic trace should transform correctly', async () => { devWorker = await startWorker('test/scripts/otlp/basic.ts'); const res = await devWorker.fetch('http://worker/test'); @@ -56,7 +56,7 @@ describe('Test OTLP Exporter', () => { expect(span.name).toBe('Request'); }); - describe.skip('Resource', () => { + describe('Resource', () => { test('Default attributes are put on resource', async () => { devWorker = await startWorker('test/scripts/otlp/basic.ts'); @@ -136,7 +136,7 @@ describe('Test OTLP Exporter', () => { }); }); - describe.skip('Single span', () => { + describe('Single span', () => { test('You can add a single span', async () => { devWorker = await startWorker('test/scripts/otlp/single-span.ts'); @@ -325,7 +325,7 @@ describe('Test OTLP Exporter', () => { }); }); - describe.skip('Multiple spans', () => { + describe('Multiple spans', () => { test('You can add multiple spans', async () => { devWorker = await startWorker('test/scripts/otlp/multiple-spans.ts', { kv: [ { binding: 'KV', id: '' } ], @@ -571,7 +571,7 @@ describe('Test OTLP Exporter', () => { }); }); - describe.skip('Child of child span', () => { + describe('Child of child span', () => { test('You can add a child to a child span', async () => { devWorker = await startWorker('test/scripts/otlp/span-span.ts', { kv: [ { binding: 'KV', id: '' } ], @@ -915,5 +915,7 @@ describe('Test OTLP Exporter', () => { await worker.stop(); }); + + test.todo('Can pass context in service binding'); }); }); diff --git a/test/scripts/zipkin/propagation/basic-fetch.ts b/test/scripts/zipkin/propagation/basic-fetch.ts new file mode 100644 index 0000000..659e110 --- /dev/null +++ b/test/scripts/zipkin/propagation/basic-fetch.ts @@ -0,0 +1,41 @@ +import { createTrace } from 'src/trace'; +import { ZipkinExporter } from 'src/exporters/zipkin'; + +interface Env {} + +export default { + async fetch(req: Request, env: Env, ctx: ExecutionContext) { + const exporter = new ZipkinExporter(); + const trace = createTrace(req, env, ctx, { + serviceName: 'basic-fetch', + collector: { + url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint + exporter: exporter, + }, + }); + + const url = new URL(req.url); + const address = url.searchParams.get('address'); + const port = url.searchParams.get('port'); + + const span = trace.startSpan('fetch'); + const res = await fetch(`http://${address}:${port}/test`, { + headers: { + ...exporter.injectContextHeaders(span), + }, + }); + span.end(); + + const context = await res.json<{ traceId: string, parentId: string }>(); + + await trace.send(); + return new Response('ok', { + headers: { + 'trace-id': trace.getTraceId(), + 'span-id': span.getSpanId(), + 'fetched-trace-id': context.traceId, + 'fetched-parent-id': context.parentId, + }, + }); + }, +}; diff --git a/test/scripts/zipkin/propagation/test-id.ts b/test/scripts/zipkin/propagation/test-id.ts new file mode 100644 index 0000000..f9cb84d --- /dev/null +++ b/test/scripts/zipkin/propagation/test-id.ts @@ -0,0 +1,21 @@ +import { createTrace } from 'src/trace'; +import { ZipkinExporter } from 'src/exporters/zipkin'; + +interface Env {} + +export default { + async fetch(req: Request, env: Env, ctx: ExecutionContext) { + const trace = createTrace(req, env, ctx, { + serviceName: 'test-ids', + collector: { + url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint + exporter: new ZipkinExporter(), + }, + }); + + return Response.json({ + traceId: trace.getTraceId(), + parentId: trace.getData().parentId, + }); + }, +}; diff --git a/test/scripts/zipkin/propagation/traced-fetch.ts b/test/scripts/zipkin/propagation/traced-fetch.ts new file mode 100644 index 0000000..ebb3c4d --- /dev/null +++ b/test/scripts/zipkin/propagation/traced-fetch.ts @@ -0,0 +1,34 @@ +import { createTrace } from 'src/trace'; +import { ZipkinExporter } from 'src/exporters/zipkin'; + +interface Env {} + +export default { + async fetch(req: Request, env: Env, ctx: ExecutionContext) { + const exporter = new ZipkinExporter(); + const trace = createTrace(req, env, ctx, { + serviceName: 'traced-fetch', + collector: { + url: 'http://0.0.0.0:9411/api/v2/spans', // Zipkin compatible Jaeger endpoint + exporter: exporter, + }, + }); + + const url = new URL(req.url); + const address = url.searchParams.get('address'); + const port = url.searchParams.get('port'); + + const res = await trace.tracedFetch(`http://${address}:${port}/test`); + const context = await res.json<{ traceId: string, parentId: string }>(); + + await trace.send(); + return new Response('ok', { + headers: { + 'trace-id': trace.getTraceId(), + 'span-id': trace.getChildSpans()[0].getSpanId(), + 'fetched-trace-id': context.traceId, + 'fetched-parent-id': context.parentId, + }, + }); + }, +}; diff --git a/test/zipkin-exporter.test.ts b/test/zipkin-exporter.test.ts index cdd2cfc..42a0c78 100644 --- a/test/zipkin-exporter.test.ts +++ b/test/zipkin-exporter.test.ts @@ -8,6 +8,8 @@ import { startCollector, startWorker } from './utils/worker'; let devWorker: UnstableDevWorker; let collectorWorker: UnstableDevWorker; +const SCRIPT_PATH = 'test/scripts/zipkin'; + describe('Test Zipkin Exporter', () => { beforeAll(async () => { collectorWorker = await startCollector({ port: 9411 }); @@ -27,7 +29,7 @@ describe('Test Zipkin Exporter', () => { } }); - test('Basic trace should transform correctly', async () => { + test.skip('Basic trace should transform correctly', async () => { devWorker = await startWorker('test/scripts/zipkin/basic.ts'); const res = await devWorker.fetch('http://worker/test'); @@ -48,7 +50,7 @@ describe('Test Zipkin Exporter', () => { expect(span.localEndpoint.serviceName).toBe('zipkin-basic'); }); - describe('Root span', () => { + describe.skip('Root span', () => { test('Default attributes are put on root span', async () => { devWorker = await startWorker('test/scripts/zipkin/basic.ts'); @@ -109,7 +111,7 @@ describe('Test Zipkin Exporter', () => { }); }); - describe('Single span', () => { + describe.skip('Single span', () => { test('You can add a single span', async () => { devWorker = await startWorker('test/scripts/zipkin/single-span.ts'); @@ -255,7 +257,7 @@ describe('Test Zipkin Exporter', () => { }); }); - describe('Multiple spans', () => { + describe.skip('Multiple spans', () => { test('You can add multiple spans', async () => { devWorker = await startWorker('test/scripts/zipkin/multiple-spans.ts', { kv: [ { binding: 'KV', id: '' } ], @@ -449,7 +451,7 @@ describe('Test Zipkin Exporter', () => { }); }); - describe('Child of child span', () => { + describe.skip('Child of child span', () => { test('You can add a child to a child span', async () => { devWorker = await startWorker('test/scripts/zipkin/span-span.ts', { kv: [ { binding: 'KV', id: '' } ], @@ -646,4 +648,118 @@ describe('Test Zipkin Exporter', () => { expect(secondChildSpan.annotations?.[0].timestamp).not.toBe(0); }); }); + + describe('Propagation', () => { + test('Can pass context in fetch', async () => { + devWorker = await startWorker(`${SCRIPT_PATH}/propagation/test-id.ts`); + + const worker = await startWorker(`${SCRIPT_PATH}/propagation/basic-fetch.ts`); + + const res = await worker.fetch(`http://worker/?address=${devWorker.address}&port=${devWorker.port}`); + + expect(res.status).toBe(200); + + const traceId = res.headers.get('trace-id'); + if (traceId === null) { + expect(traceId).not.toBeNull(); + return; + } + const spanId = res.headers.get('span-id'); + if (spanId === null) { + expect(spanId).not.toBeNull(); + return; + } + const fetchedTraceId = res.headers.get('fetched-trace-id'); + if (fetchedTraceId === null) { + expect(fetchedTraceId).not.toBeNull(); + return; + } + const fetchedParentId = res.headers.get('fetched-parent-id'); + if (fetchedParentId === null) { + expect(fetchedParentId).not.toBeNull(); + return; + } + + const trace = await getTrace(collectorWorker, traceId); + + // Validate the context was passed down + expect(fetchedTraceId).toBe(traceId); + expect(fetchedParentId).toBe(spanId); + + // Root + 1 child + expect(trace.length).toBe(2); + + // Root span + const rootSpan = trace[0]; + expect(rootSpan.traceId).toBe(traceId); + expect(rootSpan.name).toBe('Request'); + expect(rootSpan.localEndpoint.serviceName).toBe('basic-fetch'); + + // First child span + const firstChildSpan = trace[1]; + expect(firstChildSpan.traceId).toBe(traceId); + expect(firstChildSpan.parentId).toBe(rootSpan.id); + expect(firstChildSpan.name).toBe(SPAN_NAME.FETCH); + expect(firstChildSpan.duration).not.toBe(0); + + await worker.stop(); + }); + + test('Context is passed in tracedFetch', async () => { + devWorker = await startWorker(`${SCRIPT_PATH}/propagation/test-id.ts`); + + const worker = await startWorker(`${SCRIPT_PATH}/propagation/traced-fetch.ts`); + + const res = await worker.fetch(`http://worker/?address=${devWorker.address}&port=${devWorker.port}`); + + expect(res.status).toBe(200); + + const traceId = res.headers.get('trace-id'); + if (traceId === null) { + expect(traceId).not.toBeNull(); + return; + } + const spanId = res.headers.get('span-id'); + if (spanId === null) { + expect(spanId).not.toBeNull(); + return; + } + const fetchedTraceId = res.headers.get('fetched-trace-id'); + if (fetchedTraceId === null) { + expect(fetchedTraceId).not.toBeNull(); + return; + } + const fetchedParentId = res.headers.get('fetched-parent-id'); + if (fetchedParentId === null) { + expect(fetchedParentId).not.toBeNull(); + return; + } + + const trace = await getTrace(collectorWorker, traceId); + + // Validate the context was passed down + expect(fetchedTraceId).toBe(traceId); + expect(fetchedParentId).toBe(spanId); + + // Root + 1 child + expect(trace.length).toBe(2); + + // Root span + const rootSpan = trace[0]; + expect(rootSpan.traceId).toBe(traceId); + expect(rootSpan.name).toBe('Request'); + expect(rootSpan.localEndpoint.serviceName).toBe('traced-fetch'); + + // First child span + const firstChildSpan = trace[1]; + expect(firstChildSpan.traceId).toBe(traceId); + expect(firstChildSpan.parentId).toBe(rootSpan.id); + expect(firstChildSpan.name).toBe(SPAN_NAME.FETCH); + expect(firstChildSpan.duration).not.toBe(0); + + await worker.stop(); + }); + + test.todo('Can pass context in service binding'); + }); }); From 5c17cc95b62f6bba1a805c95dd6222324a43240e Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 21:15:38 +0000 Subject: [PATCH 11/12] Update service binding example --- examples/service-binding/index.ts | 6 +++++- src/trace.ts | 11 ++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/examples/service-binding/index.ts b/examples/service-binding/index.ts index 86b5d9e..968004d 100644 --- a/examples/service-binding/index.ts +++ b/examples/service-binding/index.ts @@ -26,7 +26,11 @@ export default { const serviceBindingSpan = span.startSpan(SPAN_NAME.SERVICE_FETCH, { attributes: { service: 'basic' } }); const res = await env.SERVICE.fetch('https://service/test', { - headers: { 'x-trace-id': `${serviceBindingSpan.getContext().traceId}:${serviceBindingSpan.getContext().spanId}` }, + cf: { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + spanContext: serviceBindingSpan.getContext(), + }, }); serviceBindingSpan.end(); diff --git a/src/trace.ts b/src/trace.ts index b2f2ed4..2d97495 100644 --- a/src/trace.ts +++ b/src/trace.ts @@ -9,21 +9,14 @@ export function createTrace( tracerOptions: TracerOptions, spanOptions?: SpanCreationOptions, ): Trace { - // This is ugly - // TODO: Fix this - https://www.w3.org/TR/trace-context/#traceparent-header - // https://zipkin.io/pages/architecture.html - https://github.com/openzipkin/b3-propagation#overall-process // This parent context will allow properly tracing across services (and other Workers) let parentContext: SpanContext | undefined; + // Allow passing SpanContext through the `cf` object for service bindings if ((req.cf as CfWithTrace)?.traceContext) { parentContext = (req.cf as CfWithTrace)?.traceContext; } - if (req.headers.get('x-trace-id')) { - const ids = req.headers.get('x-trace-id')?.split(':', 2); - if (ids?.length === 2) { - parentContext = { traceId: ids[0], spanId: ids[1] }; - } - } + // Read context from the spec-compliant ways const exporter = tracerOptions.collector.exporter ?? new OtlpExporter(); const context = exporter.readContextHeaders(req.headers); if (context !== null) { From 2cd26c1b244099b2c4031e4f06a12baeaba65c4a Mon Sep 17 00:00:00 2001 From: Daniel Walsh Date: Sun, 29 Jan 2023 23:49:17 +0000 Subject: [PATCH 12/12] Cleanup code a little --- src/tracing.ts | 4 +++- src/types.ts | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tracing.ts b/src/tracing.ts index 524c9dd..12f7854 100644 --- a/src/tracing.ts +++ b/src/tracing.ts @@ -5,6 +5,7 @@ import { traceFn } from './trace'; import { SpanBuilder } from './builder'; import type { Attributes, + globalThis, SpanContext, SpanCreationOptions, SpanData, @@ -190,8 +191,9 @@ export class Trace extends Span { } headers.append('content-type', 'application/json'); + // Tests // TODO: Properly pass trace context down and update the tests - if (!headers.has('x-trace-id')) { + if ((globalThis as globalThis).MINIFLARE && !headers.has('x-trace-id')) { headers.append('x-trace-id', this.getTraceId()); } diff --git a/src/types.ts b/src/types.ts index 2232bbb..cd11b29 100644 --- a/src/types.ts +++ b/src/types.ts @@ -144,3 +144,7 @@ export type CfWithTrace = IncomingRequestCfProperties & { } export type TracedFn = (span: Span) => T; + +export interface globalThis { + MINIFLARE?: boolean; +}