@upyo/logtape 0.6.0-dev.249 → 0.6.0-dev.263

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
@@ -53,6 +53,28 @@ const transport = new LogTapeTransport({
53
53
  });
54
54
  ~~~~
55
55
 
56
- Complete messages are excluded from structured logs by default. Set
57
- `recordMessage: true` only when the configured sinks and redaction rules can
58
- safely handle addresses, bodies, headers, and attachment data.
56
+ Complete messages are excluded from logs by default. Set `recordMessage` to
57
+ `"properties"` to add the complete `Message` object to each lifecycle event
58
+ while keeping its log message on one line:
59
+
60
+ ~~~~ typescript
61
+ const transport = new LogTapeTransport({
62
+ recordMessage: "properties",
63
+ });
64
+ ~~~~
65
+
66
+ For local development, `"inline"` also renders the subject and body beneath
67
+ the lifecycle message:
68
+
69
+ ~~~~ typescript
70
+ const transport = new LogTapeTransport({
71
+ recordMessage: "inline",
72
+ });
73
+ ~~~~
74
+
75
+ Inline logs use the plain-text body when it is defined, including an empty
76
+ string, and otherwise use the HTML body. Subject and body values remain
77
+ LogTape placeholders so sinks can apply their own rendering and redaction.
78
+ Both modes expose the complete message, which may contain addresses, bodies,
79
+ headers, and attachment data. Use them only when the configured sinks,
80
+ access controls, and redaction rules can safely handle that data.
package/dist/index.cjs CHANGED
@@ -234,7 +234,7 @@ var LogTapeTransport = class {
234
234
  };
235
235
  }
236
236
  logSending(message, operation) {
237
- this.log(this.config.levels.sending, "Sending email.", {
237
+ this.log(this.config.levels.sending, this.getMessageTemplate("Sending email.", message), {
238
238
  ...this.getMessageProperties(message),
239
239
  event: "email.sending",
240
240
  operation,
@@ -245,7 +245,7 @@ var LogTapeTransport = class {
245
245
  const durationMilliseconds = pendingMessage == null ? void 0 : performance.now() - pendingMessage.startedAt;
246
246
  const messageProperties = pendingMessage == null ? {} : this.getMessageProperties(pendingMessage.message);
247
247
  if (receipt.successful) {
248
- this.log(this.config.levels.sent, "Email sent.", {
248
+ this.log(this.config.levels.sent, this.getMessageTemplate("Email sent.", pendingMessage?.message), {
249
249
  ...messageProperties,
250
250
  event: "email.sent",
251
251
  operation,
@@ -257,7 +257,7 @@ var LogTapeTransport = class {
257
257
  });
258
258
  return;
259
259
  }
260
- this.log(this.config.levels.failed, "Failed to send email.", {
260
+ this.log(this.config.levels.failed, this.getMessageTemplate("Failed to send email.", pendingMessage?.message), {
261
261
  ...messageProperties,
262
262
  event: "email.failed",
263
263
  operation,
@@ -272,7 +272,7 @@ var LogTapeTransport = class {
272
272
  });
273
273
  }
274
274
  logThrownError(error, message, operation, startedAt, extraProperties = {}) {
275
- this.log(this.config.levels.failed, "Failed to send email: {error}", {
275
+ this.log(this.config.levels.failed, this.getMessageTemplate("Failed to send email: {error}", message), {
276
276
  ...message == null ? {} : this.getMessageProperties(message),
277
277
  ...extraProperties,
278
278
  event: "email.failed",
@@ -301,9 +301,14 @@ var LogTapeTransport = class {
301
301
  bccRecipientCount: message.bccRecipients.length,
302
302
  attachmentCount: message.attachments.length,
303
303
  priority: message.priority,
304
- ...this.config.recordMessage ? { message } : {}
304
+ ...this.config.recordMessage === false ? {} : { message }
305
305
  };
306
306
  }
307
+ getMessageTemplate(lifecycleMessage, message) {
308
+ if (this.config.recordMessage !== "inline" || message == null) return lifecycleMessage;
309
+ const contentPlaceholder = "text" in message.content && message.content.text !== void 0 ? "{message.content.text}" : "{message.content.html}";
310
+ return `${lifecycleMessage}\n\nSubject: {message.subject}\n\n${contentPlaceholder}`;
311
+ }
307
312
  log(level, message, properties) {
308
313
  this.logger[level](message, properties);
309
314
  }
package/dist/index.d.cts CHANGED
@@ -49,15 +49,19 @@ interface LogTapeTransportOptions<TProviderId extends string = "logtape"> {
49
49
  */
50
50
  readonly category?: string | readonly string[];
51
51
  /**
52
- * Whether to include the complete email message in structured log
53
- * properties.
52
+ * How to include the complete email message in logs.
53
+ *
54
+ * `"properties"` adds the message to structured log properties while
55
+ * keeping the lifecycle message on one line. `"inline"` also renders the
56
+ * subject and body beneath the lifecycle message. Plain text is preferred
57
+ * when it is defined; otherwise, the HTML body is rendered.
54
58
  *
55
59
  * Messages may contain sensitive or large values, including email bodies,
56
60
  * headers, and attachment data.
57
61
  *
58
- * @default false
62
+ * @default undefined
59
63
  */
60
- readonly recordMessage?: boolean;
64
+ readonly recordMessage?: "properties" | "inline";
61
65
  /**
62
66
  * Levels used for delivery lifecycle events.
63
67
  */
@@ -74,8 +78,8 @@ interface ResolvedLogTapeTransportOptions<TProviderId extends string = "logtape"
74
78
  readonly transport?: Transport<TProviderId>;
75
79
  /** Resolved LogTape category. */
76
80
  readonly category: readonly string[];
77
- /** Whether complete messages are included in structured logs. */
78
- readonly recordMessage: boolean;
81
+ /** Resolved complete-message recording mode, or `false` when disabled. */
82
+ readonly recordMessage: "properties" | "inline" | false;
79
83
  /** Resolved delivery lifecycle log levels. */
80
84
  readonly levels: Required<LogTapeTransportLevels>;
81
85
  }
@@ -155,6 +159,7 @@ declare class LogTapeTransport<TProviderId extends string = "logtape"> implement
155
159
  private logThrownError;
156
160
  private logBatchThrownError;
157
161
  private getMessageProperties;
162
+ private getMessageTemplate;
158
163
  private log;
159
164
  }
160
165
  //#endregion
package/dist/index.d.ts CHANGED
@@ -49,15 +49,19 @@ interface LogTapeTransportOptions<TProviderId extends string = "logtape"> {
49
49
  */
50
50
  readonly category?: string | readonly string[];
51
51
  /**
52
- * Whether to include the complete email message in structured log
53
- * properties.
52
+ * How to include the complete email message in logs.
53
+ *
54
+ * `"properties"` adds the message to structured log properties while
55
+ * keeping the lifecycle message on one line. `"inline"` also renders the
56
+ * subject and body beneath the lifecycle message. Plain text is preferred
57
+ * when it is defined; otherwise, the HTML body is rendered.
54
58
  *
55
59
  * Messages may contain sensitive or large values, including email bodies,
56
60
  * headers, and attachment data.
57
61
  *
58
- * @default false
62
+ * @default undefined
59
63
  */
60
- readonly recordMessage?: boolean;
64
+ readonly recordMessage?: "properties" | "inline";
61
65
  /**
62
66
  * Levels used for delivery lifecycle events.
63
67
  */
@@ -74,8 +78,8 @@ interface ResolvedLogTapeTransportOptions<TProviderId extends string = "logtape"
74
78
  readonly transport?: Transport<TProviderId>;
75
79
  /** Resolved LogTape category. */
76
80
  readonly category: readonly string[];
77
- /** Whether complete messages are included in structured logs. */
78
- readonly recordMessage: boolean;
81
+ /** Resolved complete-message recording mode, or `false` when disabled. */
82
+ readonly recordMessage: "properties" | "inline" | false;
79
83
  /** Resolved delivery lifecycle log levels. */
80
84
  readonly levels: Required<LogTapeTransportLevels>;
81
85
  }
@@ -155,6 +159,7 @@ declare class LogTapeTransport<TProviderId extends string = "logtape"> implement
155
159
  private logThrownError;
156
160
  private logBatchThrownError;
157
161
  private getMessageProperties;
162
+ private getMessageTemplate;
158
163
  private log;
159
164
  }
160
165
  //#endregion
package/dist/index.js CHANGED
@@ -211,7 +211,7 @@ var LogTapeTransport = class {
211
211
  };
212
212
  }
213
213
  logSending(message, operation) {
214
- this.log(this.config.levels.sending, "Sending email.", {
214
+ this.log(this.config.levels.sending, this.getMessageTemplate("Sending email.", message), {
215
215
  ...this.getMessageProperties(message),
216
216
  event: "email.sending",
217
217
  operation,
@@ -222,7 +222,7 @@ var LogTapeTransport = class {
222
222
  const durationMilliseconds = pendingMessage == null ? void 0 : performance.now() - pendingMessage.startedAt;
223
223
  const messageProperties = pendingMessage == null ? {} : this.getMessageProperties(pendingMessage.message);
224
224
  if (receipt.successful) {
225
- this.log(this.config.levels.sent, "Email sent.", {
225
+ this.log(this.config.levels.sent, this.getMessageTemplate("Email sent.", pendingMessage?.message), {
226
226
  ...messageProperties,
227
227
  event: "email.sent",
228
228
  operation,
@@ -234,7 +234,7 @@ var LogTapeTransport = class {
234
234
  });
235
235
  return;
236
236
  }
237
- this.log(this.config.levels.failed, "Failed to send email.", {
237
+ this.log(this.config.levels.failed, this.getMessageTemplate("Failed to send email.", pendingMessage?.message), {
238
238
  ...messageProperties,
239
239
  event: "email.failed",
240
240
  operation,
@@ -249,7 +249,7 @@ var LogTapeTransport = class {
249
249
  });
250
250
  }
251
251
  logThrownError(error, message, operation, startedAt, extraProperties = {}) {
252
- this.log(this.config.levels.failed, "Failed to send email: {error}", {
252
+ this.log(this.config.levels.failed, this.getMessageTemplate("Failed to send email: {error}", message), {
253
253
  ...message == null ? {} : this.getMessageProperties(message),
254
254
  ...extraProperties,
255
255
  event: "email.failed",
@@ -278,9 +278,14 @@ var LogTapeTransport = class {
278
278
  bccRecipientCount: message.bccRecipients.length,
279
279
  attachmentCount: message.attachments.length,
280
280
  priority: message.priority,
281
- ...this.config.recordMessage ? { message } : {}
281
+ ...this.config.recordMessage === false ? {} : { message }
282
282
  };
283
283
  }
284
+ getMessageTemplate(lifecycleMessage, message) {
285
+ if (this.config.recordMessage !== "inline" || message == null) return lifecycleMessage;
286
+ const contentPlaceholder = "text" in message.content && message.content.text !== void 0 ? "{message.content.text}" : "{message.content.html}";
287
+ return `${lifecycleMessage}\n\nSubject: {message.subject}\n\n${contentPlaceholder}`;
288
+ }
284
289
  log(level, message, properties) {
285
290
  this.logger[level](message, properties);
286
291
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upyo/logtape",
3
- "version": "0.6.0-dev.249",
3
+ "version": "0.6.0-dev.263",
4
4
  "description": "LogTape observability transport for Upyo email library",
5
5
  "keywords": [
6
6
  "email",
@@ -55,7 +55,7 @@
55
55
  "sideEffects": false,
56
56
  "peerDependencies": {
57
57
  "@logtape/logtape": "^2.2.4",
58
- "@upyo/core": "0.6.0-dev.249+f899569f"
58
+ "@upyo/core": "0.6.0-dev.263+e633e1e6"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@logtape/logtape": "^2.2.4",