[WcfClient] validate span attributes (#2743)
validate span attributes Co-authored-by: Chris Ventura <45495992+nrcventura@users.noreply.github.com>
This commit is contained in:
parent
818aa7e332
commit
9324d3d058
|
|
@ -0,0 +1,63 @@
|
|||
// <copyright file="WcfClientInstrumentation.cs" company="OpenTelemetry Authors">
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// </copyright>
|
||||
#if NETFRAMEWORK
|
||||
|
||||
using OpenTelemetry.Proto.Common.V1;
|
||||
using OpenTelemetry.Proto.Trace.V1;
|
||||
|
||||
namespace IntegrationTests;
|
||||
|
||||
internal static class WcfClientInstrumentation
|
||||
{
|
||||
public const string NetTcpBindingMessageVersion = "Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)";
|
||||
public const string HttpBindingMessageVersion = "Soap11 (http://schemas.xmlsoap.org/soap/envelope/) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)";
|
||||
public const string NetTcpChannelScheme = "net.tcp";
|
||||
public const string HttpChannelScheme = "http";
|
||||
|
||||
public static bool ValidateBasicSpanExpectations(
|
||||
Span span,
|
||||
string expectedChannelScheme,
|
||||
string expectedChannelPath,
|
||||
string expectedPeerName,
|
||||
int expectedPeerPort,
|
||||
string expectedMessageVersion)
|
||||
{
|
||||
var attributes = span.Attributes;
|
||||
var rpcSystem = ExtractAttribute(attributes, "rpc.system");
|
||||
var rpcService = ExtractAttribute(attributes, "rpc.service");
|
||||
var rpcMethod = ExtractAttribute(attributes, "rpc.method");
|
||||
var soapMessageVersion = ExtractAttribute(attributes, "soap.message_version");
|
||||
var netPeerPort = ExtractAttribute(attributes, "net.peer.port");
|
||||
var netPeerName = ExtractAttribute(attributes, "net.peer.name");
|
||||
var channelSchemeTag = ExtractAttribute(attributes, "wcf.channel.scheme");
|
||||
var channelPath = ExtractAttribute(attributes, "wcf.channel.path");
|
||||
return span.Kind == Span.Types.SpanKind.Client &&
|
||||
rpcSystem.Value.StringValue == "dotnet_wcf" &&
|
||||
rpcService.Value.StringValue == "http://opentelemetry.io/StatusService" &&
|
||||
rpcMethod.Value.StringValue == "Ping" &&
|
||||
netPeerName.Value.StringValue == expectedPeerName &&
|
||||
netPeerPort.Value.IntValue == expectedPeerPort &&
|
||||
channelSchemeTag.Value.StringValue == expectedChannelScheme &&
|
||||
soapMessageVersion.Value.StringValue == expectedMessageVersion &&
|
||||
channelPath.Value.StringValue == expectedChannelPath;
|
||||
}
|
||||
|
||||
private static KeyValue ExtractAttribute(IEnumerable<KeyValue> attributes, string key)
|
||||
{
|
||||
return attributes.Single(kv => kv.Key == key);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -27,6 +27,8 @@ namespace IntegrationTests;
|
|||
|
||||
public class WcfIISTests : TestHelper
|
||||
{
|
||||
private const string ExpectedChannelPath = "/StatusService.svc";
|
||||
private const string ExpectedPeerName = "localhost";
|
||||
private readonly Dictionary<string, string> _environmentVariables = new();
|
||||
|
||||
public WcfIISTests(ITestOutputHelper output)
|
||||
|
|
@ -49,25 +51,25 @@ public class WcfIISTests : TestHelper
|
|||
SetExporter(collector);
|
||||
using var fwPort = FirewallHelper.OpenWinPort(collector.Port, Output);
|
||||
|
||||
var netTcpPort = TcpPortProvider.GetOpenPort();
|
||||
var httpPort = TcpPortProvider.GetOpenPort();
|
||||
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, netTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion), "Client 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, netTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion), "Client 2");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, netTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion), "Client 3");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 4");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 4");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, httpPort, WcfClientInstrumentation.HttpBindingMessageVersion), "Client 4");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 5");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 5");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, httpPort, WcfClientInstrumentation.HttpBindingMessageVersion), "Client 5");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 6");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 6");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, httpPort, WcfClientInstrumentation.HttpBindingMessageVersion), "Client 6");
|
||||
|
||||
var collectorUrl = $"http://{DockerNetworkHelper.IntegrationTestsGateway}:{collector.Port}";
|
||||
_environmentVariables["OTEL_EXPORTER_OTLP_ENDPOINT"] = collectorUrl;
|
||||
|
||||
var netTcpPort = TcpPortProvider.GetOpenPort();
|
||||
var httpPort = TcpPortProvider.GetOpenPort();
|
||||
|
||||
await using var container = await StartContainerAsync(netTcpPort, httpPort);
|
||||
|
||||
RunTestApplication(new TestSettings
|
||||
|
|
@ -94,7 +96,7 @@ public class WcfIISTests : TestHelper
|
|||
var builder = new ContainerBuilder()
|
||||
.WithImage(imageName)
|
||||
.WithCleanUp(cleanUp: true)
|
||||
.WithName($"{imageName}")
|
||||
.WithName(imageName)
|
||||
.WithNetwork(networkName)
|
||||
.WithPortBinding(netTcpPort, 808)
|
||||
.WithPortBinding(httpPort, 80)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
#if NETFRAMEWORK
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.Collections;
|
||||
using IntegrationTests.Helpers;
|
||||
using OpenTelemetry.Proto.Common.V1;
|
||||
using OpenTelemetry.Proto.Trace.V1;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
|
|
@ -24,6 +26,11 @@ namespace IntegrationTests;
|
|||
|
||||
public class WcfNetFrameworkTests : WcfTestsBase
|
||||
{
|
||||
private const int NetTcpPort = 9090;
|
||||
private const int HttpPort = 9009;
|
||||
private const string ExpectedChannelPath = "/Telemetry";
|
||||
private const string ExpectedPeerName = "127.0.0.1";
|
||||
|
||||
public WcfNetFrameworkTests(ITestOutputHelper output)
|
||||
: base("Wcf.Client.NetFramework", output)
|
||||
{
|
||||
|
|
@ -34,19 +41,18 @@ public class WcfNetFrameworkTests : WcfTestsBase
|
|||
public async Task SubmitsTraces()
|
||||
{
|
||||
using var collector = await SubmitsTracesInternal(string.Empty);
|
||||
// TODO: better assertions including tags and hierarchy - https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/issues/2662
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, NetTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion), "Client 1");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, NetTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion), "Client 2");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.NetTcpChannelScheme, ExpectedChannelPath, ExpectedPeerName, NetTcpPort, WcfClientInstrumentation.NetTcpBindingMessageVersion), "Client 3");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 4");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 4");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion), "Client 4");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 5");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 5");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion), "Client 5");
|
||||
collector.Expect("OpenTelemetry.Instrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Server && span.ParentSpanId != ByteString.Empty, "Server 6");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client, "Client 6");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion), "Client 6");
|
||||
|
||||
collector.AssertExpectations();
|
||||
}
|
||||
|
|
@ -58,9 +64,9 @@ public class WcfNetFrameworkTests : WcfTestsBase
|
|||
using var collector = new MockSpansCollector(Output);
|
||||
SetExporter(collector);
|
||||
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client && span.Status.Code == Status.Types.StatusCode.Error, "Client 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client && span.Status.Code == Status.Types.StatusCode.Error, "Client 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => span.Kind == Span.Types.SpanKind.Client && span.Status.Code == Status.Types.StatusCode.Error, "Client 3");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => ValidateErrorSpanExpectations(span), "Client 1");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => ValidateErrorSpanExpectations(span), "Client 2");
|
||||
collector.Expect("OpenTelemetry.AutoInstrumentation.Wcf", span => ValidateErrorSpanExpectations(span), "Client 3");
|
||||
|
||||
RunTestApplication(new TestSettings
|
||||
{
|
||||
|
|
@ -69,6 +75,11 @@ public class WcfNetFrameworkTests : WcfTestsBase
|
|||
|
||||
collector.AssertExpectations();
|
||||
}
|
||||
|
||||
private static bool ValidateErrorSpanExpectations(Span span)
|
||||
{
|
||||
return WcfClientInstrumentation.ValidateBasicSpanExpectations(span, WcfClientInstrumentation.HttpChannelScheme, ExpectedChannelPath, ExpectedPeerName, HttpPort, WcfClientInstrumentation.HttpBindingMessageVersion) && span.Status.Code == Status.Types.StatusCode.Error;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue