diff --git a/src/OpenTelemetry.OpAmp.Client/.publicApi/PublicAPI.Unshipped.txt b/src/OpenTelemetry.OpAmp.Client/.publicApi/PublicAPI.Unshipped.txt index 175e983429..e1a1cde8ce 100644 --- a/src/OpenTelemetry.OpAmp.Client/.publicApi/PublicAPI.Unshipped.txt +++ b/src/OpenTelemetry.OpAmp.Client/.publicApi/PublicAPI.Unshipped.txt @@ -4,6 +4,12 @@ OpenTelemetry.OpAmp.Client.Messages.AgentConfigFile OpenTelemetry.OpAmp.Client.Messages.AgentConfigFile.Body.get -> System.ReadOnlySpan OpenTelemetry.OpAmp.Client.Messages.AgentConfigFile.ContentType.get -> string? OpenTelemetry.OpAmp.Client.Messages.AgentConfigFile.Name.get -> string! +OpenTelemetry.OpAmp.Client.Messages.CustomCapabilitiesMessage +OpenTelemetry.OpAmp.Client.Messages.CustomCapabilitiesMessage.Capabilities.get -> System.Collections.Generic.ICollection! +OpenTelemetry.OpAmp.Client.Messages.CustomMessageMessage +OpenTelemetry.OpAmp.Client.Messages.CustomMessageMessage.Capability.get -> string! +OpenTelemetry.OpAmp.Client.Messages.CustomMessageMessage.Data.get -> System.ReadOnlySpan +OpenTelemetry.OpAmp.Client.Messages.CustomMessageMessage.Type.get -> string! OpenTelemetry.OpAmp.Client.Messages.OpAmpMessage OpenTelemetry.OpAmp.Client.Messages.OpAmpMessage.OpAmpMessage() -> void OpenTelemetry.OpAmp.Client.Messages.RemoteConfigMessage diff --git a/src/OpenTelemetry.OpAmp.Client/CHANGELOG.md b/src/OpenTelemetry.OpAmp.Client/CHANGELOG.md index 01f9dd0fd7..bfb60c4d74 100644 --- a/src/OpenTelemetry.OpAmp.Client/CHANGELOG.md +++ b/src/OpenTelemetry.OpAmp.Client/CHANGELOG.md @@ -18,6 +18,9 @@ * Add settings for remote configuration and update advertised capabilities. ([#3618](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3618)) +* Expose public `CustomCapabilitiesMessage` and `CustomMessageMessage`. + ([#3681](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3681)) + ## 0.1.0-alpha.3 Released 2025-Nov-13 diff --git a/src/OpenTelemetry.OpAmp.Client/Internal/Messages/CustomCapabilitiesMessage.cs b/src/OpenTelemetry.OpAmp.Client/Internal/Messages/CustomCapabilitiesMessage.cs deleted file mode 100644 index 8ea8f77cc2..0000000000 --- a/src/OpenTelemetry.OpAmp.Client/Internal/Messages/CustomCapabilitiesMessage.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -using OpAmp.Proto.V1; -using OpenTelemetry.OpAmp.Client.Messages; - -namespace OpenTelemetry.OpAmp.Client.Internal.Listeners.Messages; - -internal class CustomCapabilitiesMessage : OpAmpMessage -{ - public CustomCapabilitiesMessage(CustomCapabilities customCapabilities) - { - this.CustomCapabilities = customCapabilities; - } - - public CustomCapabilities CustomCapabilities { get; set; } -} diff --git a/src/OpenTelemetry.OpAmp.Client/Internal/Messages/CustomMessageMessage.cs b/src/OpenTelemetry.OpAmp.Client/Internal/Messages/CustomMessageMessage.cs deleted file mode 100644 index 5193d53382..0000000000 --- a/src/OpenTelemetry.OpAmp.Client/Internal/Messages/CustomMessageMessage.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -using OpAmp.Proto.V1; -using OpenTelemetry.OpAmp.Client.Messages; - -namespace OpenTelemetry.OpAmp.Client.Internal.Listeners.Messages; - -internal class CustomMessageMessage : OpAmpMessage -{ - public CustomMessageMessage(CustomMessage customMessage) - { - this.CustomMessage = customMessage; - } - - public CustomMessage CustomMessage { get; set; } -} diff --git a/src/OpenTelemetry.OpAmp.Client/Messages/Custom/CustomCapabilitiesMessage.cs b/src/OpenTelemetry.OpAmp.Client/Messages/Custom/CustomCapabilitiesMessage.cs new file mode 100644 index 0000000000..01bfe71bb1 --- /dev/null +++ b/src/OpenTelemetry.OpAmp.Client/Messages/Custom/CustomCapabilitiesMessage.cs @@ -0,0 +1,22 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using OpAmp.Proto.V1; + +namespace OpenTelemetry.OpAmp.Client.Messages; + +/// +/// Represents an OpAMP server-to-agent custom capabilities message. +/// +public class CustomCapabilitiesMessage : OpAmpMessage +{ + internal CustomCapabilitiesMessage(CustomCapabilities customCapabilities) + { + this.Capabilities = [.. customCapabilities.Capabilities]; + } + + /// + /// Gets the collection of custom capabilities. + /// + public ICollection Capabilities { get; } +} diff --git a/src/OpenTelemetry.OpAmp.Client/Messages/Custom/CustomMessageMessage.cs b/src/OpenTelemetry.OpAmp.Client/Messages/Custom/CustomMessageMessage.cs new file mode 100644 index 0000000000..019f88498d --- /dev/null +++ b/src/OpenTelemetry.OpAmp.Client/Messages/Custom/CustomMessageMessage.cs @@ -0,0 +1,38 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Google.Protobuf; +using OpAmp.Proto.V1; + +namespace OpenTelemetry.OpAmp.Client.Messages; + +/// +/// Represents an OpAMP server-to-agent custom message message. +/// +public class CustomMessageMessage : OpAmpMessage +{ + private readonly ByteString data; + + internal CustomMessageMessage(CustomMessage customMessage) + { + this.data = customMessage.Data; + + this.Capability = customMessage.Capability; + this.Type = customMessage.Type; + } + + /// + /// Gets the capability associated with custom message. + /// + public string Capability { get; } + + /// + /// Gets the type of custom message. + /// + public string Type { get; } + + /// + /// Gets the data of custom message. + /// + public ReadOnlySpan Data => this.data.Span; +} diff --git a/test/OpenTelemetry.OpAmp.Client.Tests/FrameProcessorTests.cs b/test/OpenTelemetry.OpAmp.Client.Tests/FrameProcessorTests.cs index cabe49c77e..ff6380f05d 100644 --- a/test/OpenTelemetry.OpAmp.Client.Tests/FrameProcessorTests.cs +++ b/test/OpenTelemetry.OpAmp.Client.Tests/FrameProcessorTests.cs @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System.Text; using OpenTelemetry.OpAmp.Client.Internal; using OpenTelemetry.OpAmp.Client.Tests.Mocks; using OpenTelemetry.OpAmp.Client.Tests.Tools; @@ -21,7 +22,14 @@ public void FrameProcessor_Subscribe() processor.OnServerFrame(mockFrame.Frame.ToSequence()); var message = Assert.Single(listener.Messages); - Assert.Equal(mockFrame.ExptectedContent, message.CustomMessage.Data.ToStringUtf8()); + var messageContent = +#if NET + Encoding.UTF8.GetString(message.Data); +#else + Encoding.UTF8.GetString([.. message.Data]); +#endif + + Assert.Equal(mockFrame.ExptectedContent, messageContent); } [Fact] diff --git a/test/OpenTelemetry.OpAmp.Client.Tests/Messages/CustomCapabilitiesMessageTests.cs b/test/OpenTelemetry.OpAmp.Client.Tests/Messages/CustomCapabilitiesMessageTests.cs new file mode 100644 index 0000000000..d851c7812d --- /dev/null +++ b/test/OpenTelemetry.OpAmp.Client.Tests/Messages/CustomCapabilitiesMessageTests.cs @@ -0,0 +1,49 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using Xunit; + +namespace OpenTelemetry.OpAmp.Client.Tests.Messages; + +public class CustomCapabilitiesMessageTests +{ + private const string Capability1Name = "Capability1"; + private const string Capability2Name = "Capability2"; + + [Fact] + public void Constructor_WithValidCapabilities_InitializesCapabilities() + { + // Arrange + var customCapabilities = this.CreateCustomCapabilities(); + + // Act + var customCapabilitiesMessage = new Client.Messages.CustomCapabilitiesMessage(customCapabilities); + + // Assert + Assert.Equal(2, customCapabilitiesMessage.Capabilities.Count); + Assert.True(customCapabilitiesMessage.Capabilities.Contains(Capability1Name)); + Assert.True(customCapabilitiesMessage.Capabilities.Contains(Capability2Name)); + } + + [Fact] + public void Constructor_WithEmptyCapabilities_InitializesEmptyCapabilitiesCollection() + { + // Arrange + var customCapabilities = new global::OpAmp.Proto.V1.CustomCapabilities(); + + // Act + var customCapabilitiesMessage = new Client.Messages.CustomCapabilitiesMessage(customCapabilities); + + // Assert + Assert.Empty(customCapabilitiesMessage.Capabilities); + } + + private global::OpAmp.Proto.V1.CustomCapabilities CreateCustomCapabilities() + { + var capabilities = new global::OpAmp.Proto.V1.CustomCapabilities(); + capabilities.Capabilities.Add(Capability1Name); + capabilities.Capabilities.Add(Capability2Name); + + return capabilities; + } +} diff --git a/test/OpenTelemetry.OpAmp.Client.Tests/Messages/CustomMessageMessageTests.cs b/test/OpenTelemetry.OpAmp.Client.Tests/Messages/CustomMessageMessageTests.cs new file mode 100644 index 0000000000..ab8037a60b --- /dev/null +++ b/test/OpenTelemetry.OpAmp.Client.Tests/Messages/CustomMessageMessageTests.cs @@ -0,0 +1,44 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +using System.Text; +using Google.Protobuf; +using Xunit; + +namespace OpenTelemetry.OpAmp.Client.Tests.Messages; + +public class CustomMessageMessageTests +{ + private const string CapabilityName = "Capability1"; + private const string TypeName = "CustomMessageType"; + private const string DataString = "Custom Message Data Example"; + + [Fact] + public void Constructor_WithValidMessage_InitializesCustomMessage() + { + // Arrange + var customMessage = this.CreateCustomMessagesMessage(); + + // Act + var customMessageMessage = new Client.Messages.CustomMessageMessage(customMessage); + + // Assert + Assert.Equal(CapabilityName, customMessageMessage.Capability); + Assert.Equal(TypeName, customMessageMessage.Type); +#if NET + Assert.Equal(DataString, Encoding.UTF8.GetString(customMessageMessage.Data)); +#else + Assert.Equal(DataString, Encoding.UTF8.GetString([.. customMessageMessage.Data])); +#endif + } + + private global::OpAmp.Proto.V1.CustomMessage CreateCustomMessagesMessage() + { + return new global::OpAmp.Proto.V1.CustomMessage + { + Capability = CapabilityName, + Type = TypeName, + Data = ByteString.CopyFromUtf8(DataString), + }; + } +} diff --git a/test/OpenTelemetry.OpAmp.Client.Tests/Mocks/MockListener.cs b/test/OpenTelemetry.OpAmp.Client.Tests/Mocks/MockListener.cs index b6670fbdcf..fe3344c2ed 100644 --- a/test/OpenTelemetry.OpAmp.Client.Tests/Mocks/MockListener.cs +++ b/test/OpenTelemetry.OpAmp.Client.Tests/Mocks/MockListener.cs @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 using System.Collections.Concurrent; -using OpenTelemetry.OpAmp.Client.Internal.Listeners.Messages; using OpenTelemetry.OpAmp.Client.Listeners; +using OpenTelemetry.OpAmp.Client.Messages; namespace OpenTelemetry.OpAmp.Client.Tests.Mocks; diff --git a/test/OpenTelemetry.OpAmp.Client.Tests/PlainHttpTransportTests.cs b/test/OpenTelemetry.OpAmp.Client.Tests/PlainHttpTransportTests.cs index f3fc4dd71c..cc6d4af396 100644 --- a/test/OpenTelemetry.OpAmp.Client.Tests/PlainHttpTransportTests.cs +++ b/test/OpenTelemetry.OpAmp.Client.Tests/PlainHttpTransportTests.cs @@ -5,6 +5,7 @@ using System.Net.Http; #endif +using System.Text; using OpenTelemetry.OpAmp.Client.Internal; using OpenTelemetry.OpAmp.Client.Internal.Transport.Http; using OpenTelemetry.OpAmp.Client.Settings; @@ -40,7 +41,12 @@ public async Task PlainHttpTransport_SendReceiveCommunication(bool useSmallPacke // Assert var serverReceivedFrames = opAmpServer.GetFrames(); var clientReceivedFrames = mockListener.Messages; - var receivedTextData = clientReceivedFrames.First().CustomMessage.Data.ToStringUtf8(); + var receivedTextData = +#if NET + Encoding.UTF8.GetString(clientReceivedFrames.First().Data); +#else + Encoding.UTF8.GetString([.. clientReceivedFrames.First().Data]); +#endif var frame = Assert.Single(serverReceivedFrames); Assert.Equal(mockFrame.Uid, frame.InstanceUid); diff --git a/test/OpenTelemetry.OpAmp.Client.Tests/WsTransportTest.cs b/test/OpenTelemetry.OpAmp.Client.Tests/WsTransportTest.cs index 98713e3718..b2360497fa 100644 --- a/test/OpenTelemetry.OpAmp.Client.Tests/WsTransportTest.cs +++ b/test/OpenTelemetry.OpAmp.Client.Tests/WsTransportTest.cs @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System.Text; using OpenTelemetry.OpAmp.Client.Internal; using OpenTelemetry.OpAmp.Client.Internal.Transport.WebSocket; using OpenTelemetry.OpAmp.Client.Tests.Mocks; @@ -42,7 +43,12 @@ public async Task WsTransport_SendReceiveCommunication(bool useSmallPackets) // Assert var serverReceivedFrames = opAmpServer.GetFrames(); var clientReceivedFrames = mockListener.Messages; - var receivedTextData = clientReceivedFrames.First().CustomMessage.Data.ToStringUtf8(); + var receivedTextData = +#if NET + Encoding.UTF8.GetString(clientReceivedFrames.First().Data); +#else + Encoding.UTF8.GetString([.. clientReceivedFrames.First().Data]); +#endif Assert.Single(serverReceivedFrames); Assert.Equal(mockFrame.Uid, serverReceivedFrames.First().InstanceUid);