@logtape/otel 0.1.0 → 0.3.0-dev.5

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 CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm][npm badge]][npm]
6
6
  [![GitHub Actions][GitHub Actions badge]][GitHub Actions]
7
7
 
8
- This package provides an OpenTelemetry sink for [LogTape]. It allows you to
8
+ This package provides an [OpenTelemetry] sink for [LogTape]. It allows you to
9
9
  send your LogTape logs to OpenTelemetry-compatible backends.
10
10
 
11
11
  [JSR]: https://jsr.io/@logtape/otel
@@ -14,6 +14,7 @@ send your LogTape logs to OpenTelemetry-compatible backends.
14
14
  [npm badge]: https://img.shields.io/npm/v/@logtape/otel?logo=npm
15
15
  [GitHub Actions]: https://github.com/dahlia/logtape-otel/actions/workflows/main.yaml
16
16
  [GitHub Actions badge]: https://github.com/dahlia/logtape-otel/actions/workflows/main.yaml/badge.svg
17
+ [OpenTelemetry]: https://opentelemetry.io/
17
18
  [LogTape]: https://github.com/dahlia/logtape
18
19
 
19
20
 
@@ -109,7 +110,11 @@ await configure({
109
110
  });
110
111
  ~~~~
111
112
 
113
+ For more information, see the documentation of the [`getOpenTelemetrySink()`]
114
+ function and [`OpenTelemetrySinkOptions`] type.
115
+
112
116
  [`getOpenTelemetrySink()`]: https://jsr.io/@logtape/otel/doc/~/getOpenTelemetrySink
117
+ [`OpenTelemetrySinkOptions`]: https://jsr.io/@logtape/otel/doc/~/OpenTelemetrySinkOptions
113
118
  [`LoggerProvider`]: https://open-telemetry.github.io/opentelemetry-js/classes/_opentelemetry_sdk_logs.LoggerProvider.html
114
119
 
115
120
 
@@ -146,7 +151,22 @@ needed.
146
151
  Changelog
147
152
  ---------
148
153
 
149
- Version 0.1.0
150
- -------------
154
+ ### Version 0.3.0
155
+
156
+ To be released.
157
+
158
+
159
+ ### Version 0.2.0
160
+
161
+ Released on August 26, 2024.
162
+
163
+ - The `OpenTelemetrySinkOptions` type is now an interface.
164
+ - Added `OpenTelemetrySinkOptions.messageType` option.
165
+ - Added `OpenTelemetrySinkOptions.objectRenderer` option. Now non-scalar
166
+ values are rendered using `util.inspect()` in Node.js/Bun and
167
+ `Deno.inspect()` in Deno by default.
168
+
169
+
170
+ ### Version 0.1.0
151
171
 
152
172
  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.1.0",
3
+ "version": "0.3.0-dev.5+7ed92c72",
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,16 @@ 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);
51
52
  logger.emit({
52
53
  severityNumber,
53
54
  severityText: level,
54
- body,
55
+ body: typeof options.messageType === "function"
56
+ ? convertMessageToCustomBodyFormat(message, objectRenderer, options.messageType)
57
+ : options.messageType === "array"
58
+ ? convertMessageToArray(message, objectRenderer)
59
+ : convertMessageToString(message, objectRenderer),
55
60
  attributes,
56
61
  timestamp: new Date(timestamp),
57
62
  });
@@ -78,7 +83,7 @@ function mapLevelToSeverityNumber(level) {
78
83
  return SeverityNumber.UNSPECIFIED;
79
84
  }
80
85
  }
81
- function convertToAttributes(properties) {
86
+ function convertToAttributes(properties, objectRenderer) {
82
87
  const attributes = {};
83
88
  for (const [name, value] of Object.entries(properties)) {
84
89
  const key = `attributes.${name}`;
@@ -90,7 +95,7 @@ function convertToAttributes(properties) {
90
95
  if (v == null)
91
96
  continue;
92
97
  if (t != null && typeof v !== t) {
93
- attributes[key] = value.map(convertToString);
98
+ attributes[key] = value.map((v) => convertToString(v, objectRenderer));
94
99
  break;
95
100
  }
96
101
  t = typeof v;
@@ -98,7 +103,7 @@ function convertToAttributes(properties) {
98
103
  attributes[key] = value;
99
104
  }
100
105
  else {
101
- const encoded = convertToString(value);
106
+ const encoded = convertToString(value, objectRenderer);
102
107
  if (encoded == null)
103
108
  continue;
104
109
  attributes[key] = encoded;
@@ -106,11 +111,13 @@ function convertToAttributes(properties) {
106
111
  }
107
112
  return attributes;
108
113
  }
109
- function convertToString(value) {
114
+ function convertToString(value, objectRenderer) {
110
115
  if (value === null || value === undefined || typeof value === "string") {
111
116
  return value;
112
117
  }
113
- else if (typeof value === "number" || typeof value === "boolean") {
118
+ if (objectRenderer === "inspect")
119
+ return inspect(value);
120
+ if (typeof value === "number" || typeof value === "boolean") {
114
121
  return value.toString();
115
122
  }
116
123
  else if (value instanceof Date)
@@ -118,7 +125,7 @@ function convertToString(value) {
118
125
  else
119
126
  return JSON.stringify(value);
120
127
  }
121
- function convertMessageToBody(message) {
128
+ function convertMessageToArray(message, objectRenderer) {
122
129
  const body = [];
123
130
  for (let i = 0; i < message.length; i += 2) {
124
131
  const msg = message[i];
@@ -126,10 +133,49 @@ function convertMessageToBody(message) {
126
133
  if (message.length <= i + 1)
127
134
  break;
128
135
  const val = message[i + 1];
129
- body.push(convertToString(val));
136
+ body.push(convertToString(val, objectRenderer));
130
137
  }
131
138
  return body;
132
139
  }
140
+ function convertMessageToString(message, objectRenderer) {
141
+ let body = "";
142
+ for (let i = 0; i < message.length; i += 2) {
143
+ const msg = message[i];
144
+ body += msg;
145
+ if (message.length <= i + 1)
146
+ break;
147
+ const val = message[i + 1];
148
+ const extra = convertToString(val, objectRenderer);
149
+ body += extra ?? JSON.stringify(extra);
150
+ }
151
+ return body;
152
+ }
153
+ function convertMessageToCustomBodyFormat(message, objectRenderer, bodyFormatter) {
154
+ const body = message.map((msg) => convertToString(msg, objectRenderer));
155
+ return bodyFormatter(body);
156
+ }
157
+ /**
158
+ * A platform-specific inspect function. In Deno, this is {@link Deno.inspect},
159
+ * and in Node.js/Bun it is {@link util.inspect}. If neither is available, it
160
+ * falls back to {@link JSON.stringify}.
161
+ *
162
+ * @param value The value to inspect.
163
+ * @returns The string representation of the value.
164
+ */
165
+ const inspect =
166
+ // @ts-ignore: Deno global
167
+ "Deno" in dntShim.dntGlobalThis && "inspect" in globalThis.Deno &&
168
+ // @ts-ignore: Deno global
169
+ typeof globalThis.Deno.inspect === "function"
170
+ // @ts-ignore: Deno global
171
+ ? globalThis.Deno.inspect
172
+ // @ts-ignore: Node.js global
173
+ : "util" in dntShim.dntGlobalThis && "inspect" in globalThis.util &&
174
+ // @ts-ignore: Node.js global
175
+ globalThis.util.inspect === "function"
176
+ // @ts-ignore: Node.js global
177
+ ? globalThis.util.inspect
178
+ : JSON.stringify;
133
179
  class DiagLoggerAdaptor {
134
180
  constructor() {
135
181
  _DiagLoggerAdaptor_instances.add(this);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logtape/otel",
3
- "version": "0.1.0",
3
+ "version": "0.3.0-dev.5+7ed92c72",
4
4
  "description": "LogTape OpenTelemetry Sink",
5
5
  "keywords": [
6
6
  "LogTape",
@@ -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.1.0",
5
+ "version": "0.3.0-dev.5+7ed92c72",
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,16 @@ 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);
57
81
  logger.emit({
58
82
  severityNumber,
59
83
  severityText: level,
60
- body,
84
+ body: typeof options.messageType === "function"
85
+ ? convertMessageToCustomBodyFormat(message, objectRenderer, options.messageType)
86
+ : options.messageType === "array"
87
+ ? convertMessageToArray(message, objectRenderer)
88
+ : convertMessageToString(message, objectRenderer),
61
89
  attributes,
62
90
  timestamp: new Date(timestamp),
63
91
  });
@@ -84,7 +112,7 @@ function mapLevelToSeverityNumber(level) {
84
112
  return api_logs_1.SeverityNumber.UNSPECIFIED;
85
113
  }
86
114
  }
87
- function convertToAttributes(properties) {
115
+ function convertToAttributes(properties, objectRenderer) {
88
116
  const attributes = {};
89
117
  for (const [name, value] of Object.entries(properties)) {
90
118
  const key = `attributes.${name}`;
@@ -96,7 +124,7 @@ function convertToAttributes(properties) {
96
124
  if (v == null)
97
125
  continue;
98
126
  if (t != null && typeof v !== t) {
99
- attributes[key] = value.map(convertToString);
127
+ attributes[key] = value.map((v) => convertToString(v, objectRenderer));
100
128
  break;
101
129
  }
102
130
  t = typeof v;
@@ -104,7 +132,7 @@ function convertToAttributes(properties) {
104
132
  attributes[key] = value;
105
133
  }
106
134
  else {
107
- const encoded = convertToString(value);
135
+ const encoded = convertToString(value, objectRenderer);
108
136
  if (encoded == null)
109
137
  continue;
110
138
  attributes[key] = encoded;
@@ -112,11 +140,13 @@ function convertToAttributes(properties) {
112
140
  }
113
141
  return attributes;
114
142
  }
115
- function convertToString(value) {
143
+ function convertToString(value, objectRenderer) {
116
144
  if (value === null || value === undefined || typeof value === "string") {
117
145
  return value;
118
146
  }
119
- else if (typeof value === "number" || typeof value === "boolean") {
147
+ if (objectRenderer === "inspect")
148
+ return inspect(value);
149
+ if (typeof value === "number" || typeof value === "boolean") {
120
150
  return value.toString();
121
151
  }
122
152
  else if (value instanceof Date)
@@ -124,7 +154,7 @@ function convertToString(value) {
124
154
  else
125
155
  return JSON.stringify(value);
126
156
  }
127
- function convertMessageToBody(message) {
157
+ function convertMessageToArray(message, objectRenderer) {
128
158
  const body = [];
129
159
  for (let i = 0; i < message.length; i += 2) {
130
160
  const msg = message[i];
@@ -132,10 +162,49 @@ function convertMessageToBody(message) {
132
162
  if (message.length <= i + 1)
133
163
  break;
134
164
  const val = message[i + 1];
135
- body.push(convertToString(val));
165
+ body.push(convertToString(val, objectRenderer));
136
166
  }
137
167
  return body;
138
168
  }
169
+ function convertMessageToString(message, objectRenderer) {
170
+ let body = "";
171
+ for (let i = 0; i < message.length; i += 2) {
172
+ const msg = message[i];
173
+ body += msg;
174
+ if (message.length <= i + 1)
175
+ break;
176
+ const val = message[i + 1];
177
+ const extra = convertToString(val, objectRenderer);
178
+ body += extra ?? JSON.stringify(extra);
179
+ }
180
+ return body;
181
+ }
182
+ function convertMessageToCustomBodyFormat(message, objectRenderer, bodyFormatter) {
183
+ const body = message.map((msg) => convertToString(msg, objectRenderer));
184
+ return bodyFormatter(body);
185
+ }
186
+ /**
187
+ * A platform-specific inspect function. In Deno, this is {@link Deno.inspect},
188
+ * and in Node.js/Bun it is {@link util.inspect}. If neither is available, it
189
+ * falls back to {@link JSON.stringify}.
190
+ *
191
+ * @param value The value to inspect.
192
+ * @returns The string representation of the value.
193
+ */
194
+ const inspect =
195
+ // @ts-ignore: Deno global
196
+ "Deno" in dntShim.dntGlobalThis && "inspect" in globalThis.Deno &&
197
+ // @ts-ignore: Deno global
198
+ typeof globalThis.Deno.inspect === "function"
199
+ // @ts-ignore: Deno global
200
+ ? globalThis.Deno.inspect
201
+ // @ts-ignore: Node.js global
202
+ : "util" in dntShim.dntGlobalThis && "inspect" in globalThis.util &&
203
+ // @ts-ignore: Node.js global
204
+ globalThis.util.inspect === "function"
205
+ // @ts-ignore: Node.js global
206
+ ? globalThis.util.inspect
207
+ : JSON.stringify;
139
208
  class DiagLoggerAdaptor {
140
209
  constructor() {
141
210
  _DiagLoggerAdaptor_instances.add(this);
@@ -0,0 +1,2 @@
1
+ export declare const dntGlobalThis: Omit<typeof globalThis, never>;
2
+ //# sourceMappingURL=_dnt.shims.d.ts.map
@@ -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
@@ -16,6 +16,7 @@ declare namespace _default {
16
16
  "@opentelemetry/resources": string;
17
17
  "@opentelemetry/sdk-logs": string;
18
18
  "@opentelemetry/semantic-conventions": string;
19
+ "@std/dotenv": string;
19
20
  };
20
21
  namespace tasks {
21
22
  let dnt: string;
package/types/mod.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type Sink } from "@logtape/logtape";
2
- import { type LoggerProvider as LoggerProviderBase } from "@opentelemetry/api-logs";
2
+ import { type AnyValue, type LoggerProvider as LoggerProviderBase } from "@opentelemetry/api-logs";
3
3
  import type { OTLPExporterNodeConfigBase } from "@opentelemetry/otlp-exporter-base";
4
4
  import { type LogRecordProcessor } from "@opentelemetry/sdk-logs";
5
5
  /**
@@ -19,38 +19,61 @@ 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";
29
+ type Message = (string | null | undefined)[];
30
+ /**
31
+ * Custom `body` attribute formatter
32
+ */
33
+ export type BodyFormatter = (message: Message) => AnyValue;
22
34
  /**
23
35
  * Options for creating an OpenTelemetry sink.
24
36
  */
25
- export type OpenTelemetrySinkOptions = {
37
+ export interface OpenTelemetrySinkOptions {
26
38
  /**
27
39
  * The OpenTelemetry logger provider to use.
28
40
  */
29
- loggerProvider: ILoggerProvider;
41
+ loggerProvider?: ILoggerProvider;
30
42
  /**
31
- * Whether to log diagnostics. Diagnostic logs are logged to
32
- * the `["logtape", "meta", "otel"]` category.
43
+ * The way to render the message in the log record. If `"string"`,
44
+ * the message is rendered as a single string with the values are
45
+ * interpolated into the message. If `"array"`, the message is
46
+ * rendered as an array of strings. `"string"` by default.
47
+ * @since 0.2.0
48
+ *
49
+ * Or even fully customizable with a {@link BodyFormatter} function.
33
50
  */
34
- diagnostics?: boolean;
35
- } | {
51
+ messageType?: "string" | "array" | BodyFormatter;
36
52
  /**
37
- * The OpenTelemetry logger provider to use.
53
+ * The way to render the object in the log record. If `"json"`,
54
+ * the object is rendered as a JSON string. If `"inspect"`,
55
+ * the object is rendered using `util.inspect` in Node.js/Bun, or
56
+ * `Deno.inspect` in Deno. `"inspect"` by default.
38
57
  */
39
- loggerProvider?: undefined;
58
+ objectRenderer?: ObjectRenderer;
40
59
  /**
41
60
  * Whether to log diagnostics. Diagnostic logs are logged to
42
61
  * the `["logtape", "meta", "otel"]` category.
62
+ * Turned off by default.
43
63
  */
44
64
  diagnostics?: boolean;
45
65
  /**
46
66
  * The OpenTelemetry OTLP exporter configuration to use.
67
+ * Ignored if `loggerProvider` is provided.
47
68
  */
48
69
  otlpExporterConfig?: OTLPExporterNodeConfigBase;
49
70
  /**
50
- * The service name to use.
71
+ * The service name to use. If not provided, the service name is
72
+ * taken from the `OTEL_SERVICE_NAME` environment variable.
73
+ * Ignored if `loggerProvider` is provided.
51
74
  */
52
75
  serviceName?: string;
53
- };
76
+ }
54
77
  /**
55
78
  * Creates a sink that forwards log records to OpenTelemetry.
56
79
  * @param options Options for creating the sink.
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,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;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAChC;IACA;;OAEG;IACH,cAAc,EAAE,eAAe,CAAC;IAEhC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GACC;IACA;;OAEG;IACH,cAAc,CAAC,EAAE,SAAS,CAAC;IAE3B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;OAEG;IACH,kBAAkB,CAAC,EAAE,0BAA0B,CAAC;IAEhD;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEJ;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,wBAA6B,GACrC,IAAI,CAkDN"}
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,EACL,KAAK,QAAQ,EACb,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,KAAK,OAAO,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;OAEG;IACH,cAAc,CAAC,EAAE,eAAe,CAAC;IAEjC;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAC;IAEjD;;;;;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,CA0DN"}