Any issues or suggestions to improve fqm-execution
can be reported through a GitHub issue. Filling out the issue template as completely as possible
helps us replicate and track down the sources of issues faster.
We will gladly accept pull requests to help improve fqm-execution
. When submitting a pull request, please follow the auto-populated pull request template, describing the following:
- The goal/purpose of the pull request
- If the pull request resolves a GitHub issue, link the issue using the
"Fixes #___"
shorthand in the summary, which will automatically link issue___
to the pull request
- If the pull request resolves a GitHub issue, link the issue using the
- What runtime behavior has changed in the library as a result of the pull request, if any
- Relevant high-level code changes required for the pull request
- Instructions for the reviewer on how to test the pull request and verify the expected behavior
Guidelines covering project governance, including issue workflow and release expectations, can be found in the governance guidelines.
- Any code editor that has TypeScript language support. VS Code is most popular
- Node.js >=16.0.0 is supported, LTS (
>=18.0.0
) is recommended - Git
Clone the source code:
git clone https://github.com/projecttacoma/fqm-execution.git
Install dependencies:
cd fqm-execution
npm install
The easiest way to test new code in fqm-execution
is to use the built-in command line interface (CLI). This CLI can interface with all of the calculation capabilities of fqm-execution
and produce results that can be inspected/tested.
Run the CLI with the built-in package.json
script:
npm run cli -- [command] [options]
Or using the built JavaScript:
npm run build
node build/cli.js [command] [options]
Optionally, you can install the ts-node
utility globally to execute the TypeScript files directly instead of running the build script:
npm install -g ts-node
ts-node src/cli.ts [command] [options]
For a full list of available options and commands, see the CLI section of the main documentation
The CLI comes built with a debug option (-d/--debug
) which will include a debugOutput
property on the results object containing any CQL, ELM, ValueSets, and engine results processed during execution. These files will also be written to a ./debug
directory when this flag is provided,
which is useful for inspecting contents of ELM, CQL, or results.
Most commonly, development on fqm-execution
will involve pre-existing measure bundles provided via a content repository or some other means (e.g. attached to a GitHub issue report). However, in some cases it may be useful to create a smaller "stripped down" version of a measure bundle
that makes it easier to debug potential issues.
To create your own measure bundle to use during development, consider using the ecqm-bundler command line utility to easily generate valid measure bundles that fqm-execution
will accept as input. Alongside this, you can also use our publicly deployed instance of fqm-testify
to create simple patients that you can run through fqm-execution
as well.
In general, runtime errors that come directly from fqm-execution
are quite rare. Most unhandled errors come from dependent libraries, i.e. cql-execution or cql-exec-fhir
Error throws with this message commonly come from cql-execution
. The most common cause for this kind of error is a mismatch in data types for either the ELM expressions or the patient data itself (e.g. trying to do a union
on arguments that are not list-like). The recommended approach for debugging this kind of issue is:
- Try to isolate the ELM library and expression where the issue comes from
- Visually inspect the content of the ELM JSON for this library, and ensure that the operands for the function being called are the correct data types (e.g. see if it should be wrapped in a
FHIRHelpers.To___
function call) - Ensure that the HL7® FHIR®[1] data present in the patient
Bundle
are valid according to the FHIR specification
If the above conditions do not lead to an identified cause, it might be worth raising an issue in the cql-execution repository. To verify that the issue indeed comes from cql-execution
, consider using the execution extractor command line utility to extract all of the ELM content, ValueSets, etc. and run it through cql-execution
directly without needing to go through fqm-execution
. If the error still persists, then the issue lies outside fqm-execution
, and is either a problem with the input or with cql-execution
itself.
In some cases, fqm-execution
will succeed in its calculation, but the data returned may yield some unexpected calculation results. The most common situations where this kind of issue arises is calculating complex measures, such as ratio measures with multiple observations or initial populations. The recommended approach for debugging these kinds of issues is:
- Inspect the highlighted measure logic and identify the unexpected clauses that are being highlighted as red
- Inspect the relevant portions of patient data, and ensure that the data is correct relative to the measurement period that is being used for calculation
- Inspect the raw results coming back from
cql-execution
using the CLIraw
command or the.calculateRaw
API function and ensure that the proper raw data is being returned for each expression
If everything from steps 1-3 seems correct, there may be an issue with the population processing logic in fqm-execution
. In this case, please feel free to submit an issue or a pull request.
A commonly seen unexpected population result may come up when two compared DateTime
properties are thought to be equivalent. When considering DateTime
equivalencies, it is important to note the precision of the compared DateTime
properties.
Consider the following DateTime
data:
- a: "2021-12-01T08:00:00.000+00:00"
- b: "2021-12-01T08:00:00+00:00"
While these describe the "same time" according to human inspection, the calculation engine must consider the uncertainty that comes from the less precise DateTime
b
. For the b
DateTime
, cql-execution
constructs an Uncertainty
containing the range of 0 to 999 milliseconds.
When evaluating a statement about b
,cql-execution
needs to account for all possible b
values. This will be represented as an Uncertainty
. b
may be anywhere in the range "2021-12-01T08:00:00.000+00:00" to "2021-12-01T08:00:00.999+00:00". As such, if we're comparing a
and b
, the engine can guarantee that a
is <= b
but not guarantee that b
is <= a
. If b
must be before or equivalent to a
, the result of the comparison clause will be null
and show falsy values in highlighting.
To fix: Consider changing your test data to have matching precision, millisecond precision preferred. Alternatively, the precision you wish to use for the comparison can be added to the logic. ex. during seconds of
.
Examples of this issue and a description of the resolution can be seen in Issue #177 and Issue #224
To attach a debugger to the TypeScript files for deeper inspection of the tool's functionality, we recommend using the VS Code's built in debugging adapter to be able to provide easy debugger configuration.
Add the following contents to .vscode/launch.json
in the root of the project directory:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"preLaunchTask": "npm: build",
"program": "${workspaceFolder}/src/cli.ts",
"outFiles": [
"${workspaceFolder}/build/**/*.js"
],
"internalConsoleOptions": "openOnSessionStart",
"args": ["<reports | detailed | raw | gaps | dataRequirements | libraryDataRequirements | queryInfo | valueSets>", "-m", "${workspaceFolder}/relative/path/to/measure/bundle.json", "-p", "${workspaceFolder}/relative/path/to/patient/bundle.json", "-o"]
}
]
}
This will allow you to run the CLI from the Run
tab in VS Code, and will halt execution of the program at any breakpoints or debugger
statements in the code, to allow for debugging of the functionality.
NOTE: The dataRequirements
, libraryDataRequirements
, queryInfo
, and valueSets
commands do not require patient bundle(s) to be specified in the args
array
We use Jest for unit-testing fqm-execution
. Tests can be running using the test
script in package.json:
npm test
For integration testing, see the integration testing README for more information. The integration tests can be run with the following command:
npm run test:integration
When contributing new code, ensure that all tests, lint, and prettier checks pass with the following command:
npm run check
fqm-execution
also comes with a "regression" script, which is useful for ensuring that any changes made on a given branch did not change the calculation results for past known-good measures. To run the regression script:
./regression/run-regression.sh [-b|--base-branch <branch-name>] [-v|--verbose]
The above command will:
- Download all known ecqm-content repositories that have previously been a source of input for
fqm-execution
, which is currently:
- Run every measure bundle in those repositories through calculation for every test patient provided in that repository
- Run the same calculations on the "base" branch to compare the results with (default is the
master
branch, but this can be customized with-b/--base-branch
- Compare the contents of the calculation results across the two branches. If any calculation results differ, the offending files will be reported as failures in the console
Full command options:
Usage: ./regression/run-regression.sh [-b|--base-branch <branch-name>] [-v|--verbose]
Options:
-b/--base-branch: Base branch to compare results with (default: master)
-v/--verbose: Use verbose regression. Will print out diffs of failing JSON files with spacing (default: false)
Copyright 2020-2023 The MITRE Corporation
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
[1] FHIR® is the registered trademark of Health Level Seven International (HL7).