-
Notifications
You must be signed in to change notification settings - Fork 30
/
specification.md
2612 lines (1863 loc) · 112 KB
/
specification.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<h1>OpAMP: Open Agent Management Protocol</h1>
Author: Tigran Najaryan, Splunk
Contributors: Chris Green, Splunk
Status: Early Draft (see Open Questions).
Date: September 2021
Note: address all TODO and Open Questions before considering the document ready for final review.
Note 2: this document requires a simplification pass to reduce the scope, size and complexity.
[TOC]
<h1 id="introduction">Introduction</h1>
Open Agent Management Protocol (OpAMP) is a network protocol for remote
management of large fleets of data collection Agents.
OpAMP allows Agents to report their status to and receive configuration from a
Server and to receive addons and agent installation package updates from the
server. The protocol is vendor-agnostic, so the Server can remotely monitor and
manage a fleet of different Agents that implement OpAMP, including a fleet of
mixed agents from different vendors.
OpAMP supports the following functionality:
* Remote configuration of the agents.
* Status reporting. The protocol allows the agent to report the properties of
the agent such as its type and version or the operating system type and
version it runs on. The status reporting also allows the management server to
tailor the remote configuration to individual agents or types of agents.
* Agent's own telemetry reporting to an
[OTLP](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md)-compatible
backend to monitor agent's process metrics such as CPU or RAM usage, as well
as agent-specific metrics such as rate of data processing.
* Management of downloadable agent-specific addons.
* Secure auto-updating capabilities (both upgrading and downgrading of the
agents).
* Connection credentials management, including client-side TLS certificate
revocation and rotation.
The functionality listed above enables a 'single pane of glass' management view
of a large fleet of mixed agents (e.g. OpenTelemetry Collector, Fluentd, etc).
<h1 id="communication-model">Communication Model</h1>
The OpAMP Server manages Agents that implement the client-side of OpAMP
protocol. The Agents can optionally send their own telemetry to an OTLP
destination when directed so by the OpAMP Server. The Agents likely also connect
to other destinations, where they send the data they collect:
```
┌────────────┬────────┐ ┌─────────┐
│ │ OpAMP │ OpAMP │ OpAMP │
│ │ ├──────────►│ │
│ │ Client │ │ Server │
│ └────────┤ └─────────┘
│ │
│ ┌────────┤ ┌─────────┐
│ │OTLP │ OTLP/HTTP │ OTLP │
│ Agent │ ├──────────►│ │
│ │Exporter│ │ Receiver│
│ └────────┤ └─────────┘
│ │
│ ┌────────┤
│ │Other ├──────────► Other
│ │Clients ├──────────► Destinations
└────────────┴────────┘
```
This specification defines the OpAMP network protocol and the expected behavior
for OpAMP Agents and Servers. The OTLP/HTTP protocol is
[specified here](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/otlp.md).
The protocols used by the Agent to connect to other destinations are agent
type-specific and are outside the scope of this specification.
OpAMP protocol uses [WebSocket](https://datatracker.ietf.org/doc/html/rfc6455)
as the transport. The Agent is a WebSocket client and the Server is a WebSocket
server. The Agent and the Server communicate using binary data WebSocket
messages. The payload of each WebSocket message is a
[binary serialized Protobuf](https://developers.google.com/protocol-buffers/docs/encoding)
message. The Agent sends AgentToServer Protobuf messages and the Server sends
ServerToAgent Protobuf messages:
```
┌───────────────┐ ┌──────────────┐
│ │ AgentToServer │ │
│ ├───────────────────────►│ │
│ Agent │ │ Server │
│ │ ServerToAgent │ │
│ │◄───────────────────────┤ │
└───────────────┘ └──────────────┘
```
Typically a single Server accepts WebSocket connections from many agents. Agents
are identified by self-assigned globally unique instance identifiers (or
instance_uid for short). The instance_uid is recorded in each message sent from
the Agent to the Server and from the Server to the Agent.
The default URL path for the initial WebSocket's HTTP connection is /v1/opamp.
The URL path MAY be configurable on the Agent and on the Server.
OpAMP is an asynchronous, full-duplex message exchange protocol. The order and
sequence of messages exchanged by the Agent and the Server is defined for each
particular capability in the corresponding section of this specification.
The sequence is normally started by an initiating message triggered by some
external event. For example after the connection is established the Agent sends
a StatusReport message. In this case the "connection established" is the
triggering event and the StatusReport is the initiating message.
Both the Agent and the Server may begin a sequence by sending an initiating
message.
The initiating message may trigger the recipient to send one or more messages
back, which in turn may trigger messages in the opposite direction and so on.
This exchange of messages in both directions continues until the sequence is
over because the goal of the exchange is achieved or the sequence failed with an
error.
Note that the same message may in some cases be the initiating message of the
sequence and in some other cases it may be triggered in response to receiving
some other message. Unlike other protocols in OpAMP there is no strict
separation between "request" and "response" messages types. The role of the
message depends on how the sequence is triggered.
For example the StatusReport message may be the initiating message sent by the
Agent when the Agent connects to the Server for the first time. The StatusReport
message may also be sent by the Agent in response to the Server making a remote
configuration offer to the Agent and Agent reporting that it accepted the
configuration.
See sections under the [Operation](#operation) section for the details of the
message sequences.
## AgentToServer Message
The body of the WebSocket message is a binary serialized Protobuf message
AgentToServer as defined below (all messages in this document are specified in
[Protobuf 3 language](https://developers.google.com/protocol-buffers/docs/proto3)):
```protobuf
message AgentToServer {
string instance_uid = 1;
StatusReport status_report = 2;
AgentAddonStatuses addon_statuses = 3;
AgentInstallStatus agent_install_status = 4;
AgentDisconnect agent_disconnect = 5;
}
```
One or more of the fields (status_report, addon_statuses, agent_install_status,
agent_disconnect) MUST be set. The Server should process each field as it is
described in the corresponding [Operation](#operation) section.
#### instance_uid
The instance_uid field is a globally unique identifier of the running instance
of the Agent. The Agent SHOULD self-generate this identifier and make the best
effort to avoid creating an identifier that may conflict with identifiers
created by other Agents. The instance_uid SHOULD remain unchanged for the
lifetime of the agent process. The recommended format for the instance_uid is
[ULID](https://github.com/ulid/spec).
#### status_report
The status of the Agent. MUST be set in the first AgentToServer message that the
Agent sends after connecting. This field SHOULD be unset if this information is
unchanged since the last AgentToServer message for this agent was sent in the
stream.
#### addon_statuses
The list of the agent addons, including addon statuses. This field SHOULD be
unset if this information is unchanged since the last AgentToServer message for
this agent was sent in the stream.
#### agent_install_status
The status of the installation operation that was previously offered by the
server. This field SHOULD be unset if the installation status is unchanged since
the last AgentToServer message.
#### agent_disconnect
AgentDisconnect MUST be set in the last AgentToServer message sent from the
agent to the server.
## ServerToAgent Message
The body of the WebSocket message is a binary serialized Protobuf message
ServerToAgent.
ServerToAgent message is sent from the Server to the Agent either in response to
the AgentToServer message or when the Server has data to deliver to the Agent.
If the Server receives an AgentToServer message and the Server has no data to
send back to the Agent then ServerToAgent message will still be sent, but all
fields except instance_uid will be unset (in that case ServerToAgent serves
simply as an acknowledgement of receipt).
Upon receiving a ServerToAgent message the Agent MUST process it. The processing
that needs to be performed depends on what fields in the message are set. For
details see links to the corresponding sections of this specification from the
field descriptions below.
As a result of this processing the Agent may need to send status reports to the
Server. The Agent is free to perform all the processing of the ServerToAgent
message completely and then send one status report or it may send multiple
status reports as it processes the portions of ServerToAgent message to indicate
the progress (see e.g. [Addon processing](#downloading-addons)). Multiple status
reports may be desirable when processing takes a long time, in which case the
status reports allow the Server to stay informed.
Note that the Server will reply to each status report with a ServerToAgent
message (or with an ServerErrorResponse if something goes wrong). These
ServerToAgent messages may have the same content as the one received earlier or
the content may be different if the situation on the Server has changed. The
Agent SHOULD be ready to process these additional ServerToAgent messages as they
arrive.
The Agent SHOULD NOT send any status reports at all if the status of the Agent
did not change as a result of processing.
The ServerToAgent message has the following structure:
```protobuf
message ServerToAgent {
string instance_uid = 1;
ServerErrorResponse error_response = 2;
AgentRemoteConfig remote_config = 3;
ConnectionSettingsOffers connection_settings = 4;
AddonsAvailable addons_available = 5;
AgentPackageAvailable agent_package_available = 6;
Flags flags = 7;
ServerCapabilities capabilities = 8;
}
```
#### instance_uid
The Agent instance identifier. MUST match the instance_uid field previously
received in the AgentToServer message. When communication with multiple Agents
is multiplexed into one WebSocket connection (for example when a terminating
proxy is used) the instance_uid field allows to distinguish which Agent the
ServerToAgent message is addressed to.
#### error_response
error_response is set if the Server wants to indicate that something went wrong
during processing of an AgentToServer message. If error_response is set then all
other fields below must be unset and vice versa, if any of the fields below is
set then error_response must be unset.
#### remote_config
This field is set when the Server has a remote config offer for the Agent. See
[Configuration](#configuration) for details.
#### connection_settings
This field is set when the Server wants the Agent to change one or more of its
client connection settings (destination, headers, certificate, etc). See
[Connection Settings Management](#connection-settings-management) for details.
#### addons_available
This field is set when the Server has addons to offer to the Agent. See
[Addons](#addons) for details.
#### agent_package_available
This field is set when the server has a different version of an agent package
available for download. See [Agent Updates](#agent-package-updates) for details.
#### flags
Bit flags as defined by Flags bit masks.
Report* flags can be used by the server if the agent did not include the
particular bit of information in the last status report (which is an allowed
optimization) but the server does not have it (e.g. was restarted and lost
state).
```protobuf
enum Flags {
FlagsUnspecified = 0;
// Flags is a bit mask. Values below define individual bits.
// The server asks the agent to report effective config. This bit MUST NOT be
// set if the Agent indicated it cannot report effective config by setting
// the ReportsEffectiveConfig bit to 0 in StatusReport.capabilities field.
ReportEffectiveConfig = 0x00000001;
// The server asks the agent to report addon statuses. This bit MUST NOT be
// set if the Agent indicated it cannot report addon status by setting
// the ReportsAddonStatus bit to 0 in StatusReport.capabilities field.
ReportAddonStatus = 0x00000002;
}
```
#### capabilities
Bitmask of flags defined by ServerCapabilities enum. All bits that are not
defined in ServerCapabilities enum MUST be set to 0 by the Server. This allows
extending the protocol and the ServerCapabilities enum in the future such that
old Servers automatically report that they don't support the new capability.
This field MUST be set in the first ServerToAgent sent by the Server and MAY be
omitted in subsequent ServerToAgent messages by setting it to
UnspecifiedServerCapability value.
```protobuf
enum ServerCapabilities {
// The capabilities field is unspecified.
UnspecifiedServerCapability = 0;
// The Server can accept status reports. This bit MUST be set, since all Server
// MUST be able to accept status reports.
AcceptsStatus = 0x00000001;
// The Server can offer remote configuration to the Agent.
OffersRemoteConfig = 0x00000002;
// The Server can accept EffectiveConfig in StatusReport.
AcceptsEffectiveConfig = 0x00000004;
// The Server can offer Addons.
OffersAddons = 0x00000008;
// The Server can accept Addon status.
AcceptsAddonsStatus = 0x00000010;
// The Server can offer packages to install.
OffersAgentPackage = 0x00000020;
// The Server can accept the installation status of the package.
AcceptsAgentPackageStatus = 0x00000040;
// The Server can offer connection settings.
OffersConnectionSettings = 0x00000080;
// Add new capabilities here, continuing with the least significant unused bit.
}
```
<h2 id="servererrorresponse-message">ServerErrorResponse Message</h2>
The message has the following structure:
```protobuf
message ServerErrorResponse {
enum Type {
UNKNOWN = 0;
BAD_REQUEST = 1;
UNAVAILABLE = 2
}
Type type = 1;
string error_message = 2;
oneof Details {
RetryInfo retry_info = 3;
}
}
```
<h4 id="type">type</h4>
This field defines the type of the error that the Server encountered when trying
to process the Agent's request. Possible values are:
UNKNOWN: Unknown error. Something went wrong, but it is not known what exactly.
The error_message field may contain a description of the problem.
BAD_REQUEST: Only sent as a response to a previously received AgentToServer
message and indicates that the AgentToServer message was malformed. See
[Bad Request](#bad-request) processing.
UNAVAILABLE: The server is overloaded and unable to process the request. See
[Throttling](#throttling).
<h4 id="error_message">error_message</h4>
Error message, typically human readable.
<h4 id="retry_info">retry_info</h4>
Additional [RetryInfo](#throttling) message about retrying if type==UNAVAILABLE.
# Operation
<h2 id="status-reporting">Status Reporting</h2>
The Agent MUST send a status report:
* First time immediately after connecting to the Server. The status report MUST
be the first message sent by the Agent.
* Subsequently every time the status of the Agent changes.
The status report is sent as an AgentToServer message, where the [Body](#body)
field is set to [StatusReport](#statusreport-message) message.
The Server MUST respond to the status report by sending a
[ServerToAgent](#servertoagent-message) message.
If the status report processing failed then the
[error_response](#error_response) field MUST be set to ServerErrorResponse
message.
If the status report is processed successfully by the Server then the
[error_response](#error_response) field MUST be unset and the other fields can
be populated as necessary.
Here is the sequence diagram that shows how status reporting works (assuming
server-side processing is successful):
```
Agent Server
│ │
│ │
│ WebSocket Connect │
├──────────────────────────────────────►│
│ │
│ AgentToServer{StatusReport} │ ┌─────────┐
├──────────────────────────────────────►├──►│ │
│ │ │ Process │
│ ServerToAgent{} │ │ Status │
│◄──────────────────────────────────────┤◄──┤ │
│ │ └─────────┘
. ... .
│ AgentToServer{StatusReport} │ ┌─────────┐
├──────────────────────────────────────►├──►│ │
│ │ │ Process │
│ ServerToAgent{} │ │ Status │
│◄──────────────────────────────────────┤◄──┤ │
│ │ └─────────┘
│ │
```
Note that the status of the Agent may change as a result of receiving a message
from the Server. For example the Server may send a remote configuration to the
Agent. Once the Agent processes such a request the Agent's status changes (e.g.
the effective configuration of the Agent changes). Such status change should
result in the Agent sending a status report to the Server.
So, essentially in such cases the sequence of messages may look like this:
```
Agent Server
│ ServerToAgent{} │
┌───────┤◄──────────────────────────────────────┤
│ │ │
▼ │ │
┌────────┐ │ │
│Process │ │ │
│Received│ │ │
│Data │ │ │
└───┬────┘ │ │
│ │ │
│Status │ │
│Changed│ AgentToServer{StatusReport} │ ┌─────────┐
└──────►├──────────────────────────────────────►├──►│ │
│ │ │ Process │
│ ServerToAgent{} │ │ Status │
│◄──────────────────────────────────────┤◄──┤ │
│ │ └─────────┘
```
When the Agent receives a ServerToAgent message the Agent MUST NOT send a status
report unless processing of the message received from the Server resulted in
actual change of the Agent status (e.g. the configuration of the Agent has
changed). The sequence diagram in this case look like this:
```
Agent Server
│ ServerToAgent{} │
┌──────┤◄──────────────────────────────────────┤
│ │ │
▼ │ │
┌────────┐ │ │
│Process │ │ │
│Received│ │ │
│Data │ │ │
└───┬────┘ │ │
│ │ │
▼ │ │
No Status │ │
Changes │ │
│ │
│ │
```
Important: if the Agent does not follow these rules the operation may result in
an infinite loop of messages sent back and forth between the Agent and the
Server. TODO: add a section explaining how infinite oscillations between remote
config and status reporting are possible if an attribute is reported in the
status that can be changed via remote config and how to prevent it.
<h3 id="statusreport-message">StatusReport Message</h3>
StatusReport message has the following structure:
```protobuf
message StatusReport {
AgentDescription agent_description = 1;
EffectiveConfig effective_config = 2;
RemoteConfigStatus remote_config_status = 3;
AgentCapabilities capabilities = 4;
}
```
<h4 id="agent_description">agent_description</h4>
The description of the agent, its type, where it runs, etc. See
[AgentDescription](#agentdescription-message) message for details.
This field SHOULD be unset if no Agent description fields have changed since the
last StatusReport was sent.
<h4 id="effective_config">effective_config</h4>
The current effective configuration of the Agent. The effective configuration is
the one that is currently used by the Agent. The effective configuration may be
different from the remote configuration received from the Server earlier, e.g.
because the agent uses a local configuration instead (or in addition). See
[EffectiveConfig](#effectiveconfig-message) message for details.
This field SHOULD be unset if the effective configuration has not changed since
the last StatusReport message was sent.
<h4 id="remote_config_status">remote_config_status</h4>
The status of the remote config that was previously received from the server.
See [RemoteConfigStatus](#remoteconfigstatus-message) message for details.
This field SHOULD be unset if the remote config status is unchanged since the
last StatusReport message was sent.
#### capabilities
Bitmask of flags defined by AgentCapabilities enum. All bits that are not
defined in AgentCapabilities enum MUST be set to 0 by the Agent. This allows
extending the protocol and the AgentCapabilities enum in the future such that
old Agents automatically report that they don't support the new capability. This
field MUST be set in the first StatusReport sent by the Agent and MAY be omitted
in subsequent StatusReport messages by setting it to UnspecifiedAgentCapability
value.
```protobuf
enum AgentCapabilities {
// The capabilities field is unspecified.
UnspecifiedAgentCapability = 0;
// The Agent can report status. This bit MUST be set, since all Agents MUST
// report status.
ReportsStatus = 0x00000001;
// The Agent can accept remote configuration from the Server.
AcceptsRemoteConfig = 0x00000002;
// The Agent will report EffectiveConfig in StatusReport.
ReportsEffectiveConfig = 0x00000004;
// The Agent can accept Addon offers.
AcceptsAddons = 0x00000008;
// The Agent can report Addon status.
ReportsAddonsStatus = 0x00000010;
// The Agent can accept packages to install.
AcceptsAgentPackage = 0x00000020;
// The Agent can report the installation status of the package.
ReportsAgentPackageStatus = 0x00000040;
// The Agent can report own traces to the destination specified by
// the Server via ConnectionSettingsOffers.own_traces field.
ReportsOwnTraces = 0x00000080;
// The Agent can report own metrics to the destination specified by
// the Server via ConnectionSettingsOffers.own_metrics field.
ReportsOwnMetrics = 0x00000100;
// The Agent can report own logs to the destination specified by
// the Server via ConnectionSettingsOffers.own_logs field.
ReportsOwnLogs = 0x00000200;
// The can accept connections settings for OpAMP via
// ConnectionSettingsOffers.opamp field.
AcceptsOpAMPConnectionSettings = 0x00000400;
// The can accept connections settings for other destinations via
// ConnectionSettingsOffers.other_connections field.
AcceptsOtherConnectionSettings = 0x00000800;
// Add new capabilities here, continuing with the least significant unused bit.
}
```
<h3 id="agentdescription-message">AgentDescription Message</h3>
The AgentDescription message has the following structure:
```protobuf
message AgentDescription {
repeated KeyValue identifying_attributes = 1;
repeated KeyValue non_identifying_attributes = 2;
}
```
#### identifying_attributes
Attributes that identify the agent.
Keys/values are according to OpenTelemetry semantic conventions, see:
https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions
For standalone running Agents (such as OpenTelemetry Collector) the following
attributes SHOULD be specified:
- service.name should be set to a reverse FQDN that uniquely identifies the
agent type, e.g. "io.opentelemetry.collector"
- service.namespace if it is used in the environment where the Agent runs.
- service.version should be set to version number of the Agent build.
- service.instance.id should be set. It may be be set equal to the Agent's
instance uid (equal to ServerToAgent.instance_uid field) or any other value
that uniquely identifies the Agent in combination with other attributes.
- any other attributes that are necessary for uniquely identifying the Agent's
own telemetry.
The Agent SHOULD also include these attributes in the Resource of its own
telemetry. The combination of identifying attributes SHOULD be sufficient to
uniquely identify the Agent's own telemetry in the destination system to which
the Agent sends its own telemetry.
#### non_identifying_attributes
Attributes that do not necessarily identify the Agent but help describe where it
runs.
The following attributes SHOULD be included:
- os.type, os.version - to describe where the agent runs.
- host.* to describe the host the agent runs on.
- cloud.* to describe the cloud where the host is located.
- any other relevant Resource attributes that describe this agent and the
environment it runs in.
- any user-defined attributes that the end user would like to associate with
this agent.
<h3 id="effectiveconfig-message">EffectiveConfig Message</h3>
The EffectiveConfig message has the following structure:
```protobuf
message EffectiveConfig {
bytes hash = 1;
AgentConfigMap config_map = 2;
}
```
<h4 id="hash">hash</h4>
The hash of the effective config. The hash is calculated by the Agent from the
content of the effective config (from the names and content of all items in the
config_map field).
After establishing the OpAMP connection if the effective config did not change
since it was last reported during the previous connection sessions the Agent is
recommended to include only the hash field and omit the config_map field to save
bandwidth.
The Server SHOULD compare this hash with the last hash of effective config it
received from the Agent and if the hashes are different the Server SHOULD ask
the Agent to report its full effective config by sending a ServerToAgent message
with ReportEffectiveConfig flag set.
<h4 id="config_map">config_map</h4>
The effective config of the Agent. SHOULD be omitted if unchanged since last
reported.
MUST be set if the Agent has received the ReportEffectiveConfig flag in the
ServerToAgent message.
See AgentConfigMap message definition in the [Configuration](#configuration)
section.
<h3 id="remoteconfigstatus-message">RemoteConfigStatus Message</h3>
The RemoteConfigStatus message has the following structure:
```protobuf
message RemoteConfigStatus {
bytes last_remote_config_hash = 1;
enum Status {
// Remote config was successfully applied by the Agent.
APPLIED = 0;
// Agent is currently applying the remote config that it received earlier.
APPLYING = 1;
// Agent tried to apply the config received earlier, but it failed.
// See error_message for more details.
FAILED = 2;
}
Status status = 2;
string error_message = 3;
}
```
<h4 id="last_remote_config_hash">last_remote_config_hash</h4>
The hash of the remote config that was last received by this agent from the
management server. The server SHOULD compare this hash with the config hash it
has for the agent and if the hashes are different the server MUST include the
remote_config field in the response in the ServerToAgent message.
<h4 id="status">status</h4>
The status of the Agent's attempt to apply a previously received remote
configuration.
<h4 id="error_message">error_message</h4>
Optional error message if status==FAILED.
<h3 id="agentaddonstatuses-message">AgentAddonStatuses Message</h3>
The AgentAddonStatuses message describes the status of all addons that the agent
has or was offered. The message has the following structure:
```protobuf
message AgentAddonStatuses {
map<string, AgentAddonStatus> addons = 1;
bytes server_provided_all_addons_hash = 2;
}
```
<h4 id="addons">addons</h4>
A map of AgentAddonStatus messages, where the keys are addon names. The key MUST
match the name field of [AgentAddonStatus](#agentaddonstatus-message) message.
<h4 id="server_provided_all_addons_hash">server_provided_all_addons_hash</h4>
The aggregate hash of all addons that this Agent previously received from the
server via AddonsAvailable message.
The server SHOULD compare this hash to the aggregate hash of all addons that it
has for this Agent and if the hashes are different the server SHOULD send an
AddonsAvailable message to the agent.
<h3 id="agentaddonstatus-message">AgentAddonStatus Message</h3>
The AgentAddonStatus has the following structure:
```protobuf
message AgentAddonStatus {
string name = 1;
string agent_has_version = 2;
bytes agent_has_hash = 3;
string server_offered_version = 4;
bytes server_offered_hash = 5;
enum Status {
INSTALLED = 0;
INSTALLING = 1;
INSTALL_FAILED = 2;
}
Status status = 6;
string error_message = 7;
}
```
<h4 id="name">name</h4>
Addon name. MUST be always set and MUST match the key in the addons field of
AgentAddonStatuses message.
#### agent_has_version
The version of the addon that the Agent has.
MUST be set if the Agent has this addon.
MUST be empty if the Agent does not have this addon. This may be the case for
example if the addon was offered by the Server but failed to install and the
agent did not have this addon previously.
#### agent_has_hash
The hash of the addon that the Agent has.
MUST be set if the Agent has this addon.
MUST be empty if the Agent does not have this addon. This may be the case for
example if the addon was offered by the Server but failed to install and the
agent did not have this addon previously.
#### server_offered_version
The version of the addon that the server offered to the agent.
MUST be set if the installation of the addon is initiated by an earlier offer
from the server to install this addon.
MUST be empty if the Agent has this addon but it was installed locally and was
not offered by the server.
Note that it is possible for both agent_has_version and server_offered_version
fields to be set and to have different values. This is for example possible if
the agent already has a version of the addon successfully installed, the server
offers a different version, but the agent fails to install that version.
#### server_offered_hash
The hash of the addon that the server offered to the agent.
MUST be set if the installation of the addon is initiated by an earlier offer
from the server to install this addon.
MUST be empty if the Agent has this addon but it was installed locally and was
not offered by the server.
Note that it is possible for both agent_has_hash and server_offered_hash fields
to be set and to have different values. This is for example possible if the
agent already has a version of the addon successfully installed, the server
offers a different version, but the agent fails to install that version.
<h4 id="status">status</h4>
The status of this addon. The possible values are:
INSTALLED: Addon is successfully installed by the Agent. The error_message field
MUST NOT be set.
INSTALLING: Agent is currently downloading and installing the addon.
server_offered_hash field MUST be set to indicate the version that the agent is
installing. The error_message field MUST NOT be set.
INSTALL_FAILED: Agent tried to install the addon but installation failed.
server_offered_hash field MUST be set to indicate the version that the agent
tried to install. The error_message may also contain more details about the
failure.
<h4 id="error_message">error_message</h4>
An error message if the status is erroneous.
<h3 id="agentinstallstatus-message">AgentInstallStatus Message</h3>
This message contains the status of the last agent package install status
performed by the agent and has the following structure:
```protobuf
message AgentInstallStatus {
string server_offered_version = 1;
bytes server_offered_hash = 2;
enum Status {
INSTALLED = 0;
INSTALLING = 1;
INSTALL_FAILED = 2;
INSTALL_NO_PERMISSION = 3;
}
Status status = 3;
string error_message = 4;
}
```
<h4 id="server_offered_version">server_offered_version</h4>
The version field from the AgentPackageAvailable that the server offered to the
agent. MUST be set if the agent previously received an offer from the server to
install this agent.
<h4 id="server_offered_hash">server_offered_hash</h4>
The hash of the agent package file that the server offered to the agent. MUST be
set if the agent previously received an offer from the server to install this
agent.
<h4 id="status">status</h4>
The status of the agent package installation operation. The possible values are:
INSTALLED: Agent package was successfully installed. error_message MUST NOT be
set.
INSTALLING: Agent is currently downloading and installing the package.
server_offered_hash MUST be set to indicate the version that the agent is
installing. error_message MUST NOT be set.
INSTALL_FAILED: Agent tried to install the package but installation failed.
server_offered_hash MUST be set to indicate the package that the agent tried to
install. error_message may also contain more details about the failure.
INSTALL_NO_PERMISSION: Agent did not install the package because it is not
permitted to. This may be for example the case when operating system permissions
prevent the agent from self-updating or when self-updating is disabled by the
user. error_message may also contain more details about what exactly is not
permitted.
<h4 id="error_message">error_message</h4>
Optional human readable error message if the status is erroneous.
<h2 id="connection-settings-management">Connection Settings Management</h2>
OpAMP includes features that allow the Server to manage Agent's connection
settings for all of the destinations that the agent connects to.
The following diagram shows a typical Agent that is managed by OpAMP Servers,
sends its own telemetry to an OTLP backend and also connects to other
destinations to perform its work:
```
┌────────────┬────────┐ ┌─────────┐
│ │ OpAMP │ OpAMP │ OpAMP │
│ │ ├──────────►│ │
│ │ Client │ │ Server │
│ └────────┤ └─────────┘
│ │
│ ┌────────┤ ┌─────────┐
│ │OTLP │ OTLP/HTTP │OTLP │
│ Agent │ ├──────────►│Telemetry│
│ │Client │ │Backend │
│ └────────┤ └─────────┘
│ │
│ ┌────────┤
│ │Other ├──────────► Other
│ │ ├──────────►
│ │Clients ├──────────► Destinations
└────────────┴────────┘
```
When connecting to the OpAMP Server and to other destinations it is typically
expected that Agents will use some sort of header-based authorization mechanism
(e.g. an "Authorization" HTTP header or an access token in a custom header) and
optionally also client-side certificates for TLS connections (also known as
mutual TLS).
OpAMP protocol allows the Server to offer settings for each of these connections
and for the Agent to accept or reject such offers. This mechanism can be used to