From 75aa4985eb7930fca66618674add4cb24020bc40 Mon Sep 17 00:00:00 2001 From: Brandon Johnson Date: Thu, 31 Oct 2024 10:32:53 -0400 Subject: [PATCH] Add message about available components to AgentDetails (#201) This PR adds a new ComponentDetails type that allows agents to communicate metadata relating to the components available in the agent. --- proto/opamp.proto | 49 +++++++++++++ specification.md | 181 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) diff --git a/proto/opamp.proto b/proto/opamp.proto index 44f9dc3..0e7d8f8 100644 --- a/proto/opamp.proto +++ b/proto/opamp.proto @@ -91,6 +91,10 @@ message AgentToServer { // A custom message sent from an Agent to the Server. // Status: [Development] CustomMessage custom_message = 13; + + // A message indicating the components that are available for configuration on the agent. + // Status: [Development] + AvailableComponents available_components = 14; } enum AgentToServerFlags { @@ -145,6 +149,41 @@ message CertificateRequest { bytes csr = 1; } +// AvailableComponents contains metadata relating to the components included +// within the agent. +// status: [Development] +message AvailableComponents { + // A map of a unique component ID to details about the component. + // This may be omitted from the message if the server has not + // explicitly requested it be sent by setting the ReportAvailableComponents + // flag in the previous ServerToAgent message. + map components = 1; + + // Agent-calculated hash of the components. + // This hash should be included in every AvailableComponents message. + bytes hash = 2; + } + +message ComponentDetails { + // Extra key/value pairs that may be used to describe the component. + // The key/value pairs are according to semantic conventions, see: + // https://opentelemetry.io/docs/specs/semconv/ + // + // For example, you may use the "code" semantic conventions to + // report the location of the code for a specific component: + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/code/ + // + // Or you may use the "vcs" semantic conventions to report the + // repository the component may be a part of: + // https://opentelemetry.io/docs/specs/semconv/attributes-registry/vcs/ + repeated KeyValue metadata = 1; + + // A map of component ID to sub components details. It can nest as deeply as needed to + // describe the underlying system. + map sub_component_map = 2; +} + + message ServerToAgent { // Agent instance uid. MUST match the instance_uid field in AgentToServer message. // Used for multiplexing messages from/to multiple agents using one message stream. @@ -212,6 +251,13 @@ enum ServerToAgentFlags { // AgentToServer.sequence_num values. // The Server asks the Agent to report full status. ServerToAgentFlags_ReportFullState = 0x00000001; + + // ReportAvailableComponents flag can be used by the server if the Agent did + // not include the full AvailableComponents message, but only the hash. + // If this flag is specified, the agent will populate available_components.components + // with a full description of the agent's components. + // Status: [Development] + ServerToAgentFlags_ReportAvailableComponents = 0x00000002; } enum ServerCapabilities { @@ -663,6 +709,9 @@ enum AgentCapabilities { // know the configured interval and should not make assumptions about it. // Status: [Development] AgentCapabilities_ReportsHeartbeat = 0x00002000; + // The agent will report AvailableComponents via the AgentToServer.available_components field. + // Status: [Development] + AgentCapabilities_ReportsAvailableComponents = 0x00004000; // Add new capabilities here, continuing with the least significant unused bit. } diff --git a/specification.md b/specification.md index 806b69b..511a372 100644 --- a/specification.md +++ b/specification.md @@ -40,6 +40,7 @@ Status: [Beta] - [AgentToServer.connection_settings_request](#agenttoserverconnection_settings_request) - [AgentToServer.custom_capabilities](#agenttoservercustom_capabilities) - [AgentToServer.custom_message](#agenttoservercustom_message) + - [AgentToServer.available_components](#agenttoserveravailable_components) + [ServerToAgent Message](#servertoagent-message) - [ServerToAgent.instance_uid](#servertoagentinstance_uid) - [ServerToAgent.error_response](#servertoagenterror_response) @@ -173,6 +174,16 @@ Status: [Beta] * [Agent Connection](#agent-connection-1) * [FindServices](#findservices) * [FindServicesResponse](#findservicesresponse) + * [AvailableComponents Message](#availablecomponents-message) + + [AvailableComponents.components](#availablecomponentscomponents) + - [Examples](#examples-1) + * [OpenTelemetry Collector](#opentelemetry-collector) + * [Fluent Bit](#fluent-bit) + + [AvailableComponents.hash](#availablecomponentshash) + + [Initial Handshake](#initial-handshake) + + [ComponentDetails Message](#componentdetails-message) + - [ComponentDetails.metadata](#componentdetailsmetadata) + - [ComponentDetails.sub_component_map](#componentdetailssub_component_map) - [Connection Management](#connection-management) * [Establishing Connection](#establishing-connection) * [Closing Connection](#closing-connection) @@ -505,6 +516,7 @@ message AgentToServer { ConnectionSettingsRequest connection_settings_request = 11; // Status: [Development] CustomCapabilities custom_capabilities = 12; // Status: [Development] CustomMessage custom_message = 13; // Status: [Development] + AvailableComponents available_components = 14; // Status: [Development] } ``` @@ -683,6 +695,15 @@ A custom message sent from an Agent to the Server. See [CustomMessage](#custommessage) message for details. +##### AgentToServer.available_components + +Status: [Development] + +A message listing the components available in the Agent. This field SHOULD be +reported if and only if the ReportsAvailableComponents capability is set. + +See [AvailableComponents](#availablecomponents-message) message for details. + #### ServerToAgent Message The body of the WebSocket message or HTTP response body is a binary serialized @@ -2870,6 +2891,166 @@ CustomMessage { } ``` +### AvailableComponents Message + +Status: [Development] + +Each Agent may be composed of multiple sub-components. These components may have +their own associated metadata. The AvailableComponents message allows the Agent +to inform the OpAMP server about which components the Agent contains. + +The AvailableComponents message has the following structure: + +```protobuf +message AvailableComponents { + map components = 1; + bytes hash = 2; + } +``` + +#### AvailableComponents.components + +The components field contains a map of a unique ID +to a [ComponentsDetails](#componentdetails-message) message. +This field may be omitted from the message if the OpAMP server has not explicitly +requested it by setting the ReportAvailableComponents flag in the preceding +ServerToAgent message. + +##### Examples + +###### OpenTelemetry Collector + +Here is an example of how ComponentDetails could hold information regarding the included +components for a custom build of the [OpenTelemetry Collector](https://github.com/open-telemetry/opentelemetry-collector): + +```jsonc +{ + "receivers": { + "sub_component_map": { + "hostmetrics": { + "metadata": { + "code.namespace": "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/hostmetricsreceiver@v0.107.0", + } + } + } + }, + "processors": { + "sub_component_map": { + "batch": { + "metadata": { + "code.namespace": "go.opentelemetry.io/collector/processor/batchprocessor@v0.107.0" + } + }, + "transform": { + "metadata": { + "code.namespace": "github.com/open-telemetry/opentelemetry-collector-contrib/processor/transformprocessor@v0.107.0" + } + }, + } + }, + "exporters": { + "sub_component_map": { + "nop": { + "metadata": { + "code.namespace": "go.opentelemetry.io/collector/exporter/nopexporter@v0.107.0" + } + } + } + } + // ... Component list continues for extensions and collectors ... +} +``` + +###### Fluent Bit + +Here's an example of how Fluent Bit could report what components it has available. + +```jsonc +{ + "input": { + "sub_component_map": { + "tail": {} + } + }, + "parser": { + "sub_component_map": { + "json": {} + } + }, + "filter": { + "sub_component_map": { + "lua": {}, + "modify": {} + } + }, + "output": { + "sub_component_map": { + "null": {}, + "file": {}, + } + } +} +``` + +#### AvailableComponents.hash + +The agent-calculated hash of the components field. The agent MUST include this hash +if it has the ability to report the components it has available. +Its format is determined by the agent. +The hash SHOULD be the same for any agent that has the same set of components. + +#### Initial Handshake + +In order to reduce the amount of data transmitted, the AvailableComponents message +does not initially contain the entire components map. Instead, the AvailableComponents +message will have the agent computed hash set, with an empty map for components. + +The initial AgentToServer message SHOULD contain the AvailableComponents message +with just the agent computed hash set. + +The OpAMP server may use this hash to determine whether it remembers the set of +AvailableComponents or not. If the hash is not found on the OpAMP server, the server +may request for the full components map to be reported by setting the ReportAvailableComponents +flag in the ServerToAgent message. If this flag is specified, then the Agent will +populate the components field with a full description of the available components. + +The server may then optionally persist the components for this hash, so that the +server does not need to request them again on subsequent connects. + +The AvailableComponents message is also subject to [status compression](#agent-status-compression), +and may be omitted if the hash has not changed from its previous value. + +#### ComponentDetails Message + +The ComponentDetails messaged describes a component of the Agent. + +The structure of ComponentDetails DOES NOT need to be a 1-to-1 match with +the ComponentHealth structure. ComponentHealth generally refers to currently running instances of +components, while ComponentDetails refers to the available types of components, +which may not be necessarily running currently. It is also possible that the same component +type may have more than one running instance. + +The ComponentDetails message has the following structure: + +```protobuf +message ComponentDetails { + repeated KeyValue metadata = 1; + map sub_component_map = 2; +} +``` + +##### ComponentDetails.metadata + +Extra key/value pairs that may be used to describe the component. + +The key/value pairs are SHOULD conform to semantic conventions where applicable, see +the [OpenTelemetry Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/) for more information. + +##### ComponentDetails.sub_component_map + +A map of unique component ID to sub component details. It can nest as deeply as needed to +describe the underlying system. + ## Connection Management ### Establishing Connection