@adaptic/utils 0.0.957 → 0.0.959
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/dist/index.cjs +94 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +94 -1
- package/dist/index.mjs.map +1 -1
- package/dist/test.js +22 -1
- package/dist/test.js.map +1 -1
- package/dist/types/__tests__/logging.test.d.ts +2 -0
- package/dist/types/__tests__/logging.test.d.ts.map +1 -0
- package/dist/types/logger.d.ts +12 -0
- package/dist/types/logger.d.ts.map +1 -1
- package/dist/types/logging.d.ts +21 -1
- package/dist/types/logging.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -60,6 +60,7 @@ const defaultLogger = {
|
|
|
60
60
|
debug: (msg, ctx) => console.debug(msg, normalizeContext(ctx) || ""),
|
|
61
61
|
};
|
|
62
62
|
let currentLogger = defaultLogger;
|
|
63
|
+
let loggerInjected = false;
|
|
63
64
|
/**
|
|
64
65
|
* Sets a custom logger implementation.
|
|
65
66
|
* Call this to integrate with Pino or other logging libraries.
|
|
@@ -83,6 +84,21 @@ let currentLogger = defaultLogger;
|
|
|
83
84
|
*/
|
|
84
85
|
function setLogger(logger) {
|
|
85
86
|
currentLogger = logger;
|
|
87
|
+
loggerInjected = true;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Returns true when an external logger has been injected via {@link setLogger}.
|
|
91
|
+
*
|
|
92
|
+
* Used by the legacy {@link log} export in `logging.ts` to decide whether to
|
|
93
|
+
* route messages through the injected (production) logger or fall back to the
|
|
94
|
+
* `DisplayManager` terminal widget (standalone CLI usage). Without this flag,
|
|
95
|
+
* library code that imports `log` from `./logging` would silently bypass any
|
|
96
|
+
* structured logging pipeline (Pino, OTel) the host application has wired in.
|
|
97
|
+
*
|
|
98
|
+
* @returns `true` if {@link setLogger} has been called since the last reset
|
|
99
|
+
*/
|
|
100
|
+
function isLoggerInjected() {
|
|
101
|
+
return loggerInjected;
|
|
86
102
|
}
|
|
87
103
|
/**
|
|
88
104
|
* Gets the current logger instance.
|
|
@@ -110,6 +126,7 @@ function getLogger() {
|
|
|
110
126
|
*/
|
|
111
127
|
function resetLogger() {
|
|
112
128
|
currentLogger = defaultLogger;
|
|
129
|
+
loggerInjected = false;
|
|
113
130
|
}
|
|
114
131
|
|
|
115
132
|
/**
|
|
@@ -929,15 +946,91 @@ class DisplayManager {
|
|
|
929
946
|
}
|
|
930
947
|
|
|
931
948
|
/**
|
|
932
|
-
*
|
|
949
|
+
* LogType values that should map to a `Logger.info()` call when routed
|
|
950
|
+
* through an injected structured logger. Anything not in this set is
|
|
951
|
+
* treated as `info` (the safe default for unknown levels).
|
|
952
|
+
*/
|
|
953
|
+
const INFO_LEVEL_TYPES = new Set([
|
|
954
|
+
"info",
|
|
955
|
+
"major",
|
|
956
|
+
"table",
|
|
957
|
+
"system",
|
|
958
|
+
"cost",
|
|
959
|
+
]);
|
|
960
|
+
/**
|
|
961
|
+
* Builds the structured-logger context object for an injected logger call.
|
|
962
|
+
*
|
|
963
|
+
* The injected logger is expected to be a Pino-style structured logger
|
|
964
|
+
* (the engine wires it via `setUtilsLogger({...})` from
|
|
965
|
+
* `service-initializer.ts`). We surface every meaningful field from
|
|
966
|
+
* `LogOptions` so downstream consumers can filter, query, and correlate.
|
|
967
|
+
*/
|
|
968
|
+
function buildLoggerContext(options) {
|
|
969
|
+
const context = {};
|
|
970
|
+
if (options.source)
|
|
971
|
+
context.source = options.source;
|
|
972
|
+
if (options.account)
|
|
973
|
+
context.account = options.account;
|
|
974
|
+
if (options.symbol)
|
|
975
|
+
context.symbol = options.symbol;
|
|
976
|
+
if (options.type)
|
|
977
|
+
context.logType = options.type;
|
|
978
|
+
if (options.metadata)
|
|
979
|
+
Object.assign(context, options.metadata);
|
|
980
|
+
return context;
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Logs a message.
|
|
984
|
+
*
|
|
985
|
+
* **Routing strategy:**
|
|
986
|
+
* 1. If a structured logger has been injected via `setLogger()` (the engine
|
|
987
|
+
* does this on startup with a Pino child logger), route the message
|
|
988
|
+
* through that logger so it joins the centralised logging pipeline with
|
|
989
|
+
* full structure, source attribution, correlation IDs, and downstream
|
|
990
|
+
* aggregation.
|
|
991
|
+
* 2. Otherwise (standalone CLI usage of `@adaptic/utils`), fall back to the
|
|
992
|
+
* legacy `DisplayManager`, which writes directly to `process.stdout` with
|
|
993
|
+
* ANSI colours, prompt preservation, and optional symbol-specific log
|
|
994
|
+
* files. This preserves backward compatibility for scripts.
|
|
995
|
+
*
|
|
996
|
+
* Without this routing, every Alpaca client call (positions, orders,
|
|
997
|
+
* streams, market-data, crypto, options — 28 modules) would silently
|
|
998
|
+
* bypass the host application's structured logger and emit unstructured
|
|
999
|
+
* lines straight to stdout, producing a long-running observability gap
|
|
1000
|
+
* in production deployments.
|
|
1001
|
+
*
|
|
933
1002
|
* @param message The message to log.
|
|
934
1003
|
* @param options Optional options.
|
|
935
1004
|
* @param options.source The source of the message.
|
|
936
1005
|
* @param options.type The type of message to log.
|
|
937
1006
|
* @param options.symbol The trading symbol associated with this log.
|
|
938
1007
|
* @param options.logToFile Force logging to a file even when no symbol is provided.
|
|
1008
|
+
* @param options.account Optional account identifier surfaced in logs.
|
|
1009
|
+
* @param options.metadata Additional structured fields to merge into context.
|
|
939
1010
|
*/
|
|
940
1011
|
function log$m(message, options = { source: "Server", type: "info" }) {
|
|
1012
|
+
if (isLoggerInjected()) {
|
|
1013
|
+
const logger = getLogger();
|
|
1014
|
+
const context = buildLoggerContext(options);
|
|
1015
|
+
const type = options.type ?? "info";
|
|
1016
|
+
if (type === "error") {
|
|
1017
|
+
logger.error(message, context);
|
|
1018
|
+
}
|
|
1019
|
+
else if (type === "warn") {
|
|
1020
|
+
logger.warn(message, context);
|
|
1021
|
+
}
|
|
1022
|
+
else if (type === "debug") {
|
|
1023
|
+
logger.debug(message, context);
|
|
1024
|
+
}
|
|
1025
|
+
else if (INFO_LEVEL_TYPES.has(type)) {
|
|
1026
|
+
logger.info(message, context);
|
|
1027
|
+
}
|
|
1028
|
+
else {
|
|
1029
|
+
logger.info(message, context);
|
|
1030
|
+
}
|
|
1031
|
+
return;
|
|
1032
|
+
}
|
|
1033
|
+
// Fallback: standalone CLI / no host logger wired in.
|
|
941
1034
|
const displayManager = DisplayManager.getInstance();
|
|
942
1035
|
displayManager.log(message, options);
|
|
943
1036
|
}
|