Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions score/health_monitor/configuration/health_monitor_config.fbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// ********************************************************************************
// Copyright (c) 2026 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache License Version 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0
//
// SPDX-License-Identifier: Apache-2.0
// ********************************************************************************

namespace score.mw.health.config;

file_identifier "HMCF";
file_extension "bin";

/// Scheduler policy for the monitoring thread.
enum SchedulerPolicy : byte {
Other = 0,
Fifo = 1,
RoundRobin = 2
}

/// Scheduler parameters: policy and priority.
table SchedulerParameters {
policy: SchedulerPolicy = Other;
priority: int32;
}

/// Thread parameters for the monitoring thread.
table ThreadParameters {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if certain parameters are optional?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything is optional unless explicitly marked as required, as I understand.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For scalar types flatbuffer will use a default value (e.g. 0) and you will not know whether it was actually configured or not.
If that is not suitable, you can use " = null;" to truly make it optional.

For non-scalar types you get nullptr from flatbuffer api in case it is not configured.

scheduler_parameters: SchedulerParameters;
affinity: [uint32];
stack_size: uint32 = null;
}

/// A time range with minimum and maximum durations in milliseconds.
table TimeRange {
min_ms: uint32;
max_ms: uint32;
}

/// A single deadline entry within a deadline monitor.
table DeadlineEntry {
deadline_tag: string (required);
range: TimeRange (required);
}

/// Configuration for a deadline monitor.
table DeadlineMonitor {
monitor_tag: string (required);
deadlines: [DeadlineEntry] (required);
}

/// Configuration for a heartbeat monitor.
table HeartbeatMonitor {
monitor_tag: string (required);
range: TimeRange (required);
}

/// A state and its allowed transitions in a logic monitor.
table StateNode {
state: string (required);
allowed_transitions: [string] (required);
}

/// Configuration for a logic monitor.
table LogicMonitor {
monitor_tag: string (required);
initial_state: string (required);
states: [StateNode] (required);
}

/// Root configuration for a HealthMonitor instance.
table HealthMonitorConfig {
schema_version: uint32 = 1;
supervisor_api_cycle_ms: uint32;
internal_processing_cycle_ms: uint32;
thread_parameters: ThreadParameters;
deadline_monitors: [DeadlineMonitor];
heartbeat_monitors: [HeartbeatMonitor];
logic_monitors: [LogicMonitor];
}

root_type HealthMonitorConfig;
180 changes: 180 additions & 0 deletions score/health_monitor/configuration/health_monitor_config.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LM schema is based on 2020-12 version. Maybe we can use newer version to keep this in sync?

"$id": "health_monitor_config.schema.json",
"title": "HealthMonitorConfig",
"description": "Configuration schema for HealthMonitor (compatible with health_monitor_config.fbs)",
"type": "object",
"required": ["supervisor_api_cycle_ms", "internal_processing_cycle_ms"],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be worth to add schema_version here as well.

"properties": {
"schema_version": {
"type": "integer",
"minimum": 1,
"default": 1,
"description": "Schema version"
},
Comment on lines +9 to +14

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LM is using following construct:

    "schema_version": {
      "type": "integer",
      "description": "Specifies the schema version number that the Launch Manager uses to determine how to parse and validate this configuration file.",
      "enum": [
        1
      ]
    }

With your current proposal, integrator can configure 12 as schema_version and configuration will still pass validation.
Additionally I would be careful with using default in schema. They are not applied during validation and need to be added during configuration read. Populating not configured parameters with default values, during configuration load, is also a bit of a hassle.

I would suggest to go for enum here, and keep defined values always to a single number. Additionally I would define schema_version as required at the object level.
This way you will force integrator to declare which version of schema was used for configuration and if configuration validates against that schema, you will know that this schema can be used for reading this configuration file.

"supervisor_api_cycle_ms": {
"type": "integer",
"minimum": 1,
"description": "Cycle duration in ms for supervisor API notifications"
},
Comment on lines +15 to +19

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LM is using seconds as the measurement unit of time (e.g., '0.5' for 500 milliseconds). I would be tempted to suggest that we should use the same approach for health monitoring.

This way integrator will be not restricted with precision they would like to use. Encoding precision in parameter name will force configuration change, when we would allow different precision.

Additionally it may be useful to define time as a reusable type. This type can be then used by supervisor_api_cycle, internal_processing_cycle and TimeRange

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use floating point numbers, we may have to prove that we do it in a safe way. An activity that can be avoided. Please see the issue #345

"internal_processing_cycle_ms": {
"type": "integer",
"minimum": 1,
"description": "Cycle duration in ms for internal deadline checks"
},
"thread_parameters": {
"$ref": "#/definitions/ThreadParameters"
},
"deadline_monitors": {
"type": "array",
"items": { "$ref": "#/definitions/DeadlineMonitor" },
"description": "List of deadline monitors"
},
"heartbeat_monitors": {
"type": "array",
"items": { "$ref": "#/definitions/HeartbeatMonitor" },
"description": "List of heartbeat monitors"
},
"logic_monitors": {
"type": "array",
"items": { "$ref": "#/definitions/LogicMonitor" },
"description": "List of logic monitors"
}
},
"additionalProperties": false,
"definitions": {
"SchedulerPolicy": {
"type": "string",
"enum": ["Other", "Fifo", "RoundRobin"],
"description": "Scheduler policy for the monitoring thread"
},
Comment on lines +46 to +50

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LM is using this construct to define scheduling policy:

            "scheduling_policy": {
              "type": "string",
              "description": "Specifies the scheduling policy applied to the component's initial thread. Supported values correspond to OS-defined policies (e.g., FIFO, RR, OTHER).",
              "anyOf": [
                {
                  "enum": [
                    "SCHED_FIFO",
                    "SCHED_RR",
                    "SCHED_OTHER"
                  ]
                },
                {
                  "type": "string"
                }
              ]
            }

This way you can get autocomplete, in some text editors, for POSIX defined schedulers, but you also allow configuration of OS specific schedulers.

Current version will restrict integrator to ["Other", "Fifo", "RoundRobin"] and force implementation to do translation from Fifo to SCHED_FIFO when reading config.

"SchedulerParameters": {
"type": "object",
"properties": {
"policy": { "$ref": "#/definitions/SchedulerPolicy" },
"priority": {
"type": "integer",
"description": "Thread priority"
}
},
"required": ["policy", "priority"],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure that we would like to force integrator to always configure policy and priority? I would prefer to keep required configuration to bare minimum.

"additionalProperties": false
},
"ThreadParameters": {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to merge SchedulerPolicy, SchedulerParameters and ThreadParameters into a single type.

I'm not sure if I see benefits of keeping SchedulerPolicy and SchedulerParameters as a separate type.

"type": "object",
"properties": {
"scheduler_parameters": { "$ref": "#/definitions/SchedulerParameters" },
"affinity": {
"type": "array",
"items": { "type": "integer", "minimum": 0 },
"description": "CPU core IDs the thread can run on"
},
"stack_size": {
"type": "integer",
"minimum": 0,
"description": "Stack size in bytes"
}
},
"additionalProperties": false
},
"TimeRange": {
"type": "object",
"required": ["min_ms", "max_ms"],
"properties": {
"min_ms": {
"type": "integer",
"minimum": 0,
"description": "Minimum duration in milliseconds"
},
"max_ms": {
"type": "integer",
"minimum": 0,
"description": "Maximum duration in milliseconds"
}
},
"additionalProperties": false
},
"DeadlineEntry": {
"type": "object",
"required": ["deadline_tag", "range"],
"properties": {
"deadline_tag": {
"type": "string",
"minLength": 1,
"description": "Unique identifier for the deadline"
},
"range": { "$ref": "#/definitions/TimeRange" }
},
"additionalProperties": false
},
"DeadlineMonitor": {
"type": "object",
"required": ["monitor_tag", "deadlines"],
"properties": {
"monitor_tag": {
"type": "string",
"minLength": 1,
"description": "Unique identifier for the deadline monitor"
},
"deadlines": {
"type": "array",
"items": { "$ref": "#/definitions/DeadlineEntry" },
"minItems": 1
}
},
"additionalProperties": false
},
"HeartbeatMonitor": {
"type": "object",
"required": ["monitor_tag", "range"],
"properties": {
"monitor_tag": {
"type": "string",
"minLength": 1,
"description": "Unique identifier for the heartbeat monitor"
},
"range": { "$ref": "#/definitions/TimeRange" }
},
"additionalProperties": false
},
"StateNode": {
"type": "object",
"required": ["state", "allowed_transitions"],
"properties": {
"state": {
"type": "string",
"minLength": 1,
"description": "State identifier"
},
"allowed_transitions": {
"type": "array",
"items": { "type": "string", "minLength": 1 },
"description": "List of states reachable from this state"
}
},
"additionalProperties": false
},
"LogicMonitor": {
"type": "object",
"required": ["monitor_tag", "initial_state", "states"],
"properties": {
"monitor_tag": {
"type": "string",
"minLength": 1,
"description": "Unique identifier for the logic monitor"
},
"initial_state": {
"type": "string",
"minLength": 1,
"description": "Starting state of the logic monitor"
},
"states": {
"type": "array",
"items": { "$ref": "#/definitions/StateNode" },
"minItems": 1
}
},
"additionalProperties": false
}
}
}
Loading