autotel-edge 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +333 -0
- package/dist/chunk-F32WSLNX.js +309 -0
- package/dist/chunk-F32WSLNX.js.map +1 -0
- package/dist/events.d.ts +86 -0
- package/dist/events.js +157 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +326 -0
- package/dist/index.js +921 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +89 -0
- package/dist/logger.js +81 -0
- package/dist/logger.js.map +1 -0
- package/dist/sampling.d.ts +166 -0
- package/dist/sampling.js +108 -0
- package/dist/sampling.js.map +1 -0
- package/dist/testing.d.ts +2 -0
- package/dist/testing.js +3 -0
- package/dist/testing.js.map +1 -0
- package/dist/types-Dj85cPUj.d.ts +182 -0
- package/package.json +88 -0
- package/src/api/logger.test.ts +367 -0
- package/src/api/logger.ts +197 -0
- package/src/compose.ts +243 -0
- package/src/core/buffer.ts +16 -0
- package/src/core/config.test.ts +388 -0
- package/src/core/config.ts +167 -0
- package/src/core/context.ts +224 -0
- package/src/core/exporter.ts +99 -0
- package/src/core/provider.ts +45 -0
- package/src/core/span.ts +222 -0
- package/src/core/spanprocessor.test.ts +521 -0
- package/src/core/spanprocessor.ts +232 -0
- package/src/core/trace-context.ts +66 -0
- package/src/core/tracer.test.ts +123 -0
- package/src/core/tracer.ts +216 -0
- package/src/events/index.test.ts +242 -0
- package/src/events/index.ts +338 -0
- package/src/events.ts +6 -0
- package/src/functional.test.ts +702 -0
- package/src/functional.ts +846 -0
- package/src/index.ts +81 -0
- package/src/logger.ts +13 -0
- package/src/sampling/index.test.ts +297 -0
- package/src/sampling/index.ts +276 -0
- package/src/sampling.ts +6 -0
- package/src/testing/index.ts +9 -0
- package/src/testing.ts +6 -0
- package/src/types.ts +267 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { Span, SpanContext, SpanKind, Attributes, SpanStatus, HrTime, Link, TimeInput, AttributeValue, Exception, Tracer, SpanOptions as SpanOptions$1, Context, ContextManager, SpanStatusCode } from '@opentelemetry/api';
|
|
2
|
+
export { Context, Span, SpanContext, Tracer, context, propagation } from '@opentelemetry/api';
|
|
3
|
+
import { InstrumentationScope, ExportResult } from '@opentelemetry/core';
|
|
4
|
+
import { Resource } from '@opentelemetry/resources';
|
|
5
|
+
import { ReadableSpan, TimedEvent, SpanProcessor, SpanExporter, TracerConfig, Sampler } from '@opentelemetry/sdk-trace-base';
|
|
6
|
+
export { ReadableSpan } from '@opentelemetry/sdk-trace-base';
|
|
7
|
+
import { OTLPExporterError } from '@opentelemetry/otlp-exporter-base';
|
|
8
|
+
import { f as OTLPExporterConfig, g as EdgeConfig, R as ResolvedEdgeConfig, C as ConfigurationOption, h as Trigger } from './types-Dj85cPUj.js';
|
|
9
|
+
export { n as EdgeSubscriber, i as ExporterConfig, H as HandlerInstrumentation, m as InitialSpanInfo, I as InstrumentationOptions, L as LocalTrace, P as PostProcessorFn, k as ResolveConfigFn, j as SamplingConfig, S as ServiceConfig, T as TailSampleFn, l as TraceFlushableSpanProcessor } from './types-Dj85cPUj.js';
|
|
10
|
+
export { Buffer } from 'node:buffer';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Lightweight Span implementation for edge environments
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
type OnSpanEnd = (span: Span) => void;
|
|
17
|
+
interface SpanInit {
|
|
18
|
+
attributes: unknown;
|
|
19
|
+
name: string;
|
|
20
|
+
onEnd: OnSpanEnd;
|
|
21
|
+
resource: Resource;
|
|
22
|
+
spanContext: SpanContext;
|
|
23
|
+
parentSpanContext?: SpanContext;
|
|
24
|
+
links?: Link[];
|
|
25
|
+
parentSpanId?: string;
|
|
26
|
+
spanKind?: SpanKind;
|
|
27
|
+
startTime?: TimeInput;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Lightweight Span implementation for edge runtimes
|
|
31
|
+
*/
|
|
32
|
+
declare class SpanImpl implements Span, ReadableSpan {
|
|
33
|
+
name: string;
|
|
34
|
+
private readonly _spanContext;
|
|
35
|
+
private readonly onEnd;
|
|
36
|
+
readonly parentSpanId?: string;
|
|
37
|
+
readonly parentSpanContext?: SpanContext | undefined;
|
|
38
|
+
readonly kind: SpanKind;
|
|
39
|
+
readonly attributes: Attributes;
|
|
40
|
+
status: SpanStatus;
|
|
41
|
+
endTime: HrTime;
|
|
42
|
+
private _duration;
|
|
43
|
+
readonly startTime: HrTime;
|
|
44
|
+
readonly events: TimedEvent[];
|
|
45
|
+
readonly links: Link[];
|
|
46
|
+
readonly resource: Resource;
|
|
47
|
+
instrumentationScope: InstrumentationScope;
|
|
48
|
+
private _ended;
|
|
49
|
+
private _droppedAttributesCount;
|
|
50
|
+
private _droppedEventsCount;
|
|
51
|
+
private _droppedLinksCount;
|
|
52
|
+
constructor(init: SpanInit);
|
|
53
|
+
addLink(link: Link): this;
|
|
54
|
+
addLinks(links: Link[]): this;
|
|
55
|
+
spanContext(): SpanContext;
|
|
56
|
+
setAttribute(key: string, value?: AttributeValue): this;
|
|
57
|
+
setAttributes(attributes: Attributes): this;
|
|
58
|
+
addEvent(name: string, attributesOrStartTime?: Attributes | TimeInput, startTime?: TimeInput): this;
|
|
59
|
+
setStatus(status: SpanStatus): this;
|
|
60
|
+
updateName(name: string): this;
|
|
61
|
+
end(endTime?: TimeInput): void;
|
|
62
|
+
isRecording(): boolean;
|
|
63
|
+
recordException(exception: Exception, time?: TimeInput): void;
|
|
64
|
+
get duration(): HrTime;
|
|
65
|
+
get ended(): boolean;
|
|
66
|
+
get droppedAttributesCount(): number;
|
|
67
|
+
get droppedEventsCount(): number;
|
|
68
|
+
get droppedLinksCount(): number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Lightweight WorkerTracer for edge environments
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* WorkerTracer - Lightweight tracer for edge environments
|
|
77
|
+
*/
|
|
78
|
+
declare class WorkerTracer implements Tracer {
|
|
79
|
+
private readonly spanProcessors;
|
|
80
|
+
private readonly resource;
|
|
81
|
+
private headSampler;
|
|
82
|
+
constructor(spanProcessors: SpanProcessor[], resource: Resource);
|
|
83
|
+
/**
|
|
84
|
+
* Set the head sampler (called from config)
|
|
85
|
+
*/
|
|
86
|
+
setHeadSampler(sampler: any): void;
|
|
87
|
+
/**
|
|
88
|
+
* Force flush spans for a specific trace
|
|
89
|
+
*/
|
|
90
|
+
forceFlush(traceId?: string): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Add extra resource attributes
|
|
93
|
+
*/
|
|
94
|
+
addToResource(extra: Resource): void;
|
|
95
|
+
/**
|
|
96
|
+
* Start a new span
|
|
97
|
+
*/
|
|
98
|
+
startSpan(name: string, options?: SpanOptions$1, context?: Context): Span;
|
|
99
|
+
/**
|
|
100
|
+
* Start an active span (with automatic context management)
|
|
101
|
+
*/
|
|
102
|
+
startActiveSpan<F extends (span: Span) => ReturnType<F>>(name: string, fn: F): ReturnType<F>;
|
|
103
|
+
startActiveSpan<F extends (span: Span) => ReturnType<F>>(name: string, options: SpanOptions$1, fn: F): ReturnType<F>;
|
|
104
|
+
startActiveSpan<F extends (span: Span) => ReturnType<F>>(name: string, options: SpanOptions$1, context: Context, fn: F): ReturnType<F>;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Set attributes for the next span created
|
|
108
|
+
*/
|
|
109
|
+
declare function withNextSpan(attrs: Attributes): void;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Lightweight OTLP exporter for edge environments
|
|
113
|
+
* Ported and adapted from @microlabs/
|
|
114
|
+
*
|
|
115
|
+
* This exporter is much smaller than the standard @opentelemetry/exporter-trace-otlp-http
|
|
116
|
+
* because it uses fetch() directly instead of Node.js http/https modules.
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Minimal OTLP exporter using fetch()
|
|
121
|
+
*/
|
|
122
|
+
declare class OTLPExporter implements SpanExporter {
|
|
123
|
+
private headers;
|
|
124
|
+
private url;
|
|
125
|
+
constructor(config: OTLPExporterConfig);
|
|
126
|
+
export(items: any[], resultCallback: (result: ExportResult) => void): void;
|
|
127
|
+
private _export;
|
|
128
|
+
send(items: any[], onSuccess: () => void, onError: (error: OTLPExporterError) => void): void;
|
|
129
|
+
shutdown(): Promise<void>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* AsyncLocalStorage-based context manager for edge environments
|
|
134
|
+
*
|
|
135
|
+
* Copyright The OpenTelemetry Authors
|
|
136
|
+
* Licensed under the Apache License, Version 2.0
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
declare abstract class AbstractAsyncHooksContextManager implements ContextManager {
|
|
140
|
+
abstract active(): Context;
|
|
141
|
+
abstract with<A extends unknown[], F extends (...args: A) => ReturnType<F>>(context: Context, fn: F, thisArg?: ThisParameterType<F>, ...args: A): ReturnType<F>;
|
|
142
|
+
abstract enable(): this;
|
|
143
|
+
abstract disable(): this;
|
|
144
|
+
/**
|
|
145
|
+
* Binds a context to the target function or event emitter
|
|
146
|
+
*/
|
|
147
|
+
bind<T>(context: Context, target: T): T;
|
|
148
|
+
private _bindFunction;
|
|
149
|
+
/**
|
|
150
|
+
* By default, EventEmitter calls callbacks with their context, which we do
|
|
151
|
+
* not want. Instead we bind a specific context to all callbacks.
|
|
152
|
+
*/
|
|
153
|
+
private _bindEventEmitter;
|
|
154
|
+
private _patchRemoveListener;
|
|
155
|
+
private _patchRemoveAllListeners;
|
|
156
|
+
private _patchAddListener;
|
|
157
|
+
private _createPatchMap;
|
|
158
|
+
private _getPatchMap;
|
|
159
|
+
private readonly _kOtListeners;
|
|
160
|
+
private _wrapped;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* AsyncLocalStorage-based context manager for edge runtimes
|
|
164
|
+
*/
|
|
165
|
+
declare class AsyncLocalStorageContextManager extends AbstractAsyncHooksContextManager {
|
|
166
|
+
private _asyncLocalStorage;
|
|
167
|
+
constructor();
|
|
168
|
+
active(): Context;
|
|
169
|
+
with<A extends unknown[], F extends (...args: A) => ReturnType<F>>(context: Context, fn: F, thisArg?: ThisParameterType<F>, ...args: A): ReturnType<F>;
|
|
170
|
+
enable(): this;
|
|
171
|
+
disable(): this;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Tracer provider for edge environments
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* WorkerTracerProvider - Registers tracer globally
|
|
180
|
+
*/
|
|
181
|
+
declare class WorkerTracerProvider {
|
|
182
|
+
private tracer;
|
|
183
|
+
private contextManager;
|
|
184
|
+
constructor(spanProcessors: SpanProcessor[], resource: Resource);
|
|
185
|
+
/**
|
|
186
|
+
* Get the tracer instance
|
|
187
|
+
*/
|
|
188
|
+
getTracer(_name: string, _version?: string, _config?: TracerConfig): WorkerTracer;
|
|
189
|
+
/**
|
|
190
|
+
* Register this provider as the global tracer
|
|
191
|
+
*/
|
|
192
|
+
register(): void;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Configuration system for autotel-edge
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Type for config initialization function
|
|
201
|
+
*/
|
|
202
|
+
type Initialiser = (env: any, trigger: Trigger) => ResolvedEdgeConfig;
|
|
203
|
+
/**
|
|
204
|
+
* Get the currently active config from context
|
|
205
|
+
*
|
|
206
|
+
* This reads the config from the active context, ensuring each request
|
|
207
|
+
* has its own isolated config even when multiple requests are in-flight.
|
|
208
|
+
*/
|
|
209
|
+
declare function getActiveConfig(): ResolvedEdgeConfig | null;
|
|
210
|
+
/**
|
|
211
|
+
* Set the active config in context
|
|
212
|
+
*
|
|
213
|
+
* Returns a new context with the config stored. This context should be
|
|
214
|
+
* used with api_context.with() to ensure the config is isolated per-request.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const config = parseConfig({ service: { name: 'my-service' } });
|
|
219
|
+
* const context = setConfig(config);
|
|
220
|
+
*
|
|
221
|
+
* api_context.with(context, () => {
|
|
222
|
+
* // Config is available here via getActiveConfig()
|
|
223
|
+
* });
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
declare function setConfig(config: ResolvedEdgeConfig): Context;
|
|
227
|
+
/**
|
|
228
|
+
* Parse and validate configuration
|
|
229
|
+
*/
|
|
230
|
+
declare function parseConfig(config: EdgeConfig): ResolvedEdgeConfig;
|
|
231
|
+
/**
|
|
232
|
+
* Create a config initializer function
|
|
233
|
+
*/
|
|
234
|
+
declare function createInitialiser(config: ConfigurationOption): Initialiser;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Trace context types and utilities
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Base trace context containing trace identifiers
|
|
242
|
+
*/
|
|
243
|
+
interface TraceContextBase {
|
|
244
|
+
traceId: string;
|
|
245
|
+
spanId: string;
|
|
246
|
+
correlationId: string;
|
|
247
|
+
'code.function'?: string;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Span methods available on trace context
|
|
251
|
+
*/
|
|
252
|
+
interface SpanMethods {
|
|
253
|
+
setAttribute(key: string, value: string | number | boolean): void;
|
|
254
|
+
setAttributes(attrs: Record<string, string | number | boolean>): void;
|
|
255
|
+
setStatus(status: {
|
|
256
|
+
code: SpanStatusCode;
|
|
257
|
+
message?: string;
|
|
258
|
+
}): void;
|
|
259
|
+
recordException(exception: Error): void;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Complete trace context that merges base context and span methods
|
|
263
|
+
*
|
|
264
|
+
* This is the ctx parameter passed to factory functions in trace().
|
|
265
|
+
* It provides access to trace IDs and span manipulation methods.
|
|
266
|
+
*/
|
|
267
|
+
type TraceContext = TraceContextBase & SpanMethods;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Functional API for autotel-edge
|
|
271
|
+
*
|
|
272
|
+
* Provides zero-boilerplate tracing helpers that mirror the Node.js runtime
|
|
273
|
+
* implementation while staying optimized for edge environments.
|
|
274
|
+
*/
|
|
275
|
+
|
|
276
|
+
type ExtractFunctionSignature<T> = T extends (ctx: TraceContext) => infer F ? F extends (...args: infer Args) => infer Return ? (...args: Args) => Return : never : never;
|
|
277
|
+
type WrappedFunction<TArgs extends any[], TReturn> = (...args: TArgs) => TReturn | Promise<TReturn>;
|
|
278
|
+
/**
|
|
279
|
+
* trace function options
|
|
280
|
+
*/
|
|
281
|
+
interface traceOptions<TArgs extends any[] = any[], TReturn = any> {
|
|
282
|
+
name?: string;
|
|
283
|
+
serviceName?: string;
|
|
284
|
+
sampler?: Sampler;
|
|
285
|
+
attributesFromArgs?: (args: TArgs) => Record<string, unknown>;
|
|
286
|
+
attributesFromResult?: (result: TReturn) => Record<string, unknown>;
|
|
287
|
+
attributes?: Record<string, unknown>;
|
|
288
|
+
}
|
|
289
|
+
declare function trace<TReturn = any>(fn: () => TReturn): () => TReturn;
|
|
290
|
+
declare function trace<TArgs extends any[], TReturn = any>(fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
291
|
+
declare function trace<TReturn = any>(fnFactory: (ctx: TraceContext) => () => TReturn): () => TReturn;
|
|
292
|
+
declare function trace<TReturn = any>(fn: (ctx: TraceContext) => TReturn): TReturn;
|
|
293
|
+
declare function trace<TFactory extends (ctx: TraceContext) => (...args: any[]) => any>(fnFactory: TFactory): ExtractFunctionSignature<TFactory>;
|
|
294
|
+
declare function trace<TArgs extends any[], TReturn = any>(fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
295
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(name: string, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
296
|
+
declare function trace<TReturn = any>(name: string, fn: (ctx: TraceContext) => TReturn): TReturn;
|
|
297
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(name: string, fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
298
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(options: traceOptions<TArgs, TReturn>, fn: (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
299
|
+
declare function trace<TReturn = any>(options: traceOptions<[], TReturn>, fn: (ctx: TraceContext) => TReturn): TReturn;
|
|
300
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(options: traceOptions<TArgs, TReturn>, fnFactory: (ctx: TraceContext) => (...args: TArgs) => TReturn): (...args: TArgs) => TReturn;
|
|
301
|
+
declare function trace<TReturn = any>(fn: () => Promise<TReturn>): () => Promise<TReturn>;
|
|
302
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(fn: (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
|
|
303
|
+
declare function trace<TReturn = any>(fn: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
|
|
304
|
+
declare function trace<TReturn = any>(fnFactory: (ctx: TraceContext) => () => Promise<TReturn>): () => Promise<TReturn>;
|
|
305
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
|
|
306
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(name: string, fn: (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
|
|
307
|
+
declare function trace<TReturn = any>(name: string, fn: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
|
|
308
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(name: string, fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
|
|
309
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(options: traceOptions<TArgs, TReturn>, fn: (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
|
|
310
|
+
declare function trace<TReturn = any>(options: traceOptions<[], TReturn>, fn: (ctx: TraceContext) => Promise<TReturn>): Promise<TReturn>;
|
|
311
|
+
declare function trace<TArgs extends any[] = any[], TReturn = any>(options: traceOptions<TArgs, TReturn>, fnFactory: (ctx: TraceContext) => (...args: TArgs) => Promise<TReturn>): (...args: TArgs) => Promise<TReturn>;
|
|
312
|
+
declare function withTracing<TArgs extends any[] = any[], TReturn = any>(options: Omit<traceOptions<TArgs, TReturn>, 'name'>): (fnOrFactory: ((...args: TArgs) => TReturn | Promise<TReturn>) | ((ctx: TraceContext) => (...args: TArgs) => TReturn | Promise<TReturn>)) => WrappedFunction<TArgs, TReturn>;
|
|
313
|
+
interface InstrumentOptions extends traceOptions {
|
|
314
|
+
functions: Record<string, any>;
|
|
315
|
+
overrides?: Record<string, Partial<traceOptions>>;
|
|
316
|
+
skip?: (string | RegExp | ((key: string, fn: Function) => boolean))[];
|
|
317
|
+
}
|
|
318
|
+
declare function instrument<T extends Record<string, any>>(options: InstrumentOptions): T;
|
|
319
|
+
interface SpanOptions {
|
|
320
|
+
name: string;
|
|
321
|
+
attributes?: Record<string, string | number | boolean>;
|
|
322
|
+
}
|
|
323
|
+
declare function span<T = unknown>(options: SpanOptions, fn: (span: Span) => T): T;
|
|
324
|
+
declare function span<T = unknown>(options: SpanOptions, fn: (span: Span) => Promise<T>): Promise<T>;
|
|
325
|
+
|
|
326
|
+
export { AsyncLocalStorageContextManager, ConfigurationOption, EdgeConfig, type Initialiser, type InstrumentOptions, OTLPExporter, OTLPExporterConfig, ResolvedEdgeConfig, SpanImpl, type TraceContext, Trigger, WorkerTracer, WorkerTracerProvider, createInitialiser, getActiveConfig, instrument as instrumentFunctions, parseConfig, setConfig, span, trace, type traceOptions, withNextSpan, withTracing };
|