c# - How do I get accurate Exception stack in WCF Task-based Operation -
c# - How do I get accurate Exception stack in WCF Task-based Operation -
i'm using wcf ierrorhandler interface trap , log errors on server side of wcf service. however, stacktrace of exception passed handleerror , providefault messed up:
at system.servicemodel.dispatcher.taskmethodinvoker.invokeend(object instance, object[]& outputs, iasyncresult result) @ system.servicemodel.dispatcher.dispatchoperationruntime.invokeend(messagerpc& rpc) @ system.servicemodel.dispatcher.immutabledispatchruntime.processmessage7(messagerpc& rpc) ....lots more
i'm not surprised see random dispatcher methods in stack trace, assumed see own method @ top of stack.
i've determined happens on operations like
[operationcontract] public task<int> myoperation() { throw new applicationexception("test"); }
services have proper stack trace me log:
[operationcontract] public int mysyncoperation() { throw new applicationexception("test"); }
as fyi, here's error handler methods like:
public class myerrorhandler : ierrorhandler { public bool handleerror(exception error) { //variable 'error' has wrong stack trace if exception sourced task<int> operation homecoming false; } public void providefault(exception error, messageversion version, ref message fault) { //variable 'error' has wrong stack trace if exception sourced task<int> operation } }
note exception type , message correct, it's if they're incorrectly rethrowing exception somewhere 'throw ex' rather 'throw';
is there way right stack trace of exception 1 of ierrorhandler methods?
i ended solving using next custom operation invoker. goal log errors proper stack trace, error ends beingness thrown retains poor stack trace.
public class errorloggingoperationinvokerfacade : ioperationinvoker { private readonly ioperationinvoker _invoker; private readonly ilog _log; public errorloggingoperationinvokerfacade(ioperationinvoker invoker, ilog log) { _invoker = invoker; _log = log; } public object[] allocateinputs() { homecoming _invoker.allocateinputs(); } public object invoke(object instance, object[] inputs, out object[] outputs) { homecoming _invoker.invoke(instance, inputs, out outputs); } public iasyncresult invokebegin(object instance, object[] inputs, asynccallback callback, object state) { homecoming _invoker.invokebegin(instance, inputs, callback, state); } public object invokeend(object instance, out object[] outputs, iasyncresult result) { var task = result task; if (task != null && task.isfaulted && task.exception != null) { foreach (var error in task.exception.innerexceptions) { _log.log(error); } } homecoming _invoker.invokeend(instance, out outputs, result); } public bool issynchronous { { homecoming _invoker.issynchronous; } } }
it can attached attribute on service class or method:
public class logerrorsattribute : attribute, iservicebehavior, ioperationbehavior { public void applydispatchbehavior(servicedescription servicedescription, servicehostbase servicehostbase) { foreach (var operation in servicehostbase.description.endpoints.selectmany(endpoint => endpoint.contract.operations)) { if (!operation.behaviors.any(b => b logerrorsattribute)) operation.behaviors.add(this); } } public void applydispatchbehavior(operationdescription operationdescription, dispatchoperation dispatchoperation) { dispatchoperation.invoker = new errorloggingoperationinvokerfacade(dispatchoperation.invoker, wcfdependencymanager.resolvelogger()); } public void validate(operationdescription operationdescription) { } public void applyclientbehavior(operationdescription operationdescription, clientoperation clientoperation) { } public void addbindingparameters(operationdescription operationdescription, bindingparametercollection bindingparameters) { } public void validate(servicedescription servicedescription, servicehostbase servicehostbase) { } public void addbindingparameters(servicedescription servicedescription, servicehostbase servicehostbase, collection<serviceendpoint> endpoints, bindingparametercollection bindingparameters) { } }
previously logging errors in implementation of ierrorhandler
interface, @ point stack trace messed up. tried modify operation invoker throw exception proper stack trace never got work right. reason, custom fault exceptions turned generic fault exceptions, abandoned approach.
c# wcf
Comments
Post a Comment