From cfb9986a513f04c2b1d692a1966418bbcc2a7174 Mon Sep 17 00:00:00 2001 From: Budleigh Salterton Date: Tue, 19 Mar 2024 11:48:11 +0000 Subject: [PATCH 1/5] Allow runner log level change --- packages/obj-logger/src/obj-logger.ts | 37 ++++++++++++++++--- packages/runner/src/runner.ts | 30 +++++++++------ .../types/src/api-client/manager-client.ts | 2 +- .../src/messages/handshake-acknowledge.ts | 4 +- packages/types/src/object-logger.ts | 2 + 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/packages/obj-logger/src/obj-logger.ts b/packages/obj-logger/src/obj-logger.ts index 826f12a67..365d4c616 100644 --- a/packages/obj-logger/src/obj-logger.ts +++ b/packages/obj-logger/src/obj-logger.ts @@ -10,6 +10,8 @@ type ObjLogPipeOptions = { stringified?: boolean; }; +const noop = () => {}; + const getCircularReplacer = () => { const seen = new WeakSet(); @@ -65,7 +67,36 @@ export class ObjLogger implements IObjectLogger { /** * Log level. */ - logLevel: LogLevel; + private _logLevel: LogLevel = "TRACE"; + + public get logLevel(): LogLevel { + return this._logLevel; + } + public set logLevel(value: LogLevel) { + this._logLevel = value; + + this.trace = noop; + this.info = noop; + this.error = noop; + this.debug = noop; + this.fatal = noop; + this.warn = noop; + + switch (value) { + case "TRACE": + this.trace = ObjLogger.prototype.trace; + case "DEBUG": + this.debug = ObjLogger.prototype.debug; + case "INFO": + this.info = ObjLogger.prototype.info; + case "WARN": + this.warn = ObjLogger.prototype.warn; + case "ERROR": + this.error = ObjLogger.prototype.error; + case "FATAL": + this.fatal = ObjLogger.prototype.fatal; + } + } /** * Additional output streams. @@ -115,10 +146,6 @@ export class ObjLogger implements IObjectLogger { if (this.ended) throw new Error("Cannot write to the stream anymore."); - if (ObjLogger.levels.indexOf(level) > ObjLogger.levels.indexOf(this.logLevel)) { - return; - } - let paramsCopy; if (optionalParams.length) { diff --git a/packages/runner/src/runner.ts b/packages/runner/src/runner.ts index 0a54e602d..c1653d4fb 100644 --- a/packages/runner/src/runner.ts +++ b/packages/runner/src/runner.ts @@ -231,10 +231,10 @@ export class Runner implements IComponent { await this.handleKillRequest(); break; case RunnerMessageCode.STOP: - await this.addStopHandlerRequest(data as StopSequenceMessageData); + await this.handleStopRequest(data as StopSequenceMessageData); break; case RunnerMessageCode.PONG: - this.handshakeResolver?.res(data); + this.handlePongRequest(data as HandshakeAcknowledgeMessageData); break; case RunnerMessageCode.EVENT: const eventData = data as EventMessageData; @@ -248,6 +248,14 @@ export class Runner implements IComponent { } } + private handlePongRequest(data: HandshakeAcknowledgeMessageData) { + this.handshakeResolver?.res(data); + + if (data.logLevel) { + this.logger.logLevel = data.logLevel; + } + } + defineControlStream() { StringStream .from(this.hostClient.controlStream) @@ -272,7 +280,7 @@ export class Runner implements IComponent { } async handleMonitoringRequest(data: MonitoringRateMessageData): Promise { - this.logger.info("handleMonitoringRequest"); + this.logger.debug("handleMonitoringRequest"); if (this.monitoringInterval) { clearInterval(this.monitoringInterval); @@ -281,7 +289,7 @@ export class Runner implements IComponent { let working = false; this.monitoringInterval = setInterval(async () => { - this.logger.info("working", working); + this.logger.debug("working", working); if (working) { //return; @@ -294,7 +302,7 @@ export class Runner implements IComponent { } private async reportHealth(timeout?: number) { - this.logger.info("Report health"); + // this.logger.info("Report health"); const { healthy } = await this.context.monitor(); @@ -348,19 +356,19 @@ export class Runner implements IComponent { this.context.killHandler(); if (!this.stopExpected) { - this.logger.trace(`Exiting (unexpected, ${RunnerExitCode.KILLED})`); + this.logger.warn(`Exiting (unexpected, ${RunnerExitCode.KILLED})`); this.status = InstanceStatus.KILLING; return this.exit(RunnerExitCode.KILLED); } - this.logger.trace("Exiting (expected)"); + this.logger.info("Exiting (expected)"); this.status = InstanceStatus.STOPPING; return this.exit(RunnerExitCode.STOPPED); } - async addStopHandlerRequest(data: StopSequenceMessageData): Promise { + async handleStopRequest(data: StopSequenceMessageData): Promise { this.keepAliveRequested = false; let sequenceError; @@ -764,7 +772,7 @@ export class Runner implements IComponent { res(); } else if (this.instanceOutput && this.hostClient.outputStream) { - this.logger.trace("Piping Sequence output", typeof this.instanceOutput); + this.logger.info("Piping Sequence output", typeof this.instanceOutput); this.shouldSerialize = this.instanceOutput.contentType && ["application/x-ndjson", "text/x-ndjson"].includes(this.instanceOutput.contentType) || @@ -787,7 +795,7 @@ export class Runner implements IComponent { rej(new RunnerError("SEQUENCE_RUNTIME_ERROR", e)); }) .once("end", () => { - this.logger.debug("Sequence stream ended"); + this.logger.info("Sequence stream ended"); res(); }) .pipe(this.shouldSerialize @@ -809,7 +817,7 @@ export class Runner implements IComponent { ); } else { // TODO: this should push a PANG message with the sequence description - this.logger.debug("Sequence did not output a stream"); + this.logger.info("Sequence did not output a stream"); res(); } }); diff --git a/packages/types/src/api-client/manager-client.ts b/packages/types/src/api-client/manager-client.ts index 638aa2c23..014bf3b62 100644 --- a/packages/types/src/api-client/manager-client.ts +++ b/packages/types/src/api-client/manager-client.ts @@ -12,7 +12,7 @@ export declare class ManagerClient { constructor(apiBase: string, utils: ClientUtils | undefined); - getHostClient(id: string, hostApiBase: string): import("./host-client").HostClient; + getHostClient(id: string, hostApiBase?: string): import("./host-client").HostClient; getHosts(): Promise; getVersion(): Promise; sendNamedData(topic: string, stream: Parameters[1], requestInit?: RequestInit, contentType?: string, end?: boolean): Promise; diff --git a/packages/types/src/messages/handshake-acknowledge.ts b/packages/types/src/messages/handshake-acknowledge.ts index 3b724b49f..d9c31f501 100644 --- a/packages/types/src/messages/handshake-acknowledge.ts +++ b/packages/types/src/messages/handshake-acknowledge.ts @@ -1,11 +1,13 @@ import { RunnerMessageCode } from "@scramjet/symbols"; import { AppConfig } from "../app-config"; +import { LogLevel } from "../object-logger"; export type HandshakeAcknowledgeMessageData = { /** Sequence configuration passed to the Sequence when it is started by the Runner. */ appConfig: AppConfig; - args?: any[] + args?: any[], + logLevel?: LogLevel; } /** diff --git a/packages/types/src/object-logger.ts b/packages/types/src/object-logger.ts index 7bfdef0ee..e9bb8e236 100644 --- a/packages/types/src/object-logger.ts +++ b/packages/types/src/object-logger.ts @@ -51,6 +51,8 @@ export interface IObjectLogger { outputLogStream: PassThrough; output: DataStream; + logLevel: LogLevel; + addOutput(output: Writable): void; write(level: LogEntry["level"], entry: LogEntry | string, ...optionalParams: any[]): void; From 2f1efcbf4927169af6217439383e7a5f143f5199 Mon Sep 17 00:00:00 2001 From: Budleigh Salterton Date: Tue, 19 Mar 2024 15:23:55 +0000 Subject: [PATCH 2/5] Add log level change to runners and CSI --- packages/host/src/lib/cpm-connector.ts | 6 +- packages/host/src/lib/csi-controller.ts | 14 ++++- packages/host/src/lib/host.ts | 7 ++- packages/model/src/stream-handler.ts | 2 + .../python-runner/hardcoded_magic_values.py | 1 + packages/python-runner/runner.py | 24 ++++--- packages/runner/src/runner-app-context.ts | 7 ++- packages/runner/src/runner.ts | 12 +++- packages/symbols/src/runner-message-code.ts | 2 + packages/types/src/dto/index.ts | 1 + packages/types/src/dto/set-instance.ts | 6 ++ packages/types/src/dto/start-sequence.ts | 3 + packages/types/src/message-streams.ts | 4 +- packages/types/src/messages/index.ts | 1 + packages/types/src/messages/set.ts | 13 ++++ packages/types/src/runner-connect.ts | 2 + packages/types/src/runner-update.ts | 9 +++ .../src/typeguards/dto/instance-set.ts | 62 +++++++++++++++++++ .../src/typeguards/dto/sequence-start.ts | 12 +++- packages/utility/src/typeguards/index.ts | 3 +- 20 files changed, 169 insertions(+), 22 deletions(-) create mode 100644 packages/types/src/dto/set-instance.ts create mode 100644 packages/types/src/messages/set.ts create mode 100644 packages/types/src/runner-update.ts create mode 100644 packages/utility/src/typeguards/dto/instance-set.ts diff --git a/packages/host/src/lib/cpm-connector.ts b/packages/host/src/lib/cpm-connector.ts index 3b94dafac..14f820834 100644 --- a/packages/host/src/lib/cpm-connector.ts +++ b/packages/host/src/lib/cpm-connector.ts @@ -24,7 +24,7 @@ import { ObjLogger } from "@scramjet/obj-logger"; import { ReasonPhrases } from "http-status-codes"; import { DuplexStream } from "@scramjet/api-server"; import { VerserClientConnection } from "@scramjet/verser/src/types"; -import { EOL, networkInterfaces } from "os"; +import { networkInterfaces } from "os"; type STHInformation = { id?: string; @@ -253,13 +253,13 @@ export class CPMConnector extends TypedEmitter { }; } - this.logger.info(`${EOL}${EOL}\t\x1b[33m${this.config.id} connected to ${this.cpmId}\x1b[0m${EOL} `); + this.logger.info(`Hub ${this.config.id} connected to ${this.cpmId}`); StringStream.from(duplex.input as Readable) .JSONParse() .map(async (message: EncodedControlMessage) => { this.logger.trace("Received message", message); - const messageCode = message[0] as CPMMessageCode; + const messageCode = message[0] as unknown as CPMMessageCode; if (messageCode === CPMMessageCode.STH_ID) { // eslint-disable-next-line no-extra-parens diff --git a/packages/host/src/lib/csi-controller.ts b/packages/host/src/lib/csi-controller.ts index 72e400d79..f741a4981 100644 --- a/packages/host/src/lib/csi-controller.ts +++ b/packages/host/src/lib/csi-controller.ts @@ -43,7 +43,7 @@ import { DataStream } from "scramjet"; import { getInstanceAdapter } from "@scramjet/adapters"; import { ObjLogger } from "@scramjet/obj-logger"; import { RunnerConnectInfo } from "@scramjet/types/src/runner-connect"; -import { cancellableDefer, CancellablePromise, defer, promiseTimeout, TypedEmitter } from "@scramjet/utility"; +import { cancellableDefer, CancellablePromise, defer, isSetSequenceEndpointPayloadDTO, promiseTimeout, TypedEmitter } from "@scramjet/utility"; import { ReasonPhrases } from "http-status-codes"; import { mapRunnerExitCode } from "./utils"; @@ -734,6 +734,18 @@ export class CSIController extends TypedEmitter { this.router.op("post", "/_stop", (req) => this.handleStop(req), this.communicationHandler); this.router.op("post", "/_kill", (req) => this.handleKill(req), this.communicationHandler); + + this.router.op("post", "/set", async (req) => { + const { body } = req; + + if (isSetSequenceEndpointPayloadDTO(body)) { + this.logger.debug("Setting instance", body); + + this.communicationHandler.sendControlMessage(RunnerMessageCode.SET, body); + } + + return { opStatus: ReasonPhrases.OK }; + }); } private async handleEvent(event: ParsedMessage): Promise> { diff --git a/packages/host/src/lib/host.ts b/packages/host/src/lib/host.ts index b58b67a5d..5d7da0a22 100644 --- a/packages/host/src/lib/host.ts +++ b/packages/host/src/lib/host.ts @@ -592,7 +592,8 @@ export class Host implements IComponent { await this.csiDispatcher.startRunner(sequence, { appConfig: seqenceConfig.appConfig || {}, args: seqenceConfig.args, - instanceId: seqenceConfig.instanceId + instanceId: seqenceConfig.instanceId, + logLevel: this.logger.logLevel }); this.logger.debug("Starting sequence based on config", seqenceConfig); @@ -617,6 +618,8 @@ export class Host implements IComponent { // @TODO this causes problem with axios. this.s3Client?.setAgent(connector.getHttpAgent()); + + this.auditor }); await connector.connect(); @@ -1305,7 +1308,7 @@ export class Host implements IComponent { await new Promise((res, _rej) => { this.socketServer.server ?.once("close", () => { - this.logger.trace("Socket server stopped."); + this.logger.info("Socket server stopped."); res(); }) diff --git a/packages/model/src/stream-handler.ts b/packages/model/src/stream-handler.ts index e4a30d2c5..a5940eb6b 100644 --- a/packages/model/src/stream-handler.ts +++ b/packages/model/src/stream-handler.ts @@ -53,6 +53,7 @@ type ControlMessageHandlerList = { [RunnerMessageCode.MONITORING_REPLY]: ConfiguredMessageHandler[]; [RunnerMessageCode.STOP]: ConfiguredMessageHandler[]; [RunnerMessageCode.PONG]: ConfiguredMessageHandler[]; + [RunnerMessageCode.SET]: ConfiguredMessageHandler[]; [RunnerMessageCode.INPUT_CONTENT_TYPE]: ConfiguredMessageHandler[]; [RunnerMessageCode.EVENT]: ConfiguredMessageHandler[]; [CPMMessageCode.STH_ID]: ConfiguredMessageHandler[]; @@ -92,6 +93,7 @@ export class CommunicationHandler implements ICommunicationHandler { [RunnerMessageCode.STOP]: [], [RunnerMessageCode.EVENT]: [], [RunnerMessageCode.PONG]: [], + [RunnerMessageCode.SET]: [], [RunnerMessageCode.INPUT_CONTENT_TYPE]: [], [CPMMessageCode.STH_ID]: [], [CPMMessageCode.KEY_REVOKED]: [], diff --git a/packages/python-runner/hardcoded_magic_values.py b/packages/python-runner/hardcoded_magic_values.py index 25e42c7a1..f03741c18 100644 --- a/packages/python-runner/hardcoded_magic_values.py +++ b/packages/python-runner/hardcoded_magic_values.py @@ -31,5 +31,6 @@ class RunnerMessageCodes(Enum): KILL = 4002 MONITORING_RATE = 4003 MONITORING_REPLY = 4004 + SET = 4005 EVENT = 5001 diff --git a/packages/python-runner/runner.py b/packages/python-runner/runner.py index 2780b2225..867b1d27b 100644 --- a/packages/python-runner/runner.py +++ b/packages/python-runner/runner.py @@ -59,13 +59,13 @@ async def main(self, server_host, server_port): self.connect_stdio() self.connect_log_stream() - config, args = await self.handshake() + config, args, log_level = await self.handshake() self.logger.info('Communication established.') asyncio.create_task(self.connect_control_stream()) asyncio.create_task(self.setup_heartbeat()) self.load_sequence() - await self.run_instance(config, args) + await self.run_instance(config, args, log_level) async def init_connections(self, host, port): @@ -130,6 +130,8 @@ async def handshake(self): data['appConfig'] = {} if 'args' not in data: data['args'] = [] + if 'logLevel' not in data: + data['logLevel'] = 'DEBUG' self.logger.info(f'Sending PANG') pang_requires_data = { @@ -140,8 +142,7 @@ async def handshake(self): if code == msg_codes.PONG.value: self.logger.info(f'Got configuration: {data}') - return data['appConfig'], data['args'] - + return data['appConfig'], data['args'], data['logLevel'] async def connect_control_stream(self): # Control stream carries ndjson, so it's enough to split into lines. @@ -153,6 +154,8 @@ async def connect_control_stream(self): ) async for code, data in control_messages: self.logger.debug(f'Control message received: {code} {data}') + if code == msg_codes.SET.value: + self.handle_set(data) if code == msg_codes.KILL.value: self.exit_immediately() if code == msg_codes.STOP.value: @@ -161,6 +164,11 @@ async def connect_control_stream(self): self.emitter.emit(data['eventName'], data['message'] if 'message' in data else None) + async def handle_set(self, data): + self.logger.info(f'Setting logLevel: {data}') + if 'logLevel' in data: + self.logger.setLevel(data['logLevel']) + async def handle_stop(self, data): self.logger.info(f'Gracefully shutting down...{data}') self.keep_alive_requested = False @@ -203,12 +211,14 @@ def load_sequence(self): # switch to sequence dir so that relative paths will work os.chdir(os.path.dirname(self.seq_path)) - async def run_instance(self, config, args): + async def run_instance(self, config, args, log_level): context = AppContext(self, config) input_stream = Stream() + asyncio.create_task(self.connect_input_stream(input_stream)) self.logger.info('Running instance...') + self.logger.setLevel(log_level) result = self.sequence.run(context, input_stream, *args) self.logger.info(f'Sending PANG') @@ -223,7 +233,7 @@ async def run_instance(self, config, args): produces = {} produces['provides'] = produces_runtime produces['contentType'] = getattr(result, 'content_type', None) - produces_json = json.dumps(produces) + produces_json = json.dumps(produces) if produces: self.logger.info(f'Sending PANG with {produces}') @@ -238,7 +248,7 @@ async def run_instance(self, config, args): consumes = {} consumes['requires'] = consumes_runtime consumes['contentType'] = getattr(result, 'content_type', None) - consumes_json = json.dumps(consumes) + consumes_json = json.dumps(consumes) if consumes: self.logger.info(f'Sending PANG with {consumes}') diff --git a/packages/runner/src/runner-app-context.ts b/packages/runner/src/runner-app-context.ts index 848f828ac..67d884af9 100644 --- a/packages/runner/src/runner-app-context.ts +++ b/packages/runner/src/runner-app-context.ts @@ -3,7 +3,7 @@ import { ObjLogger } from "@scramjet/obj-logger"; import { EventMessageData, KeepAliveMessageData, MonitoringMessageFromRunnerData, AppConfig, AppError, AppErrorConstructor, AppContext, WritableStream, - FunctionDefinition, KillHandler, StopHandler, MonitoringHandler, IObjectLogger, HostClient, ManagerClient + FunctionDefinition, KillHandler, StopHandler, MonitoringHandler, IObjectLogger, HostClient, ManagerClient, LogLevel } from "@scramjet/types"; import { EventEmitter } from "events"; @@ -31,13 +31,13 @@ implements AppContext { emitter: EventEmitter; initialState?: State; exitTimeout: number = 10000; - logger: IObjectLogger = new ObjLogger("Sequence"); + logger: IObjectLogger; hub: HostClient; space: ManagerClient; instanceId: string; constructor(config: AppConfigType, monitorStream: WritableStream, - emitter: EventEmitter, runner: RunnerProxy, hostClient: HostClient, spaceClient: ManagerClient, id: string) { + emitter: EventEmitter, runner: RunnerProxy, hostClient: HostClient, spaceClient: ManagerClient, id: string, logLevel: LogLevel) { this.config = config; this.monitorStream = monitorStream; this.emitter = emitter; @@ -45,6 +45,7 @@ implements AppContext { this.hub = hostClient; this.space = spaceClient; this.instanceId = id; + this.logger = new ObjLogger("Sequence", {}, logLevel); } private handleSave(_state: any): void { diff --git a/packages/runner/src/runner.ts b/packages/runner/src/runner.ts index c1653d4fb..2674f7f03 100644 --- a/packages/runner/src/runner.ts +++ b/packages/runner/src/runner.ts @@ -36,6 +36,7 @@ import { Readable, Writable } from "stream"; import { RunnerAppContext, RunnerProxy } from "./runner-app-context"; import { mapToInputDataStream, readInputStreamHeaders, inputStreamInitLogger } from "./input-stream"; import { MessageUtils } from "./message-utils"; +import { SetMessageData } from "@scramjet/types/src/messages/set"; let exitHandled = false; @@ -178,7 +179,7 @@ export class Runner implements IComponent { this.runnerConnectInfo = runnerConnectInfo; - this.logger = new ObjLogger(this, { id: instanceId }); + this.logger = new ObjLogger(this, { id: instanceId }, runnerConnectInfo.logLevel || "DEBUG"); hostClient.logger.pipe(this.logger); inputStreamInitLogger.pipe(this.logger); @@ -250,9 +251,15 @@ export class Runner implements IComponent { private handlePongRequest(data: HandshakeAcknowledgeMessageData) { this.handshakeResolver?.res(data); + this.handleSetRequest(data); + } + private handleSetRequest(data: SetMessageData) { if (data.logLevel) { this.logger.logLevel = data.logLevel; + + if (this._context) + this._context.logger.logLevel = data.logLevel; } } @@ -618,7 +625,8 @@ export class Runner implements IComponent { runner, hostApiClient, managerApiClient, - this.instanceId + this.instanceId, + this.logger.logLevel ); this._context.logger.pipe(this.logger); diff --git a/packages/symbols/src/runner-message-code.ts b/packages/symbols/src/runner-message-code.ts index 9c96dff62..20ed21d9e 100644 --- a/packages/symbols/src/runner-message-code.ts +++ b/packages/symbols/src/runner-message-code.ts @@ -16,5 +16,7 @@ export enum RunnerMessageCode { KILL = 4002, MONITORING_RATE = 4003, MONITORING_REPLY = 4004, + SET = 4005, + EVENT = 5001, } diff --git a/packages/types/src/dto/index.ts b/packages/types/src/dto/index.ts index 086f54988..787c8d10c 100644 --- a/packages/types/src/dto/index.ts +++ b/packages/types/src/dto/index.ts @@ -1 +1,2 @@ export { StartSequenceDTO, StartSequenceEndpointPayloadDTO } from "./start-sequence"; +export { SetSequenceEndpointPayloadDTO } from "./set-instance"; \ No newline at end of file diff --git a/packages/types/src/dto/set-instance.ts b/packages/types/src/dto/set-instance.ts new file mode 100644 index 000000000..3dd9daa6b --- /dev/null +++ b/packages/types/src/dto/set-instance.ts @@ -0,0 +1,6 @@ +import { LogLevel } from "../object-logger"; + + +export type SetSequenceEndpointPayloadDTO = { + logLevel?: LogLevel; +}; diff --git a/packages/types/src/dto/start-sequence.ts b/packages/types/src/dto/start-sequence.ts index 0ecb367a9..412518eb2 100644 --- a/packages/types/src/dto/start-sequence.ts +++ b/packages/types/src/dto/start-sequence.ts @@ -1,14 +1,17 @@ import { AppConfig } from "../app-config"; +import { LogLevel } from "../object-logger"; export type StartSequenceDTO = { id: string, appConfig?: AppConfig, args?: string[], instanceId?: string; + logLevel?: LogLevel; } export type StartSequenceEndpointPayloadDTO = { appConfig?: AppConfig, instanceId?: string; args?: string[], + logLevel?: LogLevel; } diff --git a/packages/types/src/message-streams.ts b/packages/types/src/message-streams.ts index 96a157a68..94f05515b 100644 --- a/packages/types/src/message-streams.ts +++ b/packages/types/src/message-streams.ts @@ -44,6 +44,7 @@ import { NetworkInfo } from "./network-info"; import { SequenceCompleteMessageData } from "./messages/sequence-complete"; import { KillMessageData } from "./messages/kill-sequence"; import { MonitoringReplyMessage, MonitoringReplyMessageData } from "./messages/monitor-reply"; +import { SetMessageData } from "./messages/set"; export type MessageType = T extends RunnerMessageCode.ACKNOWLEDGE ? AcknowledgeMessage : @@ -77,6 +78,7 @@ export type MessageDataType = T extends RunnerMessageCode.STOP ? StopSequenceMessageData : T extends RunnerMessageCode.PING ? PingMessageData : T extends RunnerMessageCode.PONG ? HandshakeAcknowledgeMessageData : + T extends RunnerMessageCode.SET ? SetMessageData : T extends RunnerMessageCode.PANG ? PangMessageData : T extends RunnerMessageCode.SEQUENCE_COMPLETED ? SequenceCompleteMessageData : T extends RunnerMessageCode.SEQUENCE_STOPPED ? SequenceStoppedMessageData : @@ -97,7 +99,7 @@ export type EncodedMessage< export type ControlMessageCode = RunnerMessageCode.KILL | RunnerMessageCode.MONITORING_RATE | RunnerMessageCode.MONITORING_REPLY | RunnerMessageCode.STOP | RunnerMessageCode.EVENT | - RunnerMessageCode.PONG | + RunnerMessageCode.PONG | RunnerMessageCode.SET CPMMessageCode.STH_ID | CPMMessageCode.KEY_REVOKED | CPMMessageCode.LIMIT_EXCEEDED | CPMMessageCode.ID_DROP | RunnerMessageCode.INPUT_CONTENT_TYPE; diff --git a/packages/types/src/messages/index.ts b/packages/types/src/messages/index.ts index 3540a0fd7..f4eef2929 100644 --- a/packages/types/src/messages/index.ts +++ b/packages/types/src/messages/index.ts @@ -5,6 +5,7 @@ export { ErrorMessage, ErrorMessageData } from "./error"; export { EventMessage, EventMessageData } from "./event"; export { PangMessageData, PingMessageData, HandshakeMessage } from "./handshake"; export { HandshakeAcknowledgeMessage, HandshakeAcknowledgeMessageData } from "./handshake-acknowledge"; +export { SetMessage, SetMessageData } from "./set"; export { KeepAliveMessage, KeepAliveMessageData } from "./keep-alive"; export { KillSequenceMessage, KillMessageData } from "./kill-sequence"; export { EmptyMessageData, Message } from "./message"; diff --git a/packages/types/src/messages/set.ts b/packages/types/src/messages/set.ts new file mode 100644 index 000000000..7e3f1d431 --- /dev/null +++ b/packages/types/src/messages/set.ts @@ -0,0 +1,13 @@ +import { RunnerMessageCode } from "@scramjet/symbols"; +import { LogLevel } from "../object-logger"; + +export type SetMessageData = { + logLevel?: LogLevel; +} + +/** + * Cloud Server Host (CSH) sends handshake acknowledge message (PONG) to the Runner in response to + * the received handshake message (PING). + * The message includes the Sequence configuration information. + */ +export type SetMessage = { msgCode: RunnerMessageCode.PONG } & SetMessageData; diff --git a/packages/types/src/runner-connect.ts b/packages/types/src/runner-connect.ts index 6b101e292..0f06cc54f 100644 --- a/packages/types/src/runner-connect.ts +++ b/packages/types/src/runner-connect.ts @@ -1,5 +1,6 @@ import { AppConfig } from "./app-config"; import { InstanceLimits } from "./instance-limits"; +import { LogLevel } from "./object-logger"; export type RunnerConnectInfo = { appConfig: AppConfig; @@ -9,4 +10,5 @@ export type RunnerConnectInfo = { limits?: InstanceLimits; instanceId?: string; system?: Record; + logLevel?: LogLevel; } diff --git a/packages/types/src/runner-update.ts b/packages/types/src/runner-update.ts new file mode 100644 index 000000000..1a9f41dd1 --- /dev/null +++ b/packages/types/src/runner-update.ts @@ -0,0 +1,9 @@ +import { AppConfig } from "./app-config"; +import { LogLevel } from "./object-logger"; + +export type RunnerUpdateInfo = Partial<{ + appConfig: AppConfig; + outputTopic: string; + inputTopic: string; + logLevel: LogLevel; +}>; diff --git a/packages/utility/src/typeguards/dto/instance-set.ts b/packages/utility/src/typeguards/dto/instance-set.ts new file mode 100644 index 000000000..801a491e3 --- /dev/null +++ b/packages/utility/src/typeguards/dto/instance-set.ts @@ -0,0 +1,62 @@ +import { StartSequenceDTO, StartSequenceEndpointPayloadDTO, SetSequenceEndpointPayloadDTO } from "@scramjet/types"; +import { LogLevelStrings } from "../../constants"; + +// eslint-disable-next-line complexity +export function isStartSequenceDTO(arg: any): arg is StartSequenceDTO { + if (typeof arg !== "object") throw new Error("DTO is not an object"); + const { id, appConfig, args, instanceId, logLevel, ...rest } = arg; + + if (typeof id !== "string") throw new Error("DTO id is not string"); + if (!["object", "undefined"].includes(typeof appConfig)) + throw new Error(`DTO appConfig is ${typeof appConfig}, not an object`); + if (instanceId && typeof instanceId !== "string") { + throw new Error("DTO instanceId is not valid string"); + } + if (typeof args !== "undefined") { + if (!Array.isArray(args)) throw new Error("DTO args are not an array"); + if ((args as string[]).some((x) => typeof x !== "string")) throw new Error("DTO args are all strings"); + } + if (instanceId !== undefined && typeof instanceId === "string" && instanceId.length !== 36) + throw new Error("DTO instanceId is not 36 long"); + if (logLevel && !LogLevelStrings.includes(logLevel)) { + throw new Error("DTO logLevel is not valid"); + } + + if (Object.keys(rest).length > 0) throw new Error(`DTO has unknown ${Object.keys(rest)} keys`); + + return true; +} + +export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenceEndpointPayloadDTO { + if (typeof arg !== "object") { + throw new Error("DTO is not an object"); + } + const { appConfig, instanceId, logLevel } = arg; + + if (!["object", "undefined"].includes(typeof appConfig)) + throw new Error(`DTO appConfig is ${typeof appConfig}, not an object`); + if (instanceId !== undefined && typeof instanceId === "string" && instanceId.length !== 36) + throw new Error("DTO instanceId is not 36 long"); + if (instanceId && typeof instanceId !== "string") { + throw new Error("DTO instanceId is not valid string"); + } + if (logLevel && !LogLevelStrings.includes(logLevel)) { + throw new Error("DTO logLevel is not valid"); + } + return true; +} + +export function isSetSequenceEndpointPayloadDTO(arg: any): arg is SetSequenceEndpointPayloadDTO { + if (typeof arg !== "object") { + throw new Error("DTO is not an object"); + } + const { logLevel, ...rest } = arg; + + if (logLevel && !LogLevelStrings.includes(logLevel)) { + throw new Error("DTO logLevel is not valid"); + } + if (Object.values(rest).length > 0) + throw new Error(`DTO has unknown ${Object.keys(rest)} keys`); + + return true; +} diff --git a/packages/utility/src/typeguards/dto/sequence-start.ts b/packages/utility/src/typeguards/dto/sequence-start.ts index f76d64c7e..d983a76a5 100644 --- a/packages/utility/src/typeguards/dto/sequence-start.ts +++ b/packages/utility/src/typeguards/dto/sequence-start.ts @@ -1,9 +1,10 @@ import { StartSequenceDTO, StartSequenceEndpointPayloadDTO } from "@scramjet/types"; +import { LogLevelStrings } from "../../constants"; // eslint-disable-next-line complexity export function isStartSequenceDTO(arg: any): arg is StartSequenceDTO { if (typeof arg !== "object") throw new Error("DTO is not an object"); - const { id, appConfig, args, instanceId, ...rest } = arg; + const { id, appConfig, args, instanceId, logLevel, ...rest } = arg; if (typeof id !== "string") throw new Error("DTO id is not string"); if (!["object", "undefined"].includes(typeof appConfig)) @@ -17,6 +18,10 @@ export function isStartSequenceDTO(arg: any): arg is StartSequenceDTO { } if (instanceId !== undefined && typeof instanceId === "string" && instanceId.length !== 36) throw new Error("DTO instanceId is not 36 long"); + if (logLevel && !LogLevelStrings.includes(logLevel)) { + throw new Error("DTO logLevel is not valid"); + } + if (Object.keys(rest).length > 0) throw new Error(`DTO has unknown ${Object.keys(rest)} keys`); return true; @@ -26,7 +31,7 @@ export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenc if (typeof arg !== "object") { throw new Error("DTO is not an object"); } - const { appConfig, instanceId } = arg; + const { appConfig, instanceId, logLevel } = arg; if (!["object", "undefined"].includes(typeof appConfig)) throw new Error(`DTO appConfig is ${typeof appConfig}, not an object`); @@ -35,5 +40,8 @@ export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenc if (instanceId && typeof instanceId !== "string") { throw new Error("DTO instanceId is not valid string"); } + if (logLevel && !LogLevelStrings.includes(logLevel)) { + throw new Error("DTO logLevel is not valid"); + } return true; } diff --git a/packages/utility/src/typeguards/index.ts b/packages/utility/src/typeguards/index.ts index 4f4b74f5d..b4f85a62f 100644 --- a/packages/utility/src/typeguards/index.ts +++ b/packages/utility/src/typeguards/index.ts @@ -1,4 +1,5 @@ -export * from "./dto/sequence-start"; +export { isStartSequenceDTO, isStartSequenceEndpointPayloadDTO } from "./dto/sequence-start"; +export { isSetSequenceEndpointPayloadDTO } from "./dto/instance-set"; export { isDefined } from "./is-defined"; export { isBoolean } from "./is-boolean"; export { isEmptyString } from "./is-empty-string"; From df15ca96758b3c1b7cd8a69aeeaaff51e81239e0 Mon Sep 17 00:00:00 2001 From: Budleigh Salterton Date: Wed, 20 Mar 2024 09:43:56 +0000 Subject: [PATCH 3/5] Fix eslint errors --- packages/host/src/lib/csi-controller.ts | 2 +- packages/host/src/lib/host.ts | 2 - packages/obj-logger/src/obj-logger.ts | 10 +++- packages/types/src/dto/index.ts | 2 +- packages/types/src/dto/set-instance.ts | 1 - packages/types/src/message-streams.ts | 2 +- yarn.lock | 74 ------------------------- 7 files changed, 12 insertions(+), 81 deletions(-) diff --git a/packages/host/src/lib/csi-controller.ts b/packages/host/src/lib/csi-controller.ts index f741a4981..b0c58b26f 100644 --- a/packages/host/src/lib/csi-controller.ts +++ b/packages/host/src/lib/csi-controller.ts @@ -741,7 +741,7 @@ export class CSIController extends TypedEmitter { if (isSetSequenceEndpointPayloadDTO(body)) { this.logger.debug("Setting instance", body); - this.communicationHandler.sendControlMessage(RunnerMessageCode.SET, body); + await this.communicationHandler.sendControlMessage(RunnerMessageCode.SET, body); } return { opStatus: ReasonPhrases.OK }; diff --git a/packages/host/src/lib/host.ts b/packages/host/src/lib/host.ts index 5d7da0a22..d356969de 100644 --- a/packages/host/src/lib/host.ts +++ b/packages/host/src/lib/host.ts @@ -618,8 +618,6 @@ export class Host implements IComponent { // @TODO this causes problem with axios. this.s3Client?.setAgent(connector.getHttpAgent()); - - this.auditor }); await connector.connect(); diff --git a/packages/obj-logger/src/obj-logger.ts b/packages/obj-logger/src/obj-logger.ts index 365d4c616..0904a8018 100644 --- a/packages/obj-logger/src/obj-logger.ts +++ b/packages/obj-logger/src/obj-logger.ts @@ -81,20 +81,28 @@ export class ObjLogger implements IObjectLogger { this.debug = noop; this.fatal = noop; this.warn = noop; - + switch (value) { case "TRACE": this.trace = ObjLogger.prototype.trace; + // eslint-disable-next-line no-fallthrough case "DEBUG": this.debug = ObjLogger.prototype.debug; + // eslint-disable-next-line no-fallthrough case "INFO": this.info = ObjLogger.prototype.info; + // eslint-disable-next-line no-fallthrough case "WARN": this.warn = ObjLogger.prototype.warn; + // eslint-disable-next-line no-fallthrough case "ERROR": this.error = ObjLogger.prototype.error; + // eslint-disable-next-line no-fallthrough case "FATAL": this.fatal = ObjLogger.prototype.fatal; + // eslint-disable-next-line no-fallthrough + default: + break; } } diff --git a/packages/types/src/dto/index.ts b/packages/types/src/dto/index.ts index 787c8d10c..1cc57fc47 100644 --- a/packages/types/src/dto/index.ts +++ b/packages/types/src/dto/index.ts @@ -1,2 +1,2 @@ export { StartSequenceDTO, StartSequenceEndpointPayloadDTO } from "./start-sequence"; -export { SetSequenceEndpointPayloadDTO } from "./set-instance"; \ No newline at end of file +export { SetSequenceEndpointPayloadDTO } from "./set-instance"; diff --git a/packages/types/src/dto/set-instance.ts b/packages/types/src/dto/set-instance.ts index 3dd9daa6b..dfb29570a 100644 --- a/packages/types/src/dto/set-instance.ts +++ b/packages/types/src/dto/set-instance.ts @@ -1,6 +1,5 @@ import { LogLevel } from "../object-logger"; - export type SetSequenceEndpointPayloadDTO = { logLevel?: LogLevel; }; diff --git a/packages/types/src/message-streams.ts b/packages/types/src/message-streams.ts index 94f05515b..7345741cb 100644 --- a/packages/types/src/message-streams.ts +++ b/packages/types/src/message-streams.ts @@ -99,7 +99,7 @@ export type EncodedMessage< export type ControlMessageCode = RunnerMessageCode.KILL | RunnerMessageCode.MONITORING_RATE | RunnerMessageCode.MONITORING_REPLY | RunnerMessageCode.STOP | RunnerMessageCode.EVENT | - RunnerMessageCode.PONG | RunnerMessageCode.SET + RunnerMessageCode.PONG | RunnerMessageCode.SET | CPMMessageCode.STH_ID | CPMMessageCode.KEY_REVOKED | CPMMessageCode.LIMIT_EXCEEDED | CPMMessageCode.ID_DROP | RunnerMessageCode.INPUT_CONTENT_TYPE; diff --git a/yarn.lock b/yarn.lock index 19c360d21..f6b2f2847 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1291,80 +1291,6 @@ resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz" integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== -"@scramjet/api-client@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/api-client/-/api-client-0.38.0.tgz#0c93d6ebe9c522dc67d073dfe6794bcdb0e6fbba" - integrity sha512-YxUHtQDPPIlmRoRsFEDviKQehSTl0Gb3l8drzUcZ8vpAZzijKqab7DTgDHwf8P1sW6AKjhUKMF0Di/Ve2J14iQ== - dependencies: - "@scramjet/client-utils" "^0.38.0" - "@scramjet/sth-config" "^0.38.0" - "@scramjet/symbols" "^0.38.0" - n-readlines "^1.0.1" - scramjet "^4.36.9" - -"@scramjet/client-utils@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/client-utils/-/client-utils-0.38.0.tgz#dfebd035617aaa192cea79a9ca93844cab143e85" - integrity sha512-DzxwgcSCEtIxdG+GsIReL1Zhkh9zKnPDIq3zbVt9Svvsq/UuP94KGg25KVelvr0OTM/yEEovJw9/yOMDWLiXbQ== - dependencies: - "@scramjet/model" "^0.38.0" - "@scramjet/obj-logger" "^0.38.0" - "@scramjet/sth-config" "^0.38.0" - "@scramjet/symbols" "^0.38.0" - "@scramjet/utility" "^0.38.0" - "@types/node-fetch" "^2.6.4" - abort-controller "^3.0.0" - n-readlines "^1.0.1" - node-fetch "^2.6.7" - normalize-url "4" - scramjet "^4.36.9" - -"@scramjet/model@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/model/-/model-0.38.0.tgz#c5bc04d346dbeba6b90ac7ec182c39877477c25d" - integrity sha512-KaIqZi6tbNnBZcc7TmvJhki+oO3k+EKUuH7h044LGatVcS5tbMrIki3w5BX41OCi5neigDCoOla/nJraod6IcQ== - dependencies: - "@scramjet/obj-logger" "^0.38.0" - "@scramjet/symbols" "^0.38.0" - scramjet "^4.36.9" - uuid "^8.3.2" - -"@scramjet/obj-logger@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/obj-logger/-/obj-logger-0.38.0.tgz#681c1aa13505dbcd0ce2bcd7141a6872e80c2367" - integrity sha512-2RLYiGnVbt1rGN74yvhqocz3PDxjYdO2Rb0GKlxYZJ2JQB/hIVAJSE47wUjKmPkG39anH6UrfGV8T73paH9qgg== - dependencies: - "@scramjet/utility" "^0.38.0" - scramjet "^4.36.9" - -"@scramjet/sth-config@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/sth-config/-/sth-config-0.38.0.tgz#b3523823b2550ba19e7d61daeda6f600e2f1601c" - integrity sha512-Glm/lXMK3UsdAwnWnINlxGm7UFaJfGCnDgjwtI8DVHOL3+52SujFbO0fNb/ye0htR77vNg6GTydbK8sEFdTbkw== - dependencies: - "@scramjet/utility" "^0.38.0" - -"@scramjet/symbols@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/symbols/-/symbols-0.38.0.tgz#0ae5f48085eff32dab8c3ed621e3e6560949bc67" - integrity sha512-Wjg0JUFybp++ngDUovkoBb3IrfVAjo3OeK6d7JodCOVlgrPsOs2jvmINhGhTfbB/WZx0/sRHeG6Yr9zmpDY3Cg== - -"@scramjet/types@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/types/-/types-0.38.0.tgz#2543bcb15c47b6e91f1d87d835c40398b30a5203" - integrity sha512-6PlWPgdP5ot65Zr17d01rf9m6rgL9xgsliFw2yhikEPflLV8c2ohSGSsptR+faM+x+pNyN/O9TnxbSzwwWBNVA== - dependencies: - "@scramjet/symbols" "^0.38.0" - http-status-codes "^2.2.0" - -"@scramjet/utility@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@scramjet/utility/-/utility-0.38.0.tgz#336876075396b6959dbb8c4730889718b3a8d334" - integrity sha512-jSxeqm1BJ/ZczZAlcXP8tiU4k0cRTF4oVFsrczSw07sxliHbKSh7FaYsRfDKrO53xOlyD5FGLER/3IJckFlPpQ== - dependencies: - normalize-url "4" - yaml "^2.2.2" - "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" From d3b0aa4a5d1fe5ed1ae52c028c935f50a488bf95 Mon Sep 17 00:00:00 2001 From: Budleigh Salterton Date: Wed, 20 Mar 2024 23:53:25 +0000 Subject: [PATCH 4/5] Fix reconnect logging and memleak --- packages/runner/src/runner.ts | 2 +- packages/utility/src/typeguards/dto/instance-set.ts | 7 ++++--- packages/utility/src/typeguards/dto/sequence-start.ts | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/runner/src/runner.ts b/packages/runner/src/runner.ts index 2674f7f03..3217fe5fd 100644 --- a/packages/runner/src/runner.ts +++ b/packages/runner/src/runner.ts @@ -257,7 +257,7 @@ export class Runner implements IComponent { private handleSetRequest(data: SetMessageData) { if (data.logLevel) { this.logger.logLevel = data.logLevel; - + if (this._context) this._context.logger.logLevel = data.logLevel; } diff --git a/packages/utility/src/typeguards/dto/instance-set.ts b/packages/utility/src/typeguards/dto/instance-set.ts index 801a491e3..4737e28ce 100644 --- a/packages/utility/src/typeguards/dto/instance-set.ts +++ b/packages/utility/src/typeguards/dto/instance-set.ts @@ -27,6 +27,7 @@ export function isStartSequenceDTO(arg: any): arg is StartSequenceDTO { return true; } +// eslint-disable-next-line complexity export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenceEndpointPayloadDTO { if (typeof arg !== "object") { throw new Error("DTO is not an object"); @@ -41,7 +42,7 @@ export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenc throw new Error("DTO instanceId is not valid string"); } if (logLevel && !LogLevelStrings.includes(logLevel)) { - throw new Error("DTO logLevel is not valid"); + throw new Error("DTO logLevel is not valid"); } return true; } @@ -53,9 +54,9 @@ export function isSetSequenceEndpointPayloadDTO(arg: any): arg is SetSequenceEnd const { logLevel, ...rest } = arg; if (logLevel && !LogLevelStrings.includes(logLevel)) { - throw new Error("DTO logLevel is not valid"); + throw new Error("DTO logLevel is not valid"); } - if (Object.values(rest).length > 0) + if (Object.values(rest).length > 0) throw new Error(`DTO has unknown ${Object.keys(rest)} keys`); return true; diff --git a/packages/utility/src/typeguards/dto/sequence-start.ts b/packages/utility/src/typeguards/dto/sequence-start.ts index d983a76a5..4750e6894 100644 --- a/packages/utility/src/typeguards/dto/sequence-start.ts +++ b/packages/utility/src/typeguards/dto/sequence-start.ts @@ -27,6 +27,7 @@ export function isStartSequenceDTO(arg: any): arg is StartSequenceDTO { return true; } +// eslint-disable-next-line complexity export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenceEndpointPayloadDTO { if (typeof arg !== "object") { throw new Error("DTO is not an object"); @@ -41,7 +42,7 @@ export function isStartSequenceEndpointPayloadDTO(arg: any): arg is StartSequenc throw new Error("DTO instanceId is not valid string"); } if (logLevel && !LogLevelStrings.includes(logLevel)) { - throw new Error("DTO logLevel is not valid"); + throw new Error("DTO logLevel is not valid"); } return true; } From 969140dd129e2d28372d05ac70735e7d3a2402cf Mon Sep 17 00:00:00 2001 From: Budleigh Salterton Date: Wed, 20 Mar 2024 23:54:28 +0000 Subject: [PATCH 5/5] Passthrough env to runner in development mode --- packages/adapters/src/process-instance-adapter.ts | 7 ++++++- packages/host/src/lib/host.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/adapters/src/process-instance-adapter.ts b/packages/adapters/src/process-instance-adapter.ts index 9574c8d29..58e4c1dc8 100644 --- a/packages/adapters/src/process-instance-adapter.ts +++ b/packages/adapters/src/process-instance-adapter.ts @@ -20,6 +20,7 @@ import { constants } from "fs"; import { access, readFile, rm } from "fs/promises"; import path from "path"; import { getRunnerEnvVariables } from "./get-runner-env"; +import { development } from "@scramjet/sth-config"; const isTSNode = !!(process as any)[Symbol.for("ts-node.register.instance")]; const gotPython = "\n _ \n __ _____ _ __ ___ ___| |\n \\ \\ /\\ / / _ \\| '_ \\/ __|_ / |\n \\ V V / (_) | | | \\__ \\/ /|_|\n \\_/\\_/ \\___/|_| |_|___/___(_) 🐍\n"; @@ -152,6 +153,9 @@ class ProcessInstanceAdapter implements config.sequenceDir, config.entrypointPath ); + + const extraEnvs = development() ? process.env : {}; + const env = getRunnerEnvVariables({ sequencePath, instancesServerHost: "127.0.0.1", @@ -162,7 +166,8 @@ class ProcessInstanceAdapter implements payload }, { PYTHONPATH: this.getPythonpath(config.sequenceDir), - ...this.sthConfig.runnerEnvs + ...this.sthConfig.runnerEnvs, + ...extraEnvs }); this.logger.debug("Spawning Runner process with command", runnerCommand); diff --git a/packages/host/src/lib/host.ts b/packages/host/src/lib/host.ts index d356969de..1233c1232 100644 --- a/packages/host/src/lib/host.ts +++ b/packages/host/src/lib/host.ts @@ -201,7 +201,7 @@ export class Host implements IComponent { this.logger = new ObjLogger( this, {}, - ObjLogger.levels.find((l: LogLevel) => l.toLowerCase() === sthConfig.logLevel) || + ObjLogger.levels.find((l: LogLevel) => l.toLowerCase() === sthConfig.logLevel.toLowerCase()) || ObjLogger.levels[ObjLogger.levels.length - 1] );