How to use ITelemetryInitializer for each class respectively on dependency telemetry - c#

I want to add customer properties for dependency telemetry(outgoing request).
Saw the answer here
How to extend Dependency tracking for outgoing http requests in Application Insights
Right now I use one telemetry initializer for the whole project via config file.
But what I want to do is add different custom property value based on which outgoing request based on which class send out.
Ex: A.cs and B.cs, for all outgoing request send out by A.cs, add customer property like {"sender", "A.cs"}, and also some value should be captured on run time.
So how do I
Setup telemetry initializer for each different class, not whole project?
Is it possible that I can pass parameter to the telemetry initializer so I can set customer property based on the parameter?
Thanks

Related

Application Insights - Custom TrackRequest is creating duplicate messages

I want to be able to add custom properties to a request telemetry. I am able to do this with code such as:
public void LogRequest(IDictionary<string,string> properties)
{
var client = new TelemetryClient();
var request = new RequestTelemetry();
foreach(var prop in properties)
{
request.Properties.Add(prop );
}
client.TrackRequest(request);
}
This code works in the sense that it creates a request telemetry with all of the custom properties I wanted, however the application insights SDK is also creating a duplicate request telemetry (without my custom properties). So it's sending its own request telemetry and the one that I created.
While trying to do some research I found this:
https://github.com/Azure/Azure-Functions/wiki/App-Insights-Early-Preview
Custom telemetry
You can bring the .NET App Insights SDK in and create your own TelemetryClient. There isn’t any conflicts, but there is some advice:
Don’t create TrackRequest or use the StartOperation methods if you don’t want duplicate requests – we do this automatically.
So my question is, is there anyway to send in my own custom request telemetry without the sdk automatically creating a duplicate message?
Also I would like to avoid using TrackEvent. Most of the information I need is already in the request object so I would prefer to use TrackRequest.
This is what I have in my application insights config in the track request section:
<TelemetryModules>
<Add Type="Microsoft.ApplicationInsights.Web.RequestTrackingTelemetryModule, Microsoft.AI.Web">
<Handlers>
<Add>System.Web.Handlers.TransferRequestHandler</Add>
<Add>Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.RequestDataHttpHandler</Add>
<Add>System.Web.StaticFileHandler</Add>
<Add>System.Web.Handlers.AssemblyResourceLoader</Add>
<Add>System.Web.Optimization.BundleHandler</Add>
<Add>System.Web.Script.Services.ScriptHandlerFactory</Add>
<Add>System.Web.Handlers.TraceHandler</Add>
<Add>System.Web.Services.Discovery.DiscoveryRequestHandler</Add>
<Add>System.Web.HttpDebugHandler</Add>
</Handlers>
</Add>
</TelemetryModules>
The reason is that AI SDK automatically track requests for you, and therefore you get dups (the one w/o your properties is the one created automatically).
As PeterBons suggested, using Telemetry Initializer you can add the properties to the auto-generated request.

Authentication via headers in WCF REST service

I am new to WCF services and currently testing out things.
I have got a little REST API, which has several methods. Some of them require a user context (session), some others don't. At login, each user gets a session token. The client should supply this token and his user ID on every request via HTTP headers.
At the moment, I wrote a method for getting those two headers and validate the session, calling it on every method which will need a user context. This seems kinda nasty if the API gets bigger.
Is there a better approach for doing this?
You can leverage of following solutions:
Custom class deriving IClientMessageInspector/IDispatchMessageInspector for client and service respectively. Then you add its instance to MessageInspectors. Advantage of having messageInspector is that it's applied to single endpoint so regardless of having many endpoints exposed (both SOAP and REST), messageInspector can be associated only with single one. Whenever message is either received or sent, AfterReceive or BeforeSent method is invoked respectively. There you retrieve headers and if token does not match any expected you can throw an exception. Such a way out provides separation between exposed contract and background checks such as token validation.
Custom class deriving IOperationInvoker. Within custom operation invoker you explicitly call method and thanks to it you can examine headers (OperationContext.Current.IncomingMessage) before any method gets invoced.
I brought up only concepts, extensive information and examples can be looked up on Internet.

WCF - How can I get a reference to the incoming message string in my service implementation?

Based on the processing of the incoming request I have to store the original (unserialized) message as string to a database.
So far I implemented a DispatchMessageInspector and a ServiceBehavior that I used to decorate my service implementation. My DispatchMessageInspector has a property to which I store the message string. My service implementation includes some business rules that check the request and if this check fails I'd like to store the original message.
How can I achieve to access the message string property of my DispatchMessageInspector from the service implementation in an elegant way?
You can add a Message Property containing the raw message in a form you like. Then in your service, you can access them through OperationContext.Current.IncomingMessageProperties["RawMessage"].

Can an endpoint behavior accept parameters

I am using message inspector in WCF application to store request & responses, into DB.
Whether to store these data in DB or not has to be restricted based on userInput received in the front-end.
To cut the long story short, I need help to address these issues -
States in page context are not available in the extensibility points
interface.
Inspectors method also do not accept any custom
parameters.
In this case, How can we pass the parameters to the WCF extensibility points for customizations?
Well the IDispatchMessageInspector interface receives a IClientChannel on each call, which is in turn an IExtensible. You would have to implement an custom IExtension, and extend the client channel when it's initialized (using an IChannelInitializer implementation). You could then retrieve the extension from the channel parameter in the inspector method implementation, and use it as a means of communication with you front end..

WCF - Intercepting a Message and Sending a Custom Response

I have a requirement for a WCF service I've created to be able to go into "read only" mode. While in this state it will not service requests for calls that would make changes to the database (like creating an order) but will only service read-only requests (like authenticate user). If it receives a request that it will not service, it needs to pass back a friendly message and code (e.g. CODE: 100, DESCRIPTION: "Service is in read only mode and cannot service this request").
I have close to 100 different calls and would like to implement a solution that can be made in one place (like an IDispatchMessageInspector) but I don't see a way to provide a response to any intercepted WCF messages. I have a standard response type that I send back on ALL requests and would like to send that back in these situations as well. The type is named ServiceResponse and has a messages collection. which is a class of Codes and Descriptions.
public class ServiceResponse
{
public List<Message> Messages {get; set;}
}
public class Message
{
public string Code {get; set;}
public string Description {get; set;}
}
Can someone provide me with a direction on how to do this? I have exhausted all of my searching options.
Even if there is just a way in WCF to hand create the SOAP I'm sending back, that's fine as long as I don't have to handle the read-only check / response in every single service call.
Thanks!
I see a couple of choices. 1) add the functionality into the service implementations (100 of them), 2) find an aspect-oriented tool to intercept the service invocation at runtime and execute different code, or 3) intercept all the wcf requests using a custom HTTPHandler. In the handler you can process the request and return a response to the client. Here are some links which might help
http://blogs.msdn.com/b/wenlong/archive/2007/09/18/how-to-use-asmx-extension-to-handle-wcf-requests.aspx
HttpHandler to hook the *.svc requests
You could achieve this with a custom ServiceAuthorizationManager.
The idea would be
Add a custom attribute to each class that you want to disable when in read only mode
In the custom ServiceAuthorizationManager, check to see if the service is in read only mode. If it is, check for the custom attribute on the method you are trying to call. The method is indicated by the request message action header. The type of the service can be found from the OperationContext.InstanceContext (I think - I can't remember exactly what property)
If you find the attribute, throw a fault exception with the right error message.

Categories