/// <summary> /// Determines the log level for the current message, based on the value of /// the error parameter. /// </summary> /// <param name="error"> /// Error which occurred during processing, or null if none. /// </param> /// <returns> /// Log level that the message should be journaled in. /// </returns> private static LogLevel LogLevelFor(ActorException error) { if (error == null) { return(LogLevel.Debug); } LogLevel level; if (error.Actor.EndsWith(".Client") == true) { level = LogLevel.Warn; } else { level = LogLevel.Error; } if (error.Data.Contains("Pt.Level") == true) { try { string value = (string)error.Data["Pt.Level"]; level = LogLevel.FromString(value); } catch (Exception) { // Snuff it! } } return(level); }
public void MethodOne_Unhandled() { OneClient svc = new OneClient(); svc.ActivityId = Guid.NewGuid(); svc.AccessToken = "my.jwt.token"; try { svc.MethodOne(new Zn.Sample.OneSvc.MethodOneRequest() { Value = 15 }); Assert.Fail("Expected exception."); } catch (ServiceFaultException ex) { // Zinc.WebServices.ZincException Assert.AreEqual("ZnSample.Zinc", ex.Actor); Assert.AreEqual(4006, ex.Code); // System.Exception Assert.IsTrue(ex.InnerException != null, "Expected inner exception."); Assert.IsTrue(ex.InnerException is ActorException, "Inner exception must be ActorException."); ActorException iex = (ActorException)ex.InnerException; Assert.AreEqual("ZnSample", iex.Actor); Assert.AreEqual(991, iex.Code); } catch (Exception ex) { Assert.Fail("Expected named exception, instead got: " + ex.GetType().FullName); } }
/// <summary> /// Handles the exception. /// </summary> /// <param name="context"> /// Exception handling context. /// </param> /// <param name="cancellationToken"> /// Cancellation token. /// </param> /// <returns> /// Task. /// </returns> public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken) { #region Validations if (context == null) { throw new ArgumentNullException(nameof(context)); } #endregion ActorFault fault; bool detailed = ZincConfiguration.Current.Rest.Errors.Detailed; if (context.Exception is ActorException) { ActorException aex = (ActorException)context.Exception; fault = ActorFault.From(aex, detailed); } else { fault = ActorFault.FromUnhandled(context.Exception, detailed); } context.Result = new ExceptionResponse(fault); return(Task.CompletedTask); }
/// <summary> /// Based on the exception raised by the implementation class, assigns /// as response an instance of <see cref="ActorFault" />. /// </summary> /// <param name="context">The context for the action.</param> public override void OnException(HttpActionExecutedContext context) { #region Validations if (context == null) { throw new ArgumentNullException(nameof(context)); } #endregion var request = context.ActionContext.Request; bool detailed = ZincConfiguration.Current.Rest.Errors.Detailed; ActorFault fault; if (context.Exception is ActorException) { ActorException aex = (ActorException)context.Exception; fault = ActorFault.From(aex, detailed); } else { fault = ActorFault.FromUnhandled(context.Exception, detailed); } context.Response = request.CreateResponse <ActorFault>(HttpStatusCode.InternalServerError, fault); }
/// <summary> /// Creates an instance of <see cref="ActorFault"/> from an actor exception. /// </summary> /// <param name="exception">Unhandled exception.</param> /// <param name="detailed">Whether to include detailed information (namely, stack trace).</param> /// <returns>Instance of <see cref="ActorFault"/>.</returns> public static ActorFault From(ActorException exception, bool detailed) { #region Validations if (exception == null) { throw new ArgumentNullException(nameof(exception)); } #endregion ActorFault fault = new ActorFault(); fault.Actor = exception.Actor; fault.Code = exception.Code; fault.Message = exception.Description; fault.ExceptionType = exception.GetType().FullName; fault.InnerFaults = Walk(exception.InnerException, detailed); if (detailed == true) { fault.StackTrace = exception.StackTrace; } return(fault); }
public void MethodOn_RemoteException() { OneClient svc = new OneClient(); svc.ActivityId = Guid.NewGuid(); svc.AccessToken = "my.jwt.token"; try { svc.MethodOneAsync(new Zn.Sample.OneSvc.MethodOneRequest() { Value = 110 }).GetAwaiter().GetResult(); Assert.Fail("Expected exception."); } catch (ServiceFaultException ex) { // Zn.Sample.SampleException Assert.AreEqual("ZnSample", ex.Actor); Assert.AreEqual(10001, ex.Code); // Zn.Sample.SampleException Assert.IsTrue(ex.InnerException != null, "Expected inner exception."); Assert.IsTrue(ex.InnerException is ActorException, "Inner exception must be ActorException."); ActorException iex = (ActorException)ex.InnerException; Assert.AreEqual("ZnSample", iex.Actor); Assert.AreEqual(10000, iex.Code); } catch (Exception ex) { Assert.Fail("Expected named exception, instead got: " + ex.GetType().FullName); } }
/// <summary> /// Serializes an instance of <see cref="ActorException" /> to XML. /// </summary> /// <param name="error"> /// Exception. /// </param> /// <returns> /// XML representation of error. /// </returns> private static string ToXml(ActorException error) { if (error == null) { return(null); } var fault = ActorFault.From(error, true); return(ToXml(fault)); }
/// <summary /> public Task PostAsync(ExecutionContext context, object response, ActorException error) { #region Validations if (context == null) { throw new ArgumentNullException(nameof(context)); } #endregion return(Task.CompletedTask); }
/// <summary> /// Converts an actor exception into an WCF exception. /// </summary> /// <param name="exception"> /// Exception. /// </param> /// <returns> /// WCF exception. /// </returns> public static FaultException <ActorFault> ToException(ActorException exception) { ActorFault detail = ActorFault.From(exception, true); string faultCode = "Server"; if (detail.Actor.EndsWith(".Client", StringComparison.Ordinal) == true) { faultCode = "Client"; } return(new FaultException <ActorFault>(detail, detail.Message, new FaultCode(faultCode))); }
/// <summary /> protected ZincAggregateException(SerializationInfo info, StreamingContext context) : base(info, context) { #region Validations if (info == null) { throw new ArgumentNullException(nameof(info)); } #endregion _leading = (ActorException)info.GetValue("Leading", typeof(ActorException)); }
/// <summary /> public ServiceFaultException(string actor, int code, string message, ActorException innerException) : base(message, innerException) { #region Validations if (actor == null) { throw new ArgumentNullException(nameof(actor)); } #endregion _actor = actor; _code = code; }
/// <summary /> public ZincAggregateException(ActorException leading, ActorAggregateException aggregateException) : base(leading?.Message, aggregateException) { #region Validations if (leading == null) { throw new ArgumentNullException(nameof(leading)); } if (aggregateException == null) { throw new ArgumentNullException(nameof(aggregateException)); } #endregion _leading = leading; }
/// <summary /> public ServiceFaultException AsException() { ActorException innerException = null; if (this.InnerFaults != null && this.InnerFaults.Count > 0) { if (this.InnerFaults.Count == 1) { innerException = this.InnerFaults[0].AsException(); } else { var exceptions = this.InnerFaults.Select(x => x.AsException()); innerException = new ActorAggregateException(exceptions); } } return(new ServiceFaultException(this.Actor, this.Code, this.Message, innerException)); }
/// <summary /> public Task PostAsync(ExecutionContext context, object response, ActorException error) { #region Validations if (context == null) { throw new ArgumentNullException(nameof(context)); } #endregion /* * */ LogLevel level = LogLevelFor(error); logger.Log(level, "Zn.PostAsync", context, response, error); return(Task.CompletedTask); }
/// <summary /> public async Task PostAsync(ExecutionContext context, object response, ActorException error) { #region Validations if (context == null) { throw new ArgumentNullException(nameof(context)); } #endregion if (response == null && error == null) { throw new ArgumentOutOfRangeException(nameof(response), "Field may not be null, if error is also null."); } /* * */ string responseXml = ToXml(response); string errorXml = ToXml(error); /* * */ DbConnection conn = Db.Connection("SqlServerLogging"); await conn.ExecuteAsync(Q.SqlPost, new { ExecutionId = context.ExecutionId, ResponseXml = responseXml, ErrorXml = errorXml, MomentEnd = context.MomentEnd }); }
/// <summary /> public async Task FullAsync(ExecutionContext context, object request, object response, ActorException error) { #region Validations if (context == null) { throw new ArgumentNullException(nameof(context)); } if (request == null) { throw new ArgumentNullException(nameof(request)); } #endregion /* * */ string requestXml = ToXml(request); string responseXml = ToXml(response); string errorXml = ToXml(error); /* * */ DbConnection conn = Db.Connection("SqlServerLogging"); await conn.ExecuteAsync(Q.SqlFull, new { Application = App.Name, ExecutionId = context.ExecutionId, Method = context.Method, ActivityId = context.ActivityId, AccessToken = context.AccessToken, RequestXml = requestXml, ResponseXml = responseXml, ErrorXml = errorXml, MomentStart = context.MomentStart, MomentEnd = context.MomentEnd }); }
private static ActorFault[] Walk(Exception exception, bool detailed) { if (exception == null) { return(null); } /* * AggregateException, which contains Exception[] */ if (exception is AggregateException) { AggregateException aex = (AggregateException)exception; List <ActorFault> l = new List <ActorFault>(); foreach (Exception iex in aex.InnerExceptions) { l.AddRange(Walk(iex, detailed)); } return(l.ToArray()); } /* * ActorAggregateException, which contains ActorException[] */ if (exception is ActorAggregateException) { ActorAggregateException aex = (ActorAggregateException)exception; List <ActorFault> l = new List <ActorFault>(); foreach (ActorException iex in aex) { l.AddRange(Walk(iex, detailed)); } return(l.ToArray()); } /* * ActorException */ if (exception is ActorException) { ActorException aex = (ActorException)exception; ActorFault f = new ActorFault(); f.Actor = aex.Actor; f.Code = aex.Code; f.Message = aex.Description; f.ExceptionType = aex.GetType().FullName; f.InnerFaults = Walk(aex.InnerException, detailed); if (detailed == true) { f.StackTrace = aex.StackTrace; } return(new ActorFault[] { f }); } /* * Exception */ if (true) { ActorFault f = new ActorFault(); f.Actor = App.Name; f.Code = 991; f.Message = exception.Message; f.ExceptionType = exception.GetType().FullName; f.InnerFaults = Walk(exception.InnerException, detailed); if (detailed == true) { f.StackTrace = exception.StackTrace; } return(new ActorFault[] { f }); } // Impossible! :) }
private object ToPostData(IEnumerable <LogEventInfo> logEvents) { #region Validations if (logEvents == null) { throw new ArgumentNullException(nameof(logEvents)); } #endregion /* * */ string appName; string appEnvironment; try { appName = App.Name; } catch { appName = "##NotDefined##"; } try { appEnvironment = App.Environment; } catch { appEnvironment = "##NotDefined##"; } /* * */ var payload = new List <object>(); foreach (var logEvent in logEvents) { ExecutionContext context; object request = null; object response = null; ActorException error = null; TimeSpan? timeSpan = null; switch (logEvent.Message) { case "Zn.FullAsync": context = (ExecutionContext)logEvent.Parameters[0]; request = logEvent.Parameters[1]; response = logEvent.Parameters[2]; error = (ActorException)logEvent.Parameters[3]; timeSpan = context.MomentEnd - context.MomentStart; break; case "Zn.PostAsync": context = (ExecutionContext)logEvent.Parameters[0]; response = logEvent.Parameters[1]; error = (ActorException)logEvent.Parameters[2]; break; case "Zn.PreAsync": context = (ExecutionContext)logEvent.Parameters[0]; request = logEvent.Parameters[1]; break; default: // Not a valid log event! Skip! continue; } /* * */ var document = new Dictionary <string, object> { { "@timestamp", logEvent.TimeStamp }, { "level", logEvent.Level.Name }, { "application", App.Name }, { "environment", App.Environment }, { "host", Environment.MachineName }, { "message", "OK" }, { "accessToken", context.AccessToken }, { "activityId", context.ActivityId }, { "executionId", context.ExecutionId }, { "method", context.Method }, }; if (timeSpan.HasValue == true) { document.Add("duration", timeSpan.Value.TotalMilliseconds); } if (request != null) { document.Add("request", ToJson(request)); } if (response != null) { document.Add("response", ToJson(response)); } if (error != null) { document["message"] = error.Description; document.Add("actor", error.Actor); document.Add("code", error.Code); document.Add("exception", error.ToString()); foreach (string key in error.Data.Keys) { if (key.StartsWith("Pt.") == true) { continue; } document.Add(SafeKey("exd_", key), error.Data[key].ToString()); } } else { document.Add("actor", null); document.Add("code", null); document.Add("exception", null); } var index = Index.Render(logEvent).ToLowerInvariant(); var type = DocumentType.Render(logEvent); payload.Add(new { index = new { _index = index, _type = type } }); payload.Add(document); } /* * */ if (payload.Count == 0) { return(null); } return(payload); }
private static SoapResponse ToFault(SoapVersion version, ExecutionHeader execution, ActorException exception) { #region Validations if (execution == null) { throw new ArgumentNullException(nameof(execution)); } if (exception == null) { throw new ArgumentNullException(nameof(exception)); } #endregion /* * */ XNamespace fwkNs = "https://github.com/filipetoscano/Zinc"; XNamespace soapNs; if (version == SoapVersion.Soap11) { soapNs = "http://schemas.xmlsoap.org/soap/envelope/"; } else { soapNs = "http://www.w3.org/2003/05/soap-envelope"; } XDocument responseDoc = new XDocument(); var envelope = new XElement(soapNs + "Envelope"); envelope.Add(new XAttribute(XNamespace.Xmlns + "soap", soapNs.NamespaceName)); var header = new XElement(soapNs + "Header"); var body = new XElement(soapNs + "Body"); var fault = new XElement(soapNs + "Fault"); body.Add(fault); envelope.Add(header, body); responseDoc.Add(envelope); /* * Header */ execution.MomentEnd = DateTime.UtcNow; XmlSerializer serHeader = new XmlSerializer(typeof(ExecutionHeader)); header.Add(serHeader.SerializeAsXElement(execution)); /* * Fault */ if (version == SoapVersion.Soap11) { // TODO: recurse through exception stack XElement x = new XElement(fwkNs + "ActorFault", new XElement(fwkNs + "Actor", new XText(exception.Actor)), new XElement(fwkNs + "Code", new XText(exception.Code.ToString(CultureInfo.InvariantCulture))), new XElement(fwkNs + "Message", new XText(exception.Description)), new XElement(fwkNs + "ExceptionType", new XText(exception.GetType().FullName)) ); if (exception.StackTrace != null) { x.Add(new XElement(fwkNs + "StackTrace", new XText(exception.StackTrace))); } fault.Add( new XElement("faultcode", new XText(exception.Actor.EndsWith("Client", StringComparison.Ordinal) == true ? "soap:Client" : "soap:Server")), new XElement("faultstring", new XText(exception.Description)), new XElement("detail", x) ); } else { // TODO: implemented throw new NotImplementedException(); } /* * */ SoapResponse response = new SoapResponse(); response.Version = version; response.IsFault = true; response.Message = responseDoc.ToString(SaveOptions.DisableFormatting); return(response); }