Reuse and Configuration

This page covers the connector-level building blocks that let connectors share logic (extends, constants, translations) and let users configure behavior (connector variables, sudo commands).

Load-Time Resolution Order

When a connector is parsed, the engine resolves its building blocks in this order:

  1. extends — parent connectors are merged in
  2. ${var::name} — connector variables are substituted (defaults or user-configured values)
  3. ${source::...} and other references are resolved to absolute paths
  4. ${constant::name} — constants are inlined, then the constants section is dropped

All of the above happens once, at load time. Runtime credential macros (%{USERNAME}, %{PASSWORD}, …) are different: they are resolved at execution time, per request — see References and Expressions[1].

extends: Connector Inheritance

A connector can inherit from one or more parent connectors:

extends:
- ../../semconv/Hardware          # metric metadata dictionary
- ../MIB2-header/MIB2-header      # shared detection + monitors

Paths are resolved relative to the connector's own directory, and .yaml is appended automatically. Parents may themselves extend other connectors (chained inheritance is fully resolved). The extends key is stripped from the compiled connector.

Merge Rules

Parents are merged in list order, then the child is merged last — the child always wins over all parents, and a later parent wins over an earlier one. The merge is a structural deep merge:

Node kind Merge behavior
Objects (maps: monitors, metrics, translations, sources, mapping.attributes, …) Deep-merged key by key. Redefining one key overrides that entry only; sibling keys survive.
Arrays of objects (detection.criteria, computes, …) Child items are appended after the parent's items.
Arrays of scalars (keys, appliesTo, sudoCommands, …) Child array replaces the parent's array entirely.
Scalars Child value overrides the parent's.
Warning

Arrays of objects are appended, never replaced: if a parent source defines computes, your child's computes run in addition to the parent's — you cannot remove or reorder inherited criteria or computes, only add after them. If you need a genuinely different pipeline, do not inherit that subtree.

Semconv Connectors

The files under src/main/connector/semconv/ (Hardware, System, Storage, Database) contain only a metrics: map — no detection, no monitors. They are metric metadata dictionaries: unit, description, and instrument type for each standard metric name, aligned with OpenTelemetry semantic conventions.

Extend the relevant one so your metrics automatically carry the official metadata; only declare a local metrics: entry when you introduce a metric the semconv file does not define. See Mapping, Metrics, and Semconv[2].

Header Connectors

When several connectors share the same collection logic (e.g. the same SNMP tables or the same command parsing), factor it into a header connector — a partial connector holding the shared detection.criteria, monitors, and translations, not usable on its own. Each real connector then extends the header and adds only its identity and detection targeting:

# MIB2.yaml
extends:
- ../../semconv/Hardware
- ../MIB2-header/MIB2-header
connector:
  displayName: MIB-2 Standard SNMP Agent
  platforms: SNMP
  detection:
    appliesTo: [ Network ]
    supersedes: [ ... ]

Headers are best parameterized with constants: the header references ${constant::...} placeholders and each child supplies the values (see below). This is cleaner than overriding inherited sources.

Community examples: MIB2-header[3] with MIB2[4]; LinuxNetwork-header[5] with LinuxIPNetwork[6].

constants

Top-level map of reusable literals, referenced as ${constant::name} anywhere in the connector:

constants:
  GLOBAL_COMMAND_LINE: /sbin/ip a
  COLLECT_COMMAND_LINE: /sbin/ip -s link show dev ${attribute::id}

Constants are inlined at load time by plain text substitution, and the constants section is then removed from the compiled connector.

The flagship use case is parameterizing a header connector: LinuxNetwork-header runs ${constant::GLOBAL_COMMAND_LINE}, and each child (LinuxIPNetwork with ip, LinuxIfConfigNetwork with ifconfig) supplies its own command through constants.

Note

Constant substitution is a single, non-recursive pass: do not chain constants (a constant referencing another constant) and do not expect ${var::...} inside a constant value to be expanded — variables are resolved before constants.

connector.variables

Variables make a connector user-configurable. Declare them under connector.variables, each with a description and a defaultValue, and reference them as ${var::name} anywhere in the connector or its embedded files:

connector:
  displayName: Linux - Processes
  variables:
    matchName:
      description: Regular expression pattern to match process names for monitoring.
      defaultValue: .*
  detection:
    disableAutoDetection: true
    ...

monitors:
  process:
    simple:
      sources:
        processes:
          type: commandLine
          commandLine: /usr/bin/ps -e -o comm,args | grep -E "${var::matchName}"

Variables are resolved once, at connector load time:

  • A default instance of the connector always exists with the defaultValues applied, so forcing the connector (connectors: [ +LinuxProcess ]) works without any variable configuration.
  • Users create additional configured instances in metricshub.yaml with additionalConnectors:
resources:
  prod-web:
    attributes: { host.name: prod-web, host.type: linux }
    protocols:
      ssh: { username: monitor, password: "..." }
    additionalConnectors:
      systemdProcess:          # new connector instance id
        uses: LinuxProcess     # base connector
        variables:
          matchName: systemd
Important

Always provide a defaultValue. A variable with no default and no user-configured value is not substituted — the literal ${var::name} string survives into the connector and typically breaks at runtime.

Community examples: LinuxProcess[7], LinuxService[8], LinuxFile[9]. Note that all of them pair variables with disableAutoDetection: true: a connector whose behavior depends on user input is usually meant to be selected explicitly.

translations

Top-level map of translation tables, consumed by the translate[10], arrayTranslate[11], and perBitTranslation[12] computes via ${translation::TableName}:

translations:
  PhysicalDiskStatusTranslationTable:
    "3": ok
    "4": degraded
    "5": failed
    default: UNKNOWN

Authoring rules:

  • Keys are matched case-insensitively against the cell value; quote numeric keys so YAML treats them as strings.
  • The default key is the fallback for unmatched values (translate and arrayTranslate honor it; perBitTranslation ignores it).
  • Translate into the exact state names your metric's stateSet declares (ok, degraded, failed), so mapping can use the column directly.
  • Declare each table once and reference it from every source that needs it; tables inherited via extends merge key by key.

sudoCommands

Some Linux/Unix commands need elevation. Declare the commands under top-level sudoCommands and prefix their invocations with the %{SUDO:command} macro:

sudoCommands:
- /usr/bin/sensors

monitors:
  temperature:
    simple:
      sources:
        sensors:
          type: commandLine
          commandLine: "%{SUDO:/usr/bin/sensors} /usr/bin/sensors"

At runtime, %{SUDO:/usr/bin/sensors} expands to the configured sudo command (sudo by default) only if the user enabled sudo in their OS-command protocol configuration (useSudo: true) and whitelisted the command. Otherwise the macro silently expands to an empty string and the command runs without elevation — so the command line must remain valid without the prefix (note the pattern above: the macro is a prefix, the real command follows).

Community examples: lmsensors[13], LinuxMultipath[14], SmartMonLinux[15].

Common Mistakes

  • Expecting a child connector to remove a parent's detection criterion or compute — object-arrays only append; restructure the hierarchy instead.
  • Chaining constants or embedding ${var::} in a constant value — substitution is a single pass.
  • Declaring a variable without defaultValue, leaving ${var::name} unresolved for users who force the connector without configuration.
  • Forgetting to whitelist a command in sudoCommands while using %{SUDO:...} — the macro silently disappears and the command runs unprivileged.
  • Duplicating metric definitions locally instead of extending the right semconv/* dictionary.
extends constants variables translations sudoCommands header connector inheritance reuse metricshub community connector hardware system
Links:
  • [1] references-and-expressions.html
  • [2] mapping-metrics-semconv.html
  • [3] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/MIB2-header/MIB2-header.yaml
  • [4] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/MIB2/MIB2.yaml
  • [5] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/LinuxNetwork/LinuxNetwork-header/LinuxNetwork-header.yaml
  • [6] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/LinuxNetwork/LinuxIPNetwork/LinuxIPNetwork.yaml
  • [7] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/system/LinuxProcess/LinuxProcess.yaml
  • [8] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/system/LinuxService/LinuxService.yaml
  • [9] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/system/LinuxFile/LinuxFile.yaml
  • [10] computes/translate.html
  • [11] computes/array-translate.html
  • [12] computes/translate-per-bit.html
  • [13] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/lmsensors/lmsensors.yaml
  • [14] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/LinuxMultipath/LinuxMultipath.yaml
  • [15] https://github.com/metricshub/community-connectors/blob/main/src/main/connector/hardware/SmartMonLinux/SmartMonLinux.yaml
Searching...
No results.