@toa.io/extensions.exposition 1.0.0-alpha.245 → 1.0.0-alpha.246
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/components/identity.passkeys/operations/tsconfig.tsbuildinfo +1 -1
- package/documentation/tracing.md +70 -0
- package/features/steps/Gateway.ts +1 -4
- package/features/steps/Parameters.ts +9 -3
- package/features/steps/components/audit/manifest.toa.yaml +13 -0
- package/features/steps/components/audit/operations/record.js +9 -0
- package/features/steps/components/notify/manifest.toa.yaml +13 -0
- package/features/steps/components/notify/operations/send.js +9 -0
- package/features/steps/components/orders/manifest.toa.yaml +15 -0
- package/features/steps/components/orders/operations/create.js +9 -0
- package/features/steps/components/pricing/manifest.toa.yaml +7 -0
- package/features/steps/components/pricing/operations/quote.js +7 -0
- package/features/timing.feature +2 -22
- package/features/tracing.feature +123 -0
- package/package.json +6 -6
- package/readme.md +7 -1
- package/schemas/annotation.cos.yaml +0 -1
- package/source/Annotation.ts +0 -1
- package/source/Directive.ts +22 -4
- package/source/Factory.ts +8 -4
- package/source/HTTP/Context.ts +1 -2
- package/source/HTTP/Server.ts +66 -13
- package/source/HTTP/Timing.ts +0 -11
- package/source/HTTP/messages.test.ts +1 -1
- package/source/RTD/Directives.ts +3 -0
- package/source/deployment.ts +2 -5
- package/transpiled/Annotation.d.ts +0 -1
- package/transpiled/Directive.js +16 -4
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Factory.js +4 -1
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/HTTP/Context.d.ts +0 -1
- package/transpiled/HTTP/Context.js +1 -1
- package/transpiled/HTTP/Context.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +1 -1
- package/transpiled/HTTP/Server.js +49 -9
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/Timing.d.ts +0 -2
- package/transpiled/HTTP/Timing.js +0 -8
- package/transpiled/HTTP/Timing.js.map +1 -1
- package/transpiled/RTD/Directives.d.ts +2 -0
- package/transpiled/deployment.js +1 -3
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Tracing
|
|
2
|
+
|
|
3
|
+
Each incoming request is processed within a [trace](../../telemetry/readme.md#tracing) —
|
|
4
|
+
a server span is created, and its trace context is propagated to component invocations and
|
|
5
|
+
emitted events, so all log entries and spans across the application caused by the request
|
|
6
|
+
share the same `trace_id`.
|
|
7
|
+
|
|
8
|
+
## The `ray` response header
|
|
9
|
+
|
|
10
|
+
Each response contains a `ray` header with the trace ID of the request.
|
|
11
|
+
It can be used to find related log entries, or be attached to a support ticket.
|
|
12
|
+
|
|
13
|
+
Log entries are stamped with the trace ID regardless of the sampling decision,
|
|
14
|
+
while the trace itself is only recorded if the trace is sampled (see [Sampling](#sampling)).
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
HTTP/1.1 201 Created
|
|
18
|
+
ray: 0af7651916cd43dd8448eb211c80319c
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Continuing a trace
|
|
22
|
+
|
|
23
|
+
By default, the trace starts at the gateway. If the request carries a trace context in one of the
|
|
24
|
+
following headers, the trace is continued, that is, the incoming trace ID is used.
|
|
25
|
+
|
|
26
|
+
### `traceparent`
|
|
27
|
+
|
|
28
|
+
The [W3C Trace Context](https://www.w3.org/TR/trace-context/#traceparent-header) header, sent by
|
|
29
|
+
clients instrumented with OpenTelemetry-compatible tooling, or by upstream proxies.
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
In addition to the trace ID, it carries the ID of the client span, which becomes the *parent* of
|
|
36
|
+
the gateway's server span, linking client-side and server-side spans into a single trace tree.
|
|
37
|
+
|
|
38
|
+
### `ray`
|
|
39
|
+
|
|
40
|
+
A bare trace ID (32 lowercase hex digits), for clients without tracing instrumentation willing to
|
|
41
|
+
correlate their requests with server-side traces.
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
ray: 4bf92f3577b34da6a3ce929d0e0e4736
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Unlike `traceparent`, it carries no parent span, so the gateway's server span becomes the root of
|
|
48
|
+
the trace.
|
|
49
|
+
|
|
50
|
+
If both headers are present, `traceparent` takes precedence as it carries more information.
|
|
51
|
+
Headers with invalid values are ignored, and a new trace is started.
|
|
52
|
+
|
|
53
|
+
## Sampling
|
|
54
|
+
|
|
55
|
+
The trace *context* (trace ID) is always created and propagated, so the `ray` header and
|
|
56
|
+
`trace_id` in log entries are always present. The sampling decision only determines whether
|
|
57
|
+
the *spans* of the trace are recorded.
|
|
58
|
+
|
|
59
|
+
The decision is made once, by the process that starts the trace, and is propagated along with
|
|
60
|
+
the trace context (the flags byte of `traceparent`), so a trace is either recorded as a whole
|
|
61
|
+
or not at all. Sampling is configured with the
|
|
62
|
+
[`telemetry.traces` annotation](../../telemetry/readme.md#sampling).
|
|
63
|
+
|
|
64
|
+
Sending a trace context does not bypass sampling: an incoming `ray` header adopts the trace ID,
|
|
65
|
+
while the recording decision is still made by the gateway. The `sampled` flag of an incoming
|
|
66
|
+
`traceparent` is respected, as the decision belongs to the trace root.
|
|
67
|
+
|
|
68
|
+
## See also
|
|
69
|
+
|
|
70
|
+
- [Telemetry extension](../../telemetry/readme.md) — spans, structured logs, `context.span`
|
|
@@ -24,15 +24,12 @@ export class Gateway {
|
|
|
24
24
|
process.env.TOA_EXPOSITION = encode(tree)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const { debug,
|
|
27
|
+
const { debug, authorities } = annotation
|
|
28
28
|
const properties = Object.assign({}, DEFAULT_PROPERTIES)
|
|
29
29
|
|
|
30
30
|
if (debug !== undefined)
|
|
31
31
|
properties.debug = debug
|
|
32
32
|
|
|
33
|
-
if (trace !== undefined)
|
|
34
|
-
properties.trace = trace
|
|
35
|
-
|
|
36
33
|
if (authorities !== undefined)
|
|
37
34
|
properties.authorities = authorities
|
|
38
35
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
import * as dotenv from 'dotenv'
|
|
3
3
|
import { setDefaultTimeout } from '@cucumber/cucumber'
|
|
4
|
-
import { console } from 'openspan'
|
|
5
4
|
import { encode } from '@toa.io/generic'
|
|
6
5
|
|
|
7
6
|
dotenv.config({ path: join(__dirname, '.env') })
|
|
@@ -16,10 +15,17 @@ export class Parameters {
|
|
|
16
15
|
|
|
17
16
|
setDefaultTimeout(60 * 1000)
|
|
18
17
|
|
|
19
|
-
console.configure({ format: 'terminal' })
|
|
20
|
-
|
|
21
18
|
process.env.TOA_DEV = '1'
|
|
22
19
|
|
|
20
|
+
// export traces to the local Tempo (`docker compose up tempo grafana`),
|
|
21
|
+
// unavailability of the endpoint is harmless
|
|
22
|
+
process.env.TOA_TELEMETRY_TRACES ??= encode({
|
|
23
|
+
exporters: {
|
|
24
|
+
console: null,
|
|
25
|
+
otlp: { endpoint: 'http://localhost:4318' }
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
23
29
|
process.env.TOA_STORAGES = encode({
|
|
24
30
|
octets: {
|
|
25
31
|
provider: 'tmp',
|
package/features/timing.feature
CHANGED
|
@@ -8,26 +8,7 @@ Feature: Server timing
|
|
|
8
8
|
POST: create
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
Scenario: Server timing is
|
|
12
|
-
When the following request is received:
|
|
13
|
-
"""
|
|
14
|
-
POST /pots/ HTTP/1.1
|
|
15
|
-
host: nex.toa.io
|
|
16
|
-
content-type: application/yaml
|
|
17
|
-
|
|
18
|
-
title: Hello
|
|
19
|
-
volume: 1.5
|
|
20
|
-
"""
|
|
21
|
-
Then the reply does not contain:
|
|
22
|
-
"""
|
|
23
|
-
server-timing:
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
Scenario: Server timing is sent when `trace` is enabled
|
|
27
|
-
Given the annotation:
|
|
28
|
-
"""
|
|
29
|
-
trace: true
|
|
30
|
-
"""
|
|
11
|
+
Scenario: Server timing is sent
|
|
31
12
|
When the following request is received:
|
|
32
13
|
"""
|
|
33
14
|
POST /pots/ HTTP/1.1
|
|
@@ -47,13 +28,12 @@ Feature: Server timing
|
|
|
47
28
|
Scenario: Octets timing
|
|
48
29
|
Given the annotation:
|
|
49
30
|
"""yaml
|
|
50
|
-
trace: true
|
|
51
31
|
/:
|
|
52
32
|
io:output: true
|
|
53
33
|
auth:anonymous: true
|
|
54
34
|
octets:context: octets
|
|
55
35
|
POST:
|
|
56
|
-
octets:
|
|
36
|
+
octets:put: ~
|
|
57
37
|
"""
|
|
58
38
|
When the stream of `lenna.png` is received with the following headers:
|
|
59
39
|
"""
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Feature: Distributed tracing
|
|
2
|
+
|
|
3
|
+
Background:
|
|
4
|
+
Given the `pots` is running with the following manifest:
|
|
5
|
+
"""yaml
|
|
6
|
+
exposition:
|
|
7
|
+
/:
|
|
8
|
+
POST: create
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
Scenario: Response carries the `ray` header
|
|
12
|
+
When the following request is received:
|
|
13
|
+
"""
|
|
14
|
+
POST /pots/ HTTP/1.1
|
|
15
|
+
host: nex.toa.io
|
|
16
|
+
content-type: application/yaml
|
|
17
|
+
|
|
18
|
+
title: Hello
|
|
19
|
+
volume: 1.5
|
|
20
|
+
"""
|
|
21
|
+
Then the following reply is sent:
|
|
22
|
+
"""
|
|
23
|
+
201 Created
|
|
24
|
+
ray:
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
Scenario: Trace is continued from the `traceparent` request header
|
|
28
|
+
When the following request is received:
|
|
29
|
+
"""
|
|
30
|
+
POST /pots/ HTTP/1.1
|
|
31
|
+
host: nex.toa.io
|
|
32
|
+
content-type: application/yaml
|
|
33
|
+
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
|
|
34
|
+
|
|
35
|
+
title: Hello
|
|
36
|
+
volume: 1.5
|
|
37
|
+
"""
|
|
38
|
+
Then the following reply is sent:
|
|
39
|
+
"""
|
|
40
|
+
201 Created
|
|
41
|
+
ray: 0af7651916cd43dd8448eb211c80319c
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
Scenario: Trace is continued from the `ray` request header
|
|
45
|
+
When the following request is received:
|
|
46
|
+
"""
|
|
47
|
+
POST /pots/ HTTP/1.1
|
|
48
|
+
host: nex.toa.io
|
|
49
|
+
content-type: application/yaml
|
|
50
|
+
ray: 4bf92f3577b34da6a3ce929d0e0e4736
|
|
51
|
+
|
|
52
|
+
title: Hello
|
|
53
|
+
volume: 1.5
|
|
54
|
+
"""
|
|
55
|
+
Then the following reply is sent:
|
|
56
|
+
"""
|
|
57
|
+
201 Created
|
|
58
|
+
ray: 4bf92f3577b34da6a3ce929d0e0e4736
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
Scenario: Trace spans remote calls, storage and events
|
|
62
|
+
Given the `identity.basic` database is empty
|
|
63
|
+
And the `pricing` is running
|
|
64
|
+
And the `orders` is running with the following manifest:
|
|
65
|
+
"""yaml
|
|
66
|
+
exposition:
|
|
67
|
+
/:id:
|
|
68
|
+
auth:id: id
|
|
69
|
+
POST: create
|
|
70
|
+
"""
|
|
71
|
+
And the `audit` is running
|
|
72
|
+
And the `notify` is running
|
|
73
|
+
When the following request is received:
|
|
74
|
+
"""
|
|
75
|
+
POST /identity/ HTTP/1.1
|
|
76
|
+
host: nex.toa.io
|
|
77
|
+
authorization: Basic dXNlcjpwYXNzMTIzNA==
|
|
78
|
+
accept: application/yaml
|
|
79
|
+
"""
|
|
80
|
+
Then the following reply is sent:
|
|
81
|
+
"""
|
|
82
|
+
201 Created
|
|
83
|
+
authorization: Token ${{ token }}
|
|
84
|
+
|
|
85
|
+
id: ${{ id }}
|
|
86
|
+
roles: []
|
|
87
|
+
"""
|
|
88
|
+
When the following request is received:
|
|
89
|
+
"""
|
|
90
|
+
POST /orders/${{ id }}/ HTTP/1.1
|
|
91
|
+
host: nex.toa.io
|
|
92
|
+
authorization: Token ${{ token }}
|
|
93
|
+
content-type: application/yaml
|
|
94
|
+
|
|
95
|
+
title: Kettle
|
|
96
|
+
volume: 2
|
|
97
|
+
"""
|
|
98
|
+
Then the following reply is sent:
|
|
99
|
+
"""
|
|
100
|
+
201 Created
|
|
101
|
+
ray:
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
Scenario: Invalid `traceparent` starts a new trace
|
|
105
|
+
When the following request is received:
|
|
106
|
+
"""
|
|
107
|
+
POST /pots/ HTTP/1.1
|
|
108
|
+
host: nex.toa.io
|
|
109
|
+
content-type: application/yaml
|
|
110
|
+
traceparent: not-a-valid-traceparent
|
|
111
|
+
|
|
112
|
+
title: Hello
|
|
113
|
+
volume: 1.5
|
|
114
|
+
"""
|
|
115
|
+
Then the following reply is sent:
|
|
116
|
+
"""
|
|
117
|
+
201 Created
|
|
118
|
+
ray:
|
|
119
|
+
"""
|
|
120
|
+
And the reply does not contain:
|
|
121
|
+
"""
|
|
122
|
+
ray: 0af7651916cd43dd8448eb211c80319c
|
|
123
|
+
"""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.exposition",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.246",
|
|
4
4
|
"description": "Toa Exposition",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -19,20 +19,20 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@aws-sdk/protocol-http": "3.370.0",
|
|
21
21
|
"@simplewebauthn/server": "13.1.1",
|
|
22
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
22
|
+
"@toa.io/core": "1.0.0-alpha.246",
|
|
23
23
|
"@toa.io/generic": "1.0.0-alpha.225",
|
|
24
|
-
"@toa.io/schemas": "1.0.0-alpha.
|
|
24
|
+
"@toa.io/schemas": "1.0.0-alpha.246",
|
|
25
25
|
"bcryptjs": "2.4.3",
|
|
26
26
|
"content-type": "1.0.5",
|
|
27
27
|
"error-value": "0.4.2",
|
|
28
28
|
"jose": "5.10.0",
|
|
29
|
-
"js-yaml": "4.3.
|
|
29
|
+
"js-yaml": "4.3.1",
|
|
30
30
|
"lru-cache": "11.2.7",
|
|
31
31
|
"matchacho": "0.3.5",
|
|
32
32
|
"minimatch": "10.2.4",
|
|
33
33
|
"msgpackr": "1.11.9",
|
|
34
34
|
"negotiator": "1.0.0",
|
|
35
|
-
"openspan": "1.0.0-alpha.
|
|
35
|
+
"openspan": "1.0.0-alpha.246",
|
|
36
36
|
"paseto": "3.1.4"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
},
|
|
65
65
|
"testEnvironment": "node"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "d6ee2a7246c64a44c50c28fadcfd1e27aaf137cb"
|
|
68
68
|
}
|
package/readme.md
CHANGED
|
@@ -136,7 +136,13 @@ exposition:
|
|
|
136
136
|
| `class` | Ingress class. |
|
|
137
137
|
| `annotations` | Ingress annotations. |
|
|
138
138
|
| `debug` | Output server errors. Default `false`. |
|
|
139
|
-
|
|
139
|
+
|
|
140
|
+
### Observability
|
|
141
|
+
|
|
142
|
+
Each response contains a `ray` header with the trace ID of the request, and
|
|
143
|
+
[server timing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing) headers.
|
|
144
|
+
|
|
145
|
+
Incoming trace context is continued, see [Tracing](documentation/tracing.md).
|
|
140
146
|
|
|
141
147
|
### Context resources
|
|
142
148
|
|
package/source/Annotation.ts
CHANGED
package/source/Directive.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { console, type SpanOptions } from 'openspan'
|
|
1
2
|
import type { Context, OutgoingMessage } from './HTTP'
|
|
2
3
|
import type { Remotes } from './Remotes'
|
|
3
4
|
import type { Output } from './io'
|
|
@@ -17,7 +18,8 @@ export class Directives implements RTD.Directives {
|
|
|
17
18
|
if (set.family.preflight === undefined)
|
|
18
19
|
continue
|
|
19
20
|
|
|
20
|
-
const out = await
|
|
21
|
+
const out = await console.span(options(set, 'preflight'),
|
|
22
|
+
async () => await set.family.preflight!(set.directives, context, parameters))
|
|
21
23
|
|
|
22
24
|
if (out === null)
|
|
23
25
|
continue
|
|
@@ -34,7 +36,8 @@ export class Directives implements RTD.Directives {
|
|
|
34
36
|
public async settle (context: Context, response: OutgoingMessage): Promise<void> {
|
|
35
37
|
for (const set of this.sets)
|
|
36
38
|
if (set.family.settle !== undefined)
|
|
37
|
-
await
|
|
39
|
+
await console.span(options(set, 'settle'),
|
|
40
|
+
async () => await set.family.settle!(set.directives, context, response))
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
public dispose (): void {
|
|
@@ -67,6 +70,8 @@ export class DirectivesFactory implements RTD.DirectiveFactory {
|
|
|
67
70
|
declarations.sort((a, b) =>
|
|
68
71
|
(mandatory.has(b.family) ? 1 : 0) - (mandatory.has(a.family) ? 1 : 0))
|
|
69
72
|
|
|
73
|
+
const names: Record<string, string[]> = {}
|
|
74
|
+
|
|
70
75
|
for (const declaration of declarations) {
|
|
71
76
|
const family = this.families[declaration.family]
|
|
72
77
|
|
|
@@ -77,6 +82,8 @@ export class DirectivesFactory implements RTD.DirectiveFactory {
|
|
|
77
82
|
|
|
78
83
|
groups[family.name] ??= []
|
|
79
84
|
groups[family.name].push(directive)
|
|
85
|
+
names[family.name] ??= []
|
|
86
|
+
names[family.name].push(`${declaration.family}:${declaration.name}`)
|
|
80
87
|
mandatory.delete(family.name)
|
|
81
88
|
}
|
|
82
89
|
|
|
@@ -85,13 +92,15 @@ export class DirectivesFactory implements RTD.DirectiveFactory {
|
|
|
85
92
|
for (const family of mandatory)
|
|
86
93
|
sets.push({
|
|
87
94
|
family: this.families[family],
|
|
88
|
-
directives: []
|
|
95
|
+
directives: [],
|
|
96
|
+
names: []
|
|
89
97
|
})
|
|
90
98
|
|
|
91
99
|
for (const [family, directives] of Object.entries(groups))
|
|
92
100
|
sets.push({
|
|
93
101
|
family: this.families[family],
|
|
94
|
-
directives
|
|
102
|
+
directives,
|
|
103
|
+
names: names[family]
|
|
95
104
|
})
|
|
96
105
|
|
|
97
106
|
const directives = new Directives(sets)
|
|
@@ -107,6 +116,15 @@ export class DirectivesFactory implements RTD.DirectiveFactory {
|
|
|
107
116
|
}
|
|
108
117
|
}
|
|
109
118
|
|
|
119
|
+
function options (set: RTD.DirectiveSet, stage: 'preflight' | 'settle'): SpanOptions {
|
|
120
|
+
const options: SpanOptions = { name: `${set.family.name} ${stage}` }
|
|
121
|
+
|
|
122
|
+
if (set.names !== undefined && set.names.length > 0)
|
|
123
|
+
options.attributes = { directives: Array.from(new Set(set.names)).join(' ') }
|
|
124
|
+
|
|
125
|
+
return options
|
|
126
|
+
}
|
|
127
|
+
|
|
110
128
|
export const shortcuts: RTD.syntax.Shortcuts = new Map([
|
|
111
129
|
['anonymous', 'auth:anonymous'],
|
|
112
130
|
['anyone', 'auth:anyone'],
|
package/source/Factory.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert'
|
|
2
2
|
import { createHash } from 'node:crypto'
|
|
3
|
-
import { console } from 'openspan'
|
|
3
|
+
import { console, traces, type LevelName, type TracesOptions } from 'openspan'
|
|
4
4
|
import { decode } from '@toa.io/generic'
|
|
5
5
|
import { Tenant } from './Tenant'
|
|
6
6
|
import { Gateway } from './Gateway'
|
|
@@ -17,7 +17,6 @@ import type { Branch } from './Branch'
|
|
|
17
17
|
import type { syntax } from './RTD'
|
|
18
18
|
import type { Broadcast } from './Gateway'
|
|
19
19
|
import type { Connector, Locator, extensions } from '@toa.io/core'
|
|
20
|
-
import type { Channel } from 'openspan'
|
|
21
20
|
|
|
22
21
|
export class Factory implements extensions.Factory {
|
|
23
22
|
private readonly boot: Bootloader
|
|
@@ -72,13 +71,18 @@ export class Factory implements extensions.Factory {
|
|
|
72
71
|
|
|
73
72
|
const CHANNEL = 'exposition'
|
|
74
73
|
const LOGS_PREFIX = 'TOA_TELEMETRY_LOGS'
|
|
74
|
+
const TRACES_ENV = 'TOA_TELEMETRY_TRACES'
|
|
75
75
|
|
|
76
76
|
function configureLogs (): void {
|
|
77
77
|
const globEnv = process.env[LOGS_PREFIX]
|
|
78
|
-
const level:
|
|
79
|
-
const options = globEnv === undefined ? { level } : decode<{ level?:
|
|
78
|
+
const level: LevelName = process.env.TOA_DEV === '1' ? 'trace' : 'info'
|
|
79
|
+
const options = globEnv === undefined ? { level } : decode<{ level?: LevelName }>(globEnv)
|
|
80
80
|
|
|
81
81
|
console.configure({ level: options.level ?? level })
|
|
82
|
+
|
|
83
|
+
const tracesEnv = process.env[TRACES_ENV]
|
|
84
|
+
|
|
85
|
+
traces(tracesEnv === undefined ? {} : decode<TracesOptions>(tracesEnv))
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
package/source/HTTP/Context.ts
CHANGED
|
@@ -31,7 +31,7 @@ export class Context {
|
|
|
31
31
|
|
|
32
32
|
this.id = crypto.randomUUID()
|
|
33
33
|
this.url = new URL(request.url, `https://${request.headers.host}`)
|
|
34
|
-
this.timing = new Timing(
|
|
34
|
+
this.timing = new Timing()
|
|
35
35
|
this.debug = properties.debug
|
|
36
36
|
this.log(request)
|
|
37
37
|
|
|
@@ -95,7 +95,6 @@ interface Pipelines {
|
|
|
95
95
|
|
|
96
96
|
interface Properties {
|
|
97
97
|
debug: boolean
|
|
98
|
-
trace: boolean
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
const SUBTYPE = /^(?<type>\w{1,32})\/(vnd\.toa\.(?<subtype>\S{1,32})\+)(?<suffix>\S{1,32})$/
|