Software Version & Hardware Version
Hardware Version
The Hardware Version is used to identify the type of hardware on which software
is running. In Memfault, a device always has exactly one Hardware Version. It
can be used to identify different device types being tracked in the same Project
(i.e. smart-toaster
and smart-oven
) and different board revisions of the
same device type (i.e. smart-toaster-evt
, smart-toaster-pvt
, etc.).
By default, the Hardware Version of an individual Device is set permanently during the first time it reports in to Memfault. To enable updating this field, please contact us.
Hardware Versions must be between 1 and 128 characters long and can only contain
the following characters: a-z
, A-Z
, 0-9
, -_.+:\()[]/,
and spaces.
MCU
The software running on your devices will need to report its Hardware Version. Please see the core/device info component of the Firmware SDK for details on how to set this up on the device's software side.
Android
On Android, Memfault uses the ro.product.model
system property as the device's
Hardware Version by default. From the
Android product documentation:
The board/device layer represents [...] the bare schematics of a product. These include the peripherals on the board and their configuration.
Linux
On Linux, the Hardware Version needs to be reported to memfaultd
by the
memfault-device-info
program, which you need to
implement as part of the integration.
Software Type
A Software Type can be thought of as a "namespace" for Software Versions. The
Software Type is used to identify the separate pieces of software running on a
given device. This can be images running on different MCUs (i.e main-mcu-app
&
bluetooth-mcu
) or different images running on the same MCU (i.e
main-mcu-bootloader
& main-mcu-app
).
The Software Type is also included in a Trace's Signature. See the callout below for pitfalls.
Software Types must be between 1 and 128 characters long and can only contain
the following characters: a-z
, A-Z
, 0-9
, -_.+:\()[]/,
and spaces.
It is not recommended to use Software Types to distinguish between software
build variants (i.e. main-mcu-development
& main-mcu-prod
), because:
-
It does not play nicely with Memfault's concept of "Primary Software Type" (see below). We recommend encoding build variants into the Software Version instead, by suffixing the version (i.e.
1.0.0-development
). -
The Software Type is included in a Trace's Signature. This means that Traces with identical contents (e.g. crash stacktrace) but different Software Types will result in different Issues being created. In short, it breaks the Trace deduplication, causing multiple Issues for the same root cause to be created.
Primary Software Type
Memfault's platform uses the notion of "Primary Software Type" to identify the main software version for a device.
Each Hardware Version has a single matching Primary Software Type associated with it, which is set from the Software Type for the first device reporting in with a particular Hardware Version. The association can also be modified later from the Settings page. An example:
The Primary Software Type is used to populate the Software Version field on the individual Device page, as well as when filtering for the device, and how it appears in various fleet-level charts. When Memfault OTA is used to deploy software, the versions of OTA Releases are also expected to be derived from Software Versions of the Primary Software Type.
You can configure the Primary Software Type in Settings –> Hardware –> Create Hardware Version.
MCU
The software running on your devices will need to report its Software Type correctly such that it matches what has been configured in the Project. Please see the core/device info component of the Firmware SDK for details on how to set this up on the device's software side.
Android
Memfault uses android-build
as the Software Type for the Android OS itself.
Android Applications have a Software Type equal to their
application ID,
e.g. com.acme.smartsink
.
Linux
On Linux, the Software Type is specified in the memfaultd.conf
file and can be overridden via
memfault-device-info
.
Software Version
A Software Version is a single build of a particular Software Type. Software Versions are used in Memfault in a variety of ways, including but not limited to:
- Displaying Issue distributions by version.
- Determining regressions: re-opening an Issue if a defect recurs in a newer Software Version after the Issue was marked as resolved.
- Checking if a device is up to date: if your Project uses Memfault to deploy firmware, the firmware's Software Version is used to determine if a device requires an update.
Aside from the requirements that follow from the chosen versioning scheme,
Software Versions must be between 1 and 128 characters long and can only contain
the following characters: a-z
, A-Z
, 0-9
, -_.+:\()[]/,
and spaces.
Versioning Schemes
Human-readable and understandable software versions go a long way. A good scheme allows everyone involved in a project to quickly determine whether a device's build is new, old, or a one-off build built by an engineer. On top of readability, a good versioning scheme allows trivial and algorithmic comparisons between software versions.
Comparison between versions is also a fundamental input to Memfault's OTA system. Consult the section Updating Behavior on our OTA documentation to see how the rules below are applied to OTA.
Recommended Versioning Scheme
Memfault recommends using SemVer 2.0 for versioning. Specifically, using these forms will result in the least confusion:
-
for official releases, strict SemVer ("normal version number" per the spec):
1.0.0
Exactly 3 digit groups, leading zeros permitted, delimited by periods (see the spec for details).
-
"beta" or "release candidate", etc., pre-release versions:
1.0.0-beta.0
1.0.0-rc.0 -
automated nightly builds that are deployed over Memfault OTA to a Cohort:
# using a build number (eg CI build number, or monotonically incrementing
# based on git tag, etc.)
1.0.0-nightly.0
# using a calendar version. always increments, and can be generated without
# context (assuming only 1 build is deployed per day)
1.0.0-nightly.20220123 -
development builds generated locally (using git sha or other identifier):
1.2.3+092ced197518c8e304232239315c611af6ff2404
And set the "Disable Version Checking" setting for the Cohort.
To help generate version suffixes, consider the following:
- If using Git tags, see information on
git rev-parse
for generating tag strings - If using a calendar version, the unix
date
command could be used. For example,date --utc +%Y%m%d
.
MCU
The device_info.software_version
field may need to be populated at build time
by the build script. For example, you might have a C preprocessor token that
holds the string for the software version, where the value is populated by a
build script:
# a C compiler option setting the SOFTWARE_VERSION token to a string
-DSOFTWARE_VERSION=\"1.0.0-nightly.20220123\"`
Please see the core/device info component of the Firmware SDK for details on how to set this up on the device's software side.
Android OS
Memfault supports extracting the Software Version for the android-build
Software Type from several different sources to suit different build
configurations.
By default, irrespective of the source, the Software Version will be ordered per Version Schemes.
Recommended: Build Fingerprint and System Property
We recommend using both the build fingerprint and a custom system property for situations where the build fingerprint does not contain a meaningful identifier; for example, if the incremental and ID parts of the fingerprint are set by the ODM and have no semantic meaning for your internal software versioning.
The full Software Version stored in Memfault will have the form:
${fingerprint}::${property}
This provides the additional functionality enabled by using the build fingerprint, while also using a system property of your choice for display and comparison purposes.
The fingerprint must uniquely identify the build, and the specified system property must also uniquely identify the build.
Recommended: Build Fingerprint Only
Memfault supports using the
Android build fingerprint
as the Software Version. In recent AOSP builds, the build fingerprint can be
found in out/target/product/$DEVICE/build_fingerprint.txt
.
If the fingerprint is used to specify the Software Version, the fingerprint must be unique for each build.
We recommend using the fingerprint instead of a single system property because it enables additional functionality such as the ability to filter traces based on fingerprint properties like the build type.
Because the build fingerprint is usually a very long string, the Memfault UI will show only the most relevant part. By default, the "incremental" component is used for display and ordering; this can be customized to instead use e.g. the "ID" component.
System Property Only
The Software Version can be sourced from any system property. The specified property must be able to uniquely identify the build (the value must be unique for each build).
Android Applications
For Android applications (instead of the Android OS), Memfault will use the
APK's
versionCode
and versionName
to compare Software Versions.
Linux
On Linux, the Software Version must be specified in the memfaultd.conf
file and can be overridden by
memfault-device-info
.
Archiving Software Types and Versions
Memfault supports archiving Software Types and Versions. This action removes the selected Software Type or Software Version. After clicking the Archive button you'll no longer be able to see the selected Software Type/Version in the UI. The operation also marks any associated Events and Traces for deletion after 30 days.
A Software Type/Version cannot be unarchived so proceed with caution!
Memfault's Version Ordering Internals
By default, Memfault uses Natsort. Natsort was chosen given the balance of flexibility and predictability.
Memfault uses a slight tweak on top of natsort
to support rc
or dev
versioning schemes. This is achieved by
appending a character z
.
For example, these versions are sorted from oldest to newest:
1.0.0rc1
1.0.0
1.0.1-dev
1.0.1-rc2
1.0.1
1.0.12
1.0.20
To implement a "release candidate" or "alpha/beta" versioning scheme, the recommended option is to follow the SemVer 2.0 specification, for example:
1.0.0-alpha.1
1.0.0-alpha.2
Or:
1.0.0-rc.0
1.0.0-rc.1
Be cautious about more exotic versioning schemes! natsort
will only handle the
common scenarios.
For example, the SemVer 2.0 spec permits appending build metadata to a version number:
1.0.0+092ced197518c8e304232239315c611af6ff2404
But natsort
will apply lexical ordering (under the default settings), which
may not result in the expected OTA response
(see "Disable Version Checking").
For example, the following three software versions are in the correct order, despite SemVer 2.0 declaring they are equal.
1.0.0+00000000
1.0.0+aaaaaaaa
1.0.0+ffffffff
Testing the Ordering
It is imperative to understand how your Software Versions will be ordered by Memfault's OTA system.
To test version ordering locally, install
Natsort and create a simple Python script
order.py
to test it out.
from natsort import natsorted
def memfault_natsort(items: list[str]):
return natsorted(items, key=lambda x: x + "z")
versions = ['1.0.0', '1.0.0-alpha', '1.10.0-beta']
print(memfault_natsort(versions))
$ python order.py
['1.0.0-alpha', '1.0.0', '1.10.0-beta']