diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/CHANGELOG.md b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/CHANGELOG.md index ba5d2ea60b..baf57e4996 100644 --- a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/CHANGELOG.md +++ b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/CHANGELOG.md @@ -1,12 +1,16 @@ # Changelog -## Unreleased +## 1.0.0-rc3 * Added `TelemetryServiceBehavior`. **Breaking change** (config update required): Renamed `TelemetryBehaviourExtensionElement` -> `TelemetryEndpointBehaviorExtensionElement` ([#152](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/152)) +* Added `TelemetryContractBehaviorAttribute` which can be used for programmatic + configuration of WCF services & clients + ([#153](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/153)) + ## 1.0.0-rc2 * Updated OTel SDK package version to 1.1.0-beta1 diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/README.md b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/README.md index 3c8c76422a..fa74a3cd4f 100644 --- a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/README.md +++ b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/README.md @@ -103,8 +103,11 @@ Example project available in ## WCF Server Configuration (.NET Framework) -Add the `IDispatchMessageInspector` instrumentation via an endpoint behavior -extension on the service endpoints you want to instrument: +### Option 1: Instrument by endpoint + +To add the `IDispatchMessageInspector` instrumentation to select endpoints of a +service, use the endpoint behavior extension on the service endpoints you want +to instrument: ```xml @@ -149,6 +152,8 @@ Example project available in [examples/wcf/server-netframework](../../examples/wcf/server-netframework/) folder. +### Option 2: Instrument by service + To add the `IDispatchMessageInspector` instrumentation for all endpoints of a service, use the service behavior extension on the services you want to instrument: @@ -192,6 +197,26 @@ instrument: ``` +## WCF Programmatic Configuration Server and/or Client (.NET Framework + .NET Core) + +To add `IDispatchMessageInspector` for servers (.NET Framework only) and/or +`IClientMessageInspector` for clients (.NET Framework & .NET Core) +programmatically, use the `TelemetryContractBehaviorAttribute` on the service +contracts you want to instrument: + +```csharp + [ServiceContract( + Namespace = "http://opentelemetry.io/", + Name = "StatusService", + SessionMode = SessionMode.Allowed)] + [TelemetryContractBehavior] + public interface IStatusServiceContract + { + [OperationContract] + Task PingAsync(StatusRequest request); + } +``` + ## References * [OpenTelemetry Project](https://opentelemetry.io/) diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryContractBehaviorAttribute.cs b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryContractBehaviorAttribute.cs new file mode 100644 index 0000000000..29ea4a4b38 --- /dev/null +++ b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryContractBehaviorAttribute.cs @@ -0,0 +1,65 @@ +// +// 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. +// + +using System; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; + +namespace OpenTelemetry.Contrib.Instrumentation.Wcf +{ +#if NETFRAMEWORK + /// + /// An to add the + /// to service operations + /// and to client operations + /// programmatically. + /// +#else + /// + /// An to add the + /// to client operations + /// programmatically. + /// +#endif + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false, AllowMultiple = false)] + public class TelemetryContractBehaviorAttribute : Attribute, IContractBehavior + { + /// + public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) + { + } + + /// + public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) + { + TelemetryEndpointBehavior.ApplyClientBehaviorToClientRuntime(clientRuntime); + } + + /// + public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) + { +#if NETFRAMEWORK + TelemetryEndpointBehavior.ApplyDispatchBehaviorToEndpoint(dispatchRuntime.EndpointDispatcher); +#endif + } + + /// + public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) + { + } + } +} diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryEndpointBehavior.cs b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryEndpointBehavior.cs index 55b1f7d98b..0f55b3cacf 100644 --- a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryEndpointBehavior.cs +++ b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryEndpointBehavior.cs @@ -44,18 +44,7 @@ public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterColle /// public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { - var actionMappings = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var clientOperation in clientRuntime.ClientOperations) - { - actionMappings[clientOperation.Action] = new ActionMetadata - { - ContractName = $"{clientRuntime.ContractNamespace}{clientRuntime.ContractName}", - OperationName = clientOperation.Name, - }; - } - - clientRuntime.ClientMessageInspectors.Add(new TelemetryClientMessageInspector(actionMappings)); + ApplyClientBehaviorToClientRuntime(clientRuntime); } /// @@ -71,6 +60,22 @@ public void Validate(ServiceEndpoint endpoint) { } + internal static void ApplyClientBehaviorToClientRuntime(ClientRuntime clientRuntime) + { + var actionMappings = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var clientOperation in clientRuntime.ClientOperations) + { + actionMappings[clientOperation.Action] = new ActionMetadata + { + ContractName = $"{clientRuntime.ContractNamespace}{clientRuntime.ContractName}", + OperationName = clientOperation.Name, + }; + } + + clientRuntime.ClientMessageInspectors.Add(new TelemetryClientMessageInspector(actionMappings)); + } + #if NETFRAMEWORK internal static void ApplyDispatchBehaviorToEndpoint(EndpointDispatcher endpointDispatcher) { diff --git a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryServiceBehavior.cs b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryServiceBehavior.cs index 0ce05d329c..a7e56dcb00 100644 --- a/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryServiceBehavior.cs +++ b/src/OpenTelemetry.Contrib.Instrumentation.Wcf/TelemetryServiceBehavior.cs @@ -14,8 +14,6 @@ // limitations under the License. // -using System; -using System.Collections.Generic; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher;