Skip to content

Commit 0218196

Browse files
Release/0.9.4 (#166)
* bumps version to 0.9.4 * changes to cql-ls v4.6.0 * fix logging issues * fixes issue with missing "testCasesToExclude" option in config.json file * updates change log
1 parent 315ae21 commit 0218196

4 files changed

Lines changed: 81 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Change Log
22

3+
4+
## v0.9.4 (prerelease)
5+
6+
Date: 2026-05-14
7+
8+
* fixes issue with missing "testCasesToExclude" option in config.json file
9+
* fix logging issues, most logs were defaulting to info level and not honoring actual defined level
10+
* bumps CQL LS to v4.6.0
11+
* bumps version to 0.9.4
12+
13+
314
## v0.9.3 (prerelease)
415

516
Date: 2026-04-21

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cql",
3-
"version": "0.9.3",
3+
"version": "0.9.4",
44
"displayName": "Clinical Quality Language (CQL)",
55
"description": "Syntax highlighting, linting, and execution for the HL7 Clinical Quality Language (CQL) for VS Code",
66
"publisher": "cqframework",
@@ -658,7 +658,7 @@
658658
"cql-language-server": {
659659
"groupId": "org.opencds.cqf.cql.ls",
660660
"artifactId": "cql-ls-server",
661-
"version": "4.5.0"
661+
"version": "4.6.0"
662662
}
663663
},
664664
"devDependencies": {

src/commands/execute-cql.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,11 @@ export function loadTestConfig(testConfigPath: Uri): TestConfig {
560560
log.error('Error parsing config file', errors);
561561
return { testCasesToExclude: [] };
562562
}
563-
return parsed;
563+
// Ensure testCasesToExclude is always defined to prevent iteration errors
564+
return {
565+
...parsed,
566+
testCasesToExclude: parsed.testCasesToExclude ?? []
567+
};
564568
} catch (error) {
565569
log.error('Error reading config file', error);
566570
return { testCasesToExclude: [] };

src/log-services/multi-transport-logger.ts

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export class MultiTransportLogger implements LogOutputChannel {
99
private readonly _logger: WinstonLogger;
1010
private readonly _logFileBaseName: string;
1111
private readonly _logFileStorageUri: Uri;
12+
private _currentBlockLevel: string | undefined;
1213

1314
readonly logLevel: LogLevel;
1415
readonly onDidChangeLogLevel: Event<LogLevel>;
@@ -35,7 +36,11 @@ export class MultiTransportLogger implements LogOutputChannel {
3536
});
3637

3738
this._logger = createLogger({
38-
level: 'debug', // Default level
39+
// Use the transport's own level set so 'trace' is a recognised level name
40+
// and maps correctly to outputChannel.trace() instead of falling through
41+
// to appendLine() in the default case.
42+
levels: LogOutputChannelTransport.config.levels,
43+
level: MultiTransportLogger.toWinstonLevel(this._outputChannel.logLevel),
3944
format: format.combine(
4045
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
4146
format.errors({ stack: true }),
@@ -49,6 +54,26 @@ export class MultiTransportLogger implements LogOutputChannel {
4954
this._dailyFileTransport,
5055
],
5156
});
57+
58+
this._outputChannel.onDidChangeLogLevel(level => {
59+
if (level === LogLevel.Off) {
60+
this._logger.silent = true;
61+
} else {
62+
this._logger.silent = false;
63+
this._logger.level = MultiTransportLogger.toWinstonLevel(level);
64+
}
65+
});
66+
}
67+
68+
private static toWinstonLevel(level: LogLevel): string {
69+
switch (level) {
70+
case LogLevel.Trace: return 'trace';
71+
case LogLevel.Debug: return 'debug';
72+
case LogLevel.Info: return 'info';
73+
case LogLevel.Warning: return 'warn';
74+
case LogLevel.Error: return 'error';
75+
default: return 'info';
76+
}
5277
}
5378

5479
getOuptutChannelName(): string {
@@ -86,8 +111,44 @@ export class MultiTransportLogger implements LogOutputChannel {
86111
appendLine(value: string): void {
87112
const lines = value.split('\n');
88113

114+
// Logback server stderr pattern:
115+
// %-4relative [%thread] %-5level %logger{35} %msg %n
116+
// e.g. "1234 [main] WARN org.opencds.SomeClass Some message"
117+
const logbackPattern = /^\d+\s+\[\S+\]\s+(TRACE|DEBUG|INFO|WARN|ERROR)\s+/i;
118+
119+
// vscode-languageclient LSP trace pattern: "[Trace - HH:MM:SS AM] ..."
120+
// The header and its params body arrive in separate appendLine() calls, so
121+
// _currentBlockLevel persists the detected level across calls.
122+
const lspTracePattern = /^\[(Trace|Debug|Info|Warn|Error)\s+-\s+/i;
123+
124+
// If this call starts with an LSP trace header, update the persisted level.
125+
for (const line of lines) {
126+
if (!line.trim()) continue;
127+
const m = lspTracePattern.exec(line);
128+
if (m) this._currentBlockLevel = m[1].toUpperCase();
129+
break;
130+
}
131+
132+
const logAtLevel = (level: string | undefined, line: string) => {
133+
switch (level) {
134+
case 'TRACE': this._logger.log('trace', line); break;
135+
case 'DEBUG': this._logger.debug(line); break;
136+
case 'WARN': this._logger.warn(line); break;
137+
case 'ERROR': this._logger.error(line); break;
138+
default: this._logger.info(line); break;
139+
}
140+
};
141+
89142
lines.forEach(line => {
90-
if (line) this._logger.info(line);
143+
if (!line) return;
144+
const logbackMatch = logbackPattern.exec(line);
145+
if (logbackMatch) {
146+
// Server log lines carry their own level — use it directly.
147+
logAtLevel(logbackMatch[1].toUpperCase(), line);
148+
} else {
149+
// LSP trace lines (header + continuation) use the persisted block level.
150+
logAtLevel(this._currentBlockLevel, line);
151+
}
91152
});
92153
}
93154

0 commit comments

Comments
 (0)