@logtape/otel 0.1.0-dev.1 → 0.2.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/README.md +29 -7
- package/esm/_dnt.shims.js +57 -0
- package/esm/deno.js +3 -2
- package/esm/mod.js +38 -10
- package/package.json +1 -1
- package/script/_dnt.shims.js +60 -0
- package/script/deno.js +3 -2
- package/script/mod.js +61 -10
- package/types/_dnt.shims.d.ts +2 -0
- package/types/_dnt.shims.d.ts.map +1 -0
- package/types/deno.d.ts +1 -0
- package/types/mod.d.ts +26 -10
- package/types/mod.d.ts.map +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
@logtape/otel: LogTape OpenTelemetry Sink
|
|
2
2
|
=========================================
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
[![JSR][JSR badge]][JSR]
|
|
5
|
+
[![npm][npm badge]][npm]
|
|
6
|
+
[![GitHub Actions][GitHub Actions badge]][GitHub Actions]
|
|
7
|
+
|
|
8
|
+
This package provides an [OpenTelemetry] sink for [LogTape]. It allows you to
|
|
5
9
|
send your LogTape logs to OpenTelemetry-compatible backends.
|
|
6
10
|
|
|
11
|
+
[JSR]: https://jsr.io/@logtape/otel
|
|
12
|
+
[JSR badge]: https://jsr.io/badges/@logtape/otel
|
|
13
|
+
[npm]: https://www.npmjs.com/package/@logtape/otel
|
|
14
|
+
[npm badge]: https://img.shields.io/npm/v/@logtape/otel?logo=npm
|
|
15
|
+
[GitHub Actions]: https://github.com/dahlia/logtape-otel/actions/workflows/main.yaml
|
|
16
|
+
[GitHub Actions badge]: https://github.com/dahlia/logtape-otel/actions/workflows/main.yaml/badge.svg
|
|
17
|
+
[OpenTelemetry]: https://opentelemetry.io/
|
|
7
18
|
[LogTape]: https://github.com/dahlia/logtape
|
|
8
19
|
|
|
9
20
|
|
|
@@ -20,9 +31,6 @@ yarn add @logtape/otel # for Yarn
|
|
|
20
31
|
bun add @logtape/otel # for Bun
|
|
21
32
|
~~~~
|
|
22
33
|
|
|
23
|
-
[JSR]: https://jsr.io/@logtape/otel
|
|
24
|
-
[npm]: https://www.npmjs.com/package/@logtape/otel
|
|
25
|
-
|
|
26
34
|
|
|
27
35
|
Usage
|
|
28
36
|
-----
|
|
@@ -102,7 +110,11 @@ await configure({
|
|
|
102
110
|
});
|
|
103
111
|
~~~~
|
|
104
112
|
|
|
113
|
+
For more information, see the documentation of the [`getOpenTelemetrySink()`]
|
|
114
|
+
function and [`OpenTelemetrySinkOptions`] type.
|
|
115
|
+
|
|
105
116
|
[`getOpenTelemetrySink()`]: https://jsr.io/@logtape/otel/doc/~/getOpenTelemetrySink
|
|
117
|
+
[`OpenTelemetrySinkOptions`]: https://jsr.io/@logtape/otel/doc/~/OpenTelemetrySinkOptions
|
|
106
118
|
[`LoggerProvider`]: https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_logs.LoggerProvider.html
|
|
107
119
|
|
|
108
120
|
|
|
@@ -139,7 +151,17 @@ needed.
|
|
|
139
151
|
Changelog
|
|
140
152
|
---------
|
|
141
153
|
|
|
142
|
-
Version 0.
|
|
143
|
-
|
|
154
|
+
### Version 0.2.0
|
|
155
|
+
|
|
156
|
+
Released on August 26, 2024.
|
|
157
|
+
|
|
158
|
+
- The `OpenTelemetrySinkOptions` type is now an interface.
|
|
159
|
+
- Added `OpenTelemetrySinkOptions.messageType` option.
|
|
160
|
+
- Added `OpenTelemetrySinkOptions.objectRenderer` option. Now non-scalar
|
|
161
|
+
values are rendered using `util.inspect()` in Node.js/Bun and
|
|
162
|
+
`Deno.inspect()` in Deno by default.
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
### Version 0.1.0
|
|
144
166
|
|
|
145
|
-
|
|
167
|
+
Released on August 24, 2024. Initial release.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const dntGlobals = {};
|
|
2
|
+
export const dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
|
|
3
|
+
function createMergeProxy(baseObj, extObj) {
|
|
4
|
+
return new Proxy(baseObj, {
|
|
5
|
+
get(_target, prop, _receiver) {
|
|
6
|
+
if (prop in extObj) {
|
|
7
|
+
return extObj[prop];
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
return baseObj[prop];
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
set(_target, prop, value) {
|
|
14
|
+
if (prop in extObj) {
|
|
15
|
+
delete extObj[prop];
|
|
16
|
+
}
|
|
17
|
+
baseObj[prop] = value;
|
|
18
|
+
return true;
|
|
19
|
+
},
|
|
20
|
+
deleteProperty(_target, prop) {
|
|
21
|
+
let success = false;
|
|
22
|
+
if (prop in extObj) {
|
|
23
|
+
delete extObj[prop];
|
|
24
|
+
success = true;
|
|
25
|
+
}
|
|
26
|
+
if (prop in baseObj) {
|
|
27
|
+
delete baseObj[prop];
|
|
28
|
+
success = true;
|
|
29
|
+
}
|
|
30
|
+
return success;
|
|
31
|
+
},
|
|
32
|
+
ownKeys(_target) {
|
|
33
|
+
const baseKeys = Reflect.ownKeys(baseObj);
|
|
34
|
+
const extKeys = Reflect.ownKeys(extObj);
|
|
35
|
+
const extKeysSet = new Set(extKeys);
|
|
36
|
+
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
|
|
37
|
+
},
|
|
38
|
+
defineProperty(_target, prop, desc) {
|
|
39
|
+
if (prop in extObj) {
|
|
40
|
+
delete extObj[prop];
|
|
41
|
+
}
|
|
42
|
+
Reflect.defineProperty(baseObj, prop, desc);
|
|
43
|
+
return true;
|
|
44
|
+
},
|
|
45
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
46
|
+
if (prop in extObj) {
|
|
47
|
+
return Reflect.getOwnPropertyDescriptor(extObj, prop);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
has(_target, prop) {
|
|
54
|
+
return prop in extObj || prop in baseObj;
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
package/esm/deno.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default {
|
|
2
2
|
"name": "@logtape/otel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./mod.ts"
|
|
@@ -15,7 +15,8 @@ export default {
|
|
|
15
15
|
"@opentelemetry/otlp-exporter-base": "npm:@opentelemetry/otlp-exporter-base@^0.52.1",
|
|
16
16
|
"@opentelemetry/resources": "npm:@opentelemetry/resources@^1.25.1",
|
|
17
17
|
"@opentelemetry/sdk-logs": "npm:@opentelemetry/sdk-logs@^0.52.1",
|
|
18
|
-
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.26.0"
|
|
18
|
+
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.26.0",
|
|
19
|
+
"@std/dotenv": "jsr:@std/dotenv@^0.225.1"
|
|
19
20
|
},
|
|
20
21
|
"tasks": {
|
|
21
22
|
"dnt": "deno run -A dnt.ts"
|
package/esm/mod.js
CHANGED
|
@@ -4,6 +4,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
6
|
var _DiagLoggerAdaptor_instances, _DiagLoggerAdaptor_escape;
|
|
7
|
+
import * as dntShim from "./_dnt.shims.js";
|
|
7
8
|
import { getLogger, } from "@logtape/logtape";
|
|
8
9
|
import { diag, DiagLogLevel } from "@opentelemetry/api";
|
|
9
10
|
import { SeverityNumber, } from "@opentelemetry/api-logs";
|
|
@@ -37,6 +38,7 @@ export function getOpenTelemetrySink(options = {}) {
|
|
|
37
38
|
else {
|
|
38
39
|
loggerProvider = options.loggerProvider;
|
|
39
40
|
}
|
|
41
|
+
const objectRenderer = options.objectRenderer ?? "inspect";
|
|
40
42
|
const logger = loggerProvider.getLogger(metadata.name, metadata.version);
|
|
41
43
|
const sink = (record) => {
|
|
42
44
|
const { category, level, message, timestamp, properties } = record;
|
|
@@ -45,13 +47,15 @@ export function getOpenTelemetrySink(options = {}) {
|
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
47
49
|
const severityNumber = mapLevelToSeverityNumber(level);
|
|
48
|
-
const attributes = convertToAttributes(properties);
|
|
50
|
+
const attributes = convertToAttributes(properties, objectRenderer);
|
|
49
51
|
attributes["category"] = [...category];
|
|
50
|
-
const body = convertMessageToBody(message);
|
|
52
|
+
const body = convertMessageToBody(message, objectRenderer);
|
|
51
53
|
logger.emit({
|
|
52
54
|
severityNumber,
|
|
53
55
|
severityText: level,
|
|
54
|
-
body
|
|
56
|
+
body: options.messageType === "array"
|
|
57
|
+
? body
|
|
58
|
+
: body.map((v) => v === undefined ? "undefined" : v === null ? "null" : v).join(""),
|
|
55
59
|
attributes,
|
|
56
60
|
timestamp: new Date(timestamp),
|
|
57
61
|
});
|
|
@@ -78,7 +82,7 @@ function mapLevelToSeverityNumber(level) {
|
|
|
78
82
|
return SeverityNumber.UNSPECIFIED;
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
|
-
function convertToAttributes(properties) {
|
|
85
|
+
function convertToAttributes(properties, objectRenderer) {
|
|
82
86
|
const attributes = {};
|
|
83
87
|
for (const [name, value] of Object.entries(properties)) {
|
|
84
88
|
const key = `attributes.${name}`;
|
|
@@ -90,7 +94,7 @@ function convertToAttributes(properties) {
|
|
|
90
94
|
if (v == null)
|
|
91
95
|
continue;
|
|
92
96
|
if (t != null && typeof v !== t) {
|
|
93
|
-
attributes[key] = value.map(convertToString);
|
|
97
|
+
attributes[key] = value.map((v) => convertToString(v, objectRenderer));
|
|
94
98
|
break;
|
|
95
99
|
}
|
|
96
100
|
t = typeof v;
|
|
@@ -98,7 +102,7 @@ function convertToAttributes(properties) {
|
|
|
98
102
|
attributes[key] = value;
|
|
99
103
|
}
|
|
100
104
|
else {
|
|
101
|
-
const encoded = convertToString(value);
|
|
105
|
+
const encoded = convertToString(value, objectRenderer);
|
|
102
106
|
if (encoded == null)
|
|
103
107
|
continue;
|
|
104
108
|
attributes[key] = encoded;
|
|
@@ -106,11 +110,13 @@ function convertToAttributes(properties) {
|
|
|
106
110
|
}
|
|
107
111
|
return attributes;
|
|
108
112
|
}
|
|
109
|
-
function convertToString(value) {
|
|
113
|
+
function convertToString(value, objectRenderer) {
|
|
110
114
|
if (value === null || value === undefined || typeof value === "string") {
|
|
111
115
|
return value;
|
|
112
116
|
}
|
|
113
|
-
|
|
117
|
+
if (objectRenderer === "inspect")
|
|
118
|
+
return inspect(value);
|
|
119
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
114
120
|
return value.toString();
|
|
115
121
|
}
|
|
116
122
|
else if (value instanceof Date)
|
|
@@ -118,7 +124,7 @@ function convertToString(value) {
|
|
|
118
124
|
else
|
|
119
125
|
return JSON.stringify(value);
|
|
120
126
|
}
|
|
121
|
-
function convertMessageToBody(message) {
|
|
127
|
+
function convertMessageToBody(message, objectRenderer) {
|
|
122
128
|
const body = [];
|
|
123
129
|
for (let i = 0; i < message.length; i += 2) {
|
|
124
130
|
const msg = message[i];
|
|
@@ -126,10 +132,32 @@ function convertMessageToBody(message) {
|
|
|
126
132
|
if (message.length <= i + 1)
|
|
127
133
|
break;
|
|
128
134
|
const val = message[i + 1];
|
|
129
|
-
body.push(convertToString(val));
|
|
135
|
+
body.push(convertToString(val, objectRenderer));
|
|
130
136
|
}
|
|
131
137
|
return body;
|
|
132
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* A platform-specific inspect function. In Deno, this is {@link Deno.inspect},
|
|
141
|
+
* and in Node.js/Bun it is {@link util.inspect}. If neither is available, it
|
|
142
|
+
* falls back to {@link JSON.stringify}.
|
|
143
|
+
*
|
|
144
|
+
* @param value The value to inspect.
|
|
145
|
+
* @returns The string representation of the value.
|
|
146
|
+
*/
|
|
147
|
+
const inspect =
|
|
148
|
+
// @ts-ignore: Deno global
|
|
149
|
+
"Deno" in dntShim.dntGlobalThis && "inspect" in globalThis.Deno &&
|
|
150
|
+
// @ts-ignore: Deno global
|
|
151
|
+
typeof globalThis.Deno.inspect === "function"
|
|
152
|
+
// @ts-ignore: Deno global
|
|
153
|
+
? globalThis.Deno.inspect
|
|
154
|
+
// @ts-ignore: Node.js global
|
|
155
|
+
: "util" in dntShim.dntGlobalThis && "inspect" in globalThis.util &&
|
|
156
|
+
// @ts-ignore: Node.js global
|
|
157
|
+
globalThis.util.inspect === "function"
|
|
158
|
+
// @ts-ignore: Node.js global
|
|
159
|
+
? globalThis.util.inspect
|
|
160
|
+
: JSON.stringify;
|
|
133
161
|
class DiagLoggerAdaptor {
|
|
134
162
|
constructor() {
|
|
135
163
|
_DiagLoggerAdaptor_instances.add(this);
|
package/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dntGlobalThis = void 0;
|
|
4
|
+
const dntGlobals = {};
|
|
5
|
+
exports.dntGlobalThis = createMergeProxy(globalThis, dntGlobals);
|
|
6
|
+
function createMergeProxy(baseObj, extObj) {
|
|
7
|
+
return new Proxy(baseObj, {
|
|
8
|
+
get(_target, prop, _receiver) {
|
|
9
|
+
if (prop in extObj) {
|
|
10
|
+
return extObj[prop];
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
return baseObj[prop];
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
set(_target, prop, value) {
|
|
17
|
+
if (prop in extObj) {
|
|
18
|
+
delete extObj[prop];
|
|
19
|
+
}
|
|
20
|
+
baseObj[prop] = value;
|
|
21
|
+
return true;
|
|
22
|
+
},
|
|
23
|
+
deleteProperty(_target, prop) {
|
|
24
|
+
let success = false;
|
|
25
|
+
if (prop in extObj) {
|
|
26
|
+
delete extObj[prop];
|
|
27
|
+
success = true;
|
|
28
|
+
}
|
|
29
|
+
if (prop in baseObj) {
|
|
30
|
+
delete baseObj[prop];
|
|
31
|
+
success = true;
|
|
32
|
+
}
|
|
33
|
+
return success;
|
|
34
|
+
},
|
|
35
|
+
ownKeys(_target) {
|
|
36
|
+
const baseKeys = Reflect.ownKeys(baseObj);
|
|
37
|
+
const extKeys = Reflect.ownKeys(extObj);
|
|
38
|
+
const extKeysSet = new Set(extKeys);
|
|
39
|
+
return [...baseKeys.filter((k) => !extKeysSet.has(k)), ...extKeys];
|
|
40
|
+
},
|
|
41
|
+
defineProperty(_target, prop, desc) {
|
|
42
|
+
if (prop in extObj) {
|
|
43
|
+
delete extObj[prop];
|
|
44
|
+
}
|
|
45
|
+
Reflect.defineProperty(baseObj, prop, desc);
|
|
46
|
+
return true;
|
|
47
|
+
},
|
|
48
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
49
|
+
if (prop in extObj) {
|
|
50
|
+
return Reflect.getOwnPropertyDescriptor(extObj, prop);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return Reflect.getOwnPropertyDescriptor(baseObj, prop);
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
has(_target, prop) {
|
|
57
|
+
return prop in extObj || prop in baseObj;
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
package/script/deno.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = {
|
|
4
4
|
"name": "@logtape/otel",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.2.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./mod.ts"
|
|
@@ -17,7 +17,8 @@ exports.default = {
|
|
|
17
17
|
"@opentelemetry/otlp-exporter-base": "npm:@opentelemetry/otlp-exporter-base@^0.52.1",
|
|
18
18
|
"@opentelemetry/resources": "npm:@opentelemetry/resources@^1.25.1",
|
|
19
19
|
"@opentelemetry/sdk-logs": "npm:@opentelemetry/sdk-logs@^0.52.1",
|
|
20
|
-
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.26.0"
|
|
20
|
+
"@opentelemetry/semantic-conventions": "npm:@opentelemetry/semantic-conventions@^1.26.0",
|
|
21
|
+
"@std/dotenv": "jsr:@std/dotenv@^0.225.1"
|
|
21
22
|
},
|
|
22
23
|
"tasks": {
|
|
23
24
|
"dnt": "deno run -A dnt.ts"
|
package/script/mod.js
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
3
26
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
4
27
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
@@ -10,6 +33,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
33
|
var _DiagLoggerAdaptor_instances, _DiagLoggerAdaptor_escape;
|
|
11
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
35
|
exports.getOpenTelemetrySink = getOpenTelemetrySink;
|
|
36
|
+
const dntShim = __importStar(require("./_dnt.shims.js"));
|
|
13
37
|
const logtape_1 = require("@logtape/logtape");
|
|
14
38
|
const api_1 = require("@opentelemetry/api");
|
|
15
39
|
const api_logs_1 = require("@opentelemetry/api-logs");
|
|
@@ -43,6 +67,7 @@ function getOpenTelemetrySink(options = {}) {
|
|
|
43
67
|
else {
|
|
44
68
|
loggerProvider = options.loggerProvider;
|
|
45
69
|
}
|
|
70
|
+
const objectRenderer = options.objectRenderer ?? "inspect";
|
|
46
71
|
const logger = loggerProvider.getLogger(deno_js_1.default.name, deno_js_1.default.version);
|
|
47
72
|
const sink = (record) => {
|
|
48
73
|
const { category, level, message, timestamp, properties } = record;
|
|
@@ -51,13 +76,15 @@ function getOpenTelemetrySink(options = {}) {
|
|
|
51
76
|
return;
|
|
52
77
|
}
|
|
53
78
|
const severityNumber = mapLevelToSeverityNumber(level);
|
|
54
|
-
const attributes = convertToAttributes(properties);
|
|
79
|
+
const attributes = convertToAttributes(properties, objectRenderer);
|
|
55
80
|
attributes["category"] = [...category];
|
|
56
|
-
const body = convertMessageToBody(message);
|
|
81
|
+
const body = convertMessageToBody(message, objectRenderer);
|
|
57
82
|
logger.emit({
|
|
58
83
|
severityNumber,
|
|
59
84
|
severityText: level,
|
|
60
|
-
body
|
|
85
|
+
body: options.messageType === "array"
|
|
86
|
+
? body
|
|
87
|
+
: body.map((v) => v === undefined ? "undefined" : v === null ? "null" : v).join(""),
|
|
61
88
|
attributes,
|
|
62
89
|
timestamp: new Date(timestamp),
|
|
63
90
|
});
|
|
@@ -84,7 +111,7 @@ function mapLevelToSeverityNumber(level) {
|
|
|
84
111
|
return api_logs_1.SeverityNumber.UNSPECIFIED;
|
|
85
112
|
}
|
|
86
113
|
}
|
|
87
|
-
function convertToAttributes(properties) {
|
|
114
|
+
function convertToAttributes(properties, objectRenderer) {
|
|
88
115
|
const attributes = {};
|
|
89
116
|
for (const [name, value] of Object.entries(properties)) {
|
|
90
117
|
const key = `attributes.${name}`;
|
|
@@ -96,7 +123,7 @@ function convertToAttributes(properties) {
|
|
|
96
123
|
if (v == null)
|
|
97
124
|
continue;
|
|
98
125
|
if (t != null && typeof v !== t) {
|
|
99
|
-
attributes[key] = value.map(convertToString);
|
|
126
|
+
attributes[key] = value.map((v) => convertToString(v, objectRenderer));
|
|
100
127
|
break;
|
|
101
128
|
}
|
|
102
129
|
t = typeof v;
|
|
@@ -104,7 +131,7 @@ function convertToAttributes(properties) {
|
|
|
104
131
|
attributes[key] = value;
|
|
105
132
|
}
|
|
106
133
|
else {
|
|
107
|
-
const encoded = convertToString(value);
|
|
134
|
+
const encoded = convertToString(value, objectRenderer);
|
|
108
135
|
if (encoded == null)
|
|
109
136
|
continue;
|
|
110
137
|
attributes[key] = encoded;
|
|
@@ -112,11 +139,13 @@ function convertToAttributes(properties) {
|
|
|
112
139
|
}
|
|
113
140
|
return attributes;
|
|
114
141
|
}
|
|
115
|
-
function convertToString(value) {
|
|
142
|
+
function convertToString(value, objectRenderer) {
|
|
116
143
|
if (value === null || value === undefined || typeof value === "string") {
|
|
117
144
|
return value;
|
|
118
145
|
}
|
|
119
|
-
|
|
146
|
+
if (objectRenderer === "inspect")
|
|
147
|
+
return inspect(value);
|
|
148
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
120
149
|
return value.toString();
|
|
121
150
|
}
|
|
122
151
|
else if (value instanceof Date)
|
|
@@ -124,7 +153,7 @@ function convertToString(value) {
|
|
|
124
153
|
else
|
|
125
154
|
return JSON.stringify(value);
|
|
126
155
|
}
|
|
127
|
-
function convertMessageToBody(message) {
|
|
156
|
+
function convertMessageToBody(message, objectRenderer) {
|
|
128
157
|
const body = [];
|
|
129
158
|
for (let i = 0; i < message.length; i += 2) {
|
|
130
159
|
const msg = message[i];
|
|
@@ -132,10 +161,32 @@ function convertMessageToBody(message) {
|
|
|
132
161
|
if (message.length <= i + 1)
|
|
133
162
|
break;
|
|
134
163
|
const val = message[i + 1];
|
|
135
|
-
body.push(convertToString(val));
|
|
164
|
+
body.push(convertToString(val, objectRenderer));
|
|
136
165
|
}
|
|
137
166
|
return body;
|
|
138
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* A platform-specific inspect function. In Deno, this is {@link Deno.inspect},
|
|
170
|
+
* and in Node.js/Bun it is {@link util.inspect}. If neither is available, it
|
|
171
|
+
* falls back to {@link JSON.stringify}.
|
|
172
|
+
*
|
|
173
|
+
* @param value The value to inspect.
|
|
174
|
+
* @returns The string representation of the value.
|
|
175
|
+
*/
|
|
176
|
+
const inspect =
|
|
177
|
+
// @ts-ignore: Deno global
|
|
178
|
+
"Deno" in dntShim.dntGlobalThis && "inspect" in globalThis.Deno &&
|
|
179
|
+
// @ts-ignore: Deno global
|
|
180
|
+
typeof globalThis.Deno.inspect === "function"
|
|
181
|
+
// @ts-ignore: Deno global
|
|
182
|
+
? globalThis.Deno.inspect
|
|
183
|
+
// @ts-ignore: Node.js global
|
|
184
|
+
: "util" in dntShim.dntGlobalThis && "inspect" in globalThis.util &&
|
|
185
|
+
// @ts-ignore: Node.js global
|
|
186
|
+
globalThis.util.inspect === "function"
|
|
187
|
+
// @ts-ignore: Node.js global
|
|
188
|
+
? globalThis.util.inspect
|
|
189
|
+
: JSON.stringify;
|
|
139
190
|
class DiagLoggerAdaptor {
|
|
140
191
|
constructor() {
|
|
141
192
|
_DiagLoggerAdaptor_instances.add(this);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_dnt.shims.d.ts","sourceRoot":"","sources":["../src/_dnt.shims.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,gCAA2C,CAAC"}
|
package/types/deno.d.ts
CHANGED
package/types/mod.d.ts
CHANGED
|
@@ -19,38 +19,54 @@ type ILoggerProvider = LoggerProviderBase & {
|
|
|
19
19
|
*/
|
|
20
20
|
shutdown?: () => Promise<void>;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* The way to render the object in the log record. If `"json"`,
|
|
24
|
+
* the object is rendered as a JSON string. If `"inspect"`,
|
|
25
|
+
* the object is rendered using `util.inspect` in Node.js/Bun, or
|
|
26
|
+
* `Deno.inspect` in Deno.
|
|
27
|
+
*/
|
|
28
|
+
export type ObjectRenderer = "json" | "inspect";
|
|
22
29
|
/**
|
|
23
30
|
* Options for creating an OpenTelemetry sink.
|
|
24
31
|
*/
|
|
25
|
-
export
|
|
32
|
+
export interface OpenTelemetrySinkOptions {
|
|
26
33
|
/**
|
|
27
34
|
* The OpenTelemetry logger provider to use.
|
|
28
35
|
*/
|
|
29
|
-
loggerProvider
|
|
36
|
+
loggerProvider?: ILoggerProvider;
|
|
30
37
|
/**
|
|
31
|
-
*
|
|
32
|
-
* the
|
|
38
|
+
* The way to render the message in the log record. If `"string"`,
|
|
39
|
+
* the message is rendered as a single string with the values are
|
|
40
|
+
* interpolated into the message. If `"array"`, the message is
|
|
41
|
+
* rendered as an array of strings. `"string"` by default.
|
|
42
|
+
* @since 0.2.0
|
|
33
43
|
*/
|
|
34
|
-
|
|
35
|
-
} | {
|
|
44
|
+
messageType?: "string" | "array";
|
|
36
45
|
/**
|
|
37
|
-
* The
|
|
46
|
+
* The way to render the object in the log record. If `"json"`,
|
|
47
|
+
* the object is rendered as a JSON string. If `"inspect"`,
|
|
48
|
+
* the object is rendered using `util.inspect` in Node.js/Bun, or
|
|
49
|
+
* `Deno.inspect` in Deno. `"inspect"` by default.
|
|
38
50
|
*/
|
|
39
|
-
|
|
51
|
+
objectRenderer?: ObjectRenderer;
|
|
40
52
|
/**
|
|
41
53
|
* Whether to log diagnostics. Diagnostic logs are logged to
|
|
42
54
|
* the `["logtape", "meta", "otel"]` category.
|
|
55
|
+
* Turned off by default.
|
|
43
56
|
*/
|
|
44
57
|
diagnostics?: boolean;
|
|
45
58
|
/**
|
|
46
59
|
* The OpenTelemetry OTLP exporter configuration to use.
|
|
60
|
+
* Ignored if `loggerProvider` is provided.
|
|
47
61
|
*/
|
|
48
62
|
otlpExporterConfig?: OTLPExporterNodeConfigBase;
|
|
49
63
|
/**
|
|
50
|
-
* The service name to use.
|
|
64
|
+
* The service name to use. If not provided, the service name is
|
|
65
|
+
* taken from the `OTEL_SERVICE_NAME` environment variable.
|
|
66
|
+
* Ignored if `loggerProvider` is provided.
|
|
51
67
|
*/
|
|
52
68
|
serviceName?: string;
|
|
53
|
-
}
|
|
69
|
+
}
|
|
54
70
|
/**
|
|
55
71
|
* Creates a sink that forwards log records to OpenTelemetry.
|
|
56
72
|
* @param options Options for creating the sink.
|
package/types/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,IAAI,EACV,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAEL,KAAK,cAAc,IAAI,kBAAkB,EAG1C,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mCAAmC,CAAC;AAEpF,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,yBAAyB,CAAC;AAKjC;;GAEG;AACH,KAAK,eAAe,GAAG,kBAAkB,GAAG;IAC1C;;;OAGG;IACH,qBAAqB,CAAC,SAAS,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAE3D;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,cAAc,CAAC,EAAE,eAAe,CAAC;IAEjC;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAEjC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,0BAA0B,CAAC;IAEhD;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,wBAA6B,GACrC,IAAI,CAuDN"}
|