parent
85914b5262
commit
fb74a1a6a7
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Exceptron.Driver" version="0.1.0.30" />
|
||||
<package id="Exceptron.Driver" version="0.1.0.34" />
|
||||
<package id="Newtonsoft.Json" version="4.5.4" />
|
||||
<package id="NLog" version="2.0.0.2000" />
|
||||
</packages>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
|
||||
namespace Exceptron.Driver
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information that will be used to construct an exception report.
|
||||
/// </summary>
|
||||
public class ExceptionData
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception that is being reported
|
||||
/// </summary>
|
||||
public Exception Exception { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Component that caused this error.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is common to use the logger name that was used to log the exception as the component.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// DataAccess, Configuration, Registration, etc.
|
||||
/// </example>
|
||||
public string Component { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID that will uniquely identify the user
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This Id does not have to be tied to the user's identity.
|
||||
/// You can use a system generated unique ID such as GUID.
|
||||
/// This field is used to report how many unique users are experiencing an error.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// "62E5C8EF-0CA2-43AB-B278-FC6994F776ED"
|
||||
/// "Timmy@aol.com"
|
||||
/// "26437"
|
||||
/// </example>
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Any message that should be attached to this exceptions
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// Something went wrong while checking for application updates.
|
||||
/// </example>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Severity of the exception being reported
|
||||
/// </summary>
|
||||
public ExceptionSeverity Severity { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
namespace Exceptron.Driver
|
||||
{
|
||||
/// <summary>
|
||||
/// Severity of the exception being reported
|
||||
/// </summary>
|
||||
public enum ExceptionSeverity
|
||||
{
|
||||
/// <summary>
|
||||
/// Excepted Error. Can be ignored
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Error that can be handled gracefully
|
||||
/// </summary>
|
||||
Warning = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Blocking user from completing their intended action
|
||||
/// </summary>
|
||||
Error = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Will most likely cause the application to crash
|
||||
/// </summary>
|
||||
Fatal = 3
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Exceptron.Driver
|
||||
{
|
||||
internal interface IRestClient
|
||||
{
|
||||
TResponse Put<TResponse>(string url, object report) where TResponse : class, new();
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Exceptron.Driver.Message
|
||||
{
|
||||
internal class ExceptionReport
|
||||
{
|
||||
/// <summary>
|
||||
/// API key
|
||||
/// </summary>
|
||||
public string ap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Application Version
|
||||
/// </summary>
|
||||
public string aver { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exception Severity
|
||||
/// </summary>
|
||||
public int sv { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User or Instance ID
|
||||
/// </summary>
|
||||
public string uid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of exception
|
||||
/// </summary>
|
||||
public string ext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Exception message
|
||||
/// </summary>
|
||||
public string exm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of frames that make up the StackTrace of the exception
|
||||
/// </summary>
|
||||
public List<Frame> stk { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Component that experienced this exception
|
||||
/// </summary>
|
||||
public string cmp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Environment that this exception occurred in.
|
||||
/// </summary>
|
||||
/// <example>Dev, Stage, Production</example>
|
||||
public string env { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Message that was logged along with the exception.
|
||||
/// </summary>
|
||||
public string msg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// User's culture in
|
||||
/// </summary>
|
||||
/// <remarks>http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.name.aspx</remarks>
|
||||
public string cul { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OS Version
|
||||
/// </summary>
|
||||
public string os { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the driver that generated and is sending this message
|
||||
/// </summary>
|
||||
public string dn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Version of the driver that generated and is sending this message
|
||||
/// </summary>
|
||||
public string dv { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
|
||||
namespace Exceptron.Driver.Message
|
||||
{
|
||||
public class ExceptionResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception report reference ID. This ID will be shared across
|
||||
/// similar exceptions
|
||||
/// </summary>
|
||||
public string RefId { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Was the report successfully processed on the server
|
||||
/// </summary>
|
||||
public bool Successful
|
||||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrEmpty(RefId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exception that caused the message to fail.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property will only be populated if <see cref="ClientConfiguration.ThrowsExceptions"/> is set to <see cref="bool.False"/>/>
|
||||
/// Exception is thrown if <see cref="ClientConfiguration.ThrowsExceptions"/> is set to <see cref="bool.True"/>.
|
||||
/// </remarks>
|
||||
public Exception Exception { get; internal set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
namespace Exceptron.Driver.Message
|
||||
{
|
||||
internal class Frame
|
||||
{
|
||||
/// <summary>
|
||||
/// Order of current frame
|
||||
/// </summary>
|
||||
public int i { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Line number of the current frame
|
||||
/// </summary>
|
||||
public int ln { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File name of the current frame
|
||||
/// </summary>
|
||||
public string fn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Method name for current frame
|
||||
/// </summary>
|
||||
public string m { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Class name for current frame
|
||||
/// </summary>
|
||||
public string c { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
namespace Exceptron.Driver
|
||||
{
|
||||
public class ValidationError
|
||||
{
|
||||
public string ErrorCode { get; set; }
|
||||
|
||||
public string FieldName { get; set; }
|
||||
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,408 @@
|
||||
//http://fastjson.codeplex.com/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Exceptron.Driver.fastJSON
|
||||
{
|
||||
/// <summary>
|
||||
/// This class encodes and decodes JSON strings.
|
||||
/// Spec. details, see http://www.json.org/
|
||||
///
|
||||
/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable.
|
||||
/// All numbers are parsed to doubles.
|
||||
/// </summary>
|
||||
internal class JsonParser
|
||||
{
|
||||
enum Token
|
||||
{
|
||||
None = -1, // Used to denote no Lookahead available
|
||||
Curly_Open,
|
||||
Curly_Close,
|
||||
Squared_Open,
|
||||
Squared_Close,
|
||||
Colon,
|
||||
Comma,
|
||||
String,
|
||||
Number,
|
||||
True,
|
||||
False,
|
||||
Null
|
||||
}
|
||||
|
||||
readonly char[] json;
|
||||
readonly StringBuilder s = new StringBuilder();
|
||||
Token lookAheadToken = Token.None;
|
||||
int index;
|
||||
|
||||
internal JsonParser(string json)
|
||||
{
|
||||
this.json = json.ToCharArray();
|
||||
}
|
||||
|
||||
public object Decode()
|
||||
{
|
||||
return ParseValue();
|
||||
}
|
||||
|
||||
private Dictionary<string, object> ParseObject()
|
||||
{
|
||||
Dictionary<string, object> table = new Dictionary<string, object>();
|
||||
|
||||
ConsumeToken(); // {
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (LookAhead())
|
||||
{
|
||||
|
||||
case Token.Comma:
|
||||
ConsumeToken();
|
||||
break;
|
||||
|
||||
case Token.Curly_Close:
|
||||
ConsumeToken();
|
||||
return table;
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
// name
|
||||
string name = ParseString();
|
||||
|
||||
// :
|
||||
if (NextToken() != Token.Colon)
|
||||
{
|
||||
throw new Exception("Expected colon at index " + index);
|
||||
}
|
||||
|
||||
// value
|
||||
object value = ParseValue();
|
||||
|
||||
table[name] = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SILVERLIGHT
|
||||
private List<object> ParseArray()
|
||||
{
|
||||
List<object> array = new List<object>();
|
||||
#else
|
||||
private ArrayList ParseArray()
|
||||
{
|
||||
ArrayList array = new ArrayList();
|
||||
#endif
|
||||
ConsumeToken(); // [
|
||||
|
||||
while (true)
|
||||
{
|
||||
switch (LookAhead())
|
||||
{
|
||||
|
||||
case Token.Comma:
|
||||
ConsumeToken();
|
||||
break;
|
||||
|
||||
case Token.Squared_Close:
|
||||
ConsumeToken();
|
||||
return array;
|
||||
|
||||
default:
|
||||
{
|
||||
array.Add(ParseValue());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object ParseValue()
|
||||
{
|
||||
switch (LookAhead())
|
||||
{
|
||||
case Token.Number:
|
||||
return ParseNumber();
|
||||
|
||||
case Token.String:
|
||||
return ParseString();
|
||||
|
||||
case Token.Curly_Open:
|
||||
return ParseObject();
|
||||
|
||||
case Token.Squared_Open:
|
||||
return ParseArray();
|
||||
|
||||
case Token.True:
|
||||
ConsumeToken();
|
||||
return true;
|
||||
|
||||
case Token.False:
|
||||
ConsumeToken();
|
||||
return false;
|
||||
|
||||
case Token.Null:
|
||||
ConsumeToken();
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new Exception("Unrecognized token at index" + index);
|
||||
}
|
||||
|
||||
private string ParseString()
|
||||
{
|
||||
ConsumeToken(); // "
|
||||
|
||||
s.Length = 0;
|
||||
|
||||
int runIndex = -1;
|
||||
|
||||
while (index < json.Length)
|
||||
{
|
||||
var c = json[index++];
|
||||
|
||||
if (c == '"')
|
||||
{
|
||||
if (runIndex != -1)
|
||||
{
|
||||
if (s.Length == 0)
|
||||
return new string(json, runIndex, index - runIndex - 1);
|
||||
|
||||
s.Append(json, runIndex, index - runIndex - 1);
|
||||
}
|
||||
return s.ToString();
|
||||
}
|
||||
|
||||
if (c != '\\')
|
||||
{
|
||||
if (runIndex == -1)
|
||||
runIndex = index - 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index == json.Length) break;
|
||||
|
||||
if (runIndex != -1)
|
||||
{
|
||||
s.Append(json, runIndex, index - runIndex - 1);
|
||||
runIndex = -1;
|
||||
}
|
||||
|
||||
switch (json[index++])
|
||||
{
|
||||
case '"':
|
||||
s.Append('"');
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
s.Append('\\');
|
||||
break;
|
||||
|
||||
case '/':
|
||||
s.Append('/');
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
s.Append('\b');
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
s.Append('\f');
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
s.Append('\n');
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
s.Append('\r');
|
||||
break;
|
||||
|
||||
case 't':
|
||||
s.Append('\t');
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
{
|
||||
int remainingLength = json.Length - index;
|
||||
if (remainingLength < 4) break;
|
||||
|
||||
// parse the 32 bit hex into an integer codepoint
|
||||
uint codePoint = ParseUnicode(json[index], json[index + 1], json[index + 2], json[index + 3]);
|
||||
s.Append((char)codePoint);
|
||||
|
||||
// skip 4 chars
|
||||
index += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Unexpectedly reached end of string");
|
||||
}
|
||||
|
||||
private uint ParseSingleChar(char c1, uint multipliyer)
|
||||
{
|
||||
uint p1 = 0;
|
||||
if (c1 >= '0' && c1 <= '9')
|
||||
p1 = (uint)(c1 - '0') * multipliyer;
|
||||
else if (c1 >= 'A' && c1 <= 'F')
|
||||
p1 = (uint)((c1 - 'A') + 10) * multipliyer;
|
||||
else if (c1 >= 'a' && c1 <= 'f')
|
||||
p1 = (uint)((c1 - 'a') + 10) * multipliyer;
|
||||
return p1;
|
||||
}
|
||||
|
||||
private uint ParseUnicode(char c1, char c2, char c3, char c4)
|
||||
{
|
||||
uint p1 = ParseSingleChar(c1, 0x1000);
|
||||
uint p2 = ParseSingleChar(c2, 0x100);
|
||||
uint p3 = ParseSingleChar(c3, 0x10);
|
||||
uint p4 = ParseSingleChar(c4, 1);
|
||||
|
||||
return p1 + p2 + p3 + p4;
|
||||
}
|
||||
|
||||
private string ParseNumber()
|
||||
{
|
||||
ConsumeToken();
|
||||
|
||||
// Need to start back one place because the first digit is also a token and would have been consumed
|
||||
var startIndex = index - 1;
|
||||
|
||||
do
|
||||
{
|
||||
var c = json[index];
|
||||
|
||||
if ((c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E')
|
||||
{
|
||||
if (++index == json.Length) throw new Exception("Unexpected end of string whilst parsing number");
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
return new string(json, startIndex, index - startIndex);
|
||||
}
|
||||
|
||||
private Token LookAhead()
|
||||
{
|
||||
if (lookAheadToken != Token.None) return lookAheadToken;
|
||||
|
||||
return lookAheadToken = NextTokenCore();
|
||||
}
|
||||
|
||||
private void ConsumeToken()
|
||||
{
|
||||
lookAheadToken = Token.None;
|
||||
}
|
||||
|
||||
private Token NextToken()
|
||||
{
|
||||
var result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();
|
||||
|
||||
lookAheadToken = Token.None;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Token NextTokenCore()
|
||||
{
|
||||
char c;
|
||||
|
||||
// Skip past whitespace
|
||||
do
|
||||
{
|
||||
c = json[index];
|
||||
|
||||
if (c > ' ') break;
|
||||
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
|
||||
|
||||
} while (++index < json.Length);
|
||||
|
||||
if (index == json.Length)
|
||||
{
|
||||
throw new Exception("Reached end of string unexpectedly");
|
||||
}
|
||||
|
||||
c = json[index];
|
||||
|
||||
index++;
|
||||
|
||||
//if (c >= '0' && c <= '9')
|
||||
// return Token.Number;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '{':
|
||||
return Token.Curly_Open;
|
||||
|
||||
case '}':
|
||||
return Token.Curly_Close;
|
||||
|
||||
case '[':
|
||||
return Token.Squared_Open;
|
||||
|
||||
case ']':
|
||||
return Token.Squared_Close;
|
||||
|
||||
case ',':
|
||||
return Token.Comma;
|
||||
|
||||
case '"':
|
||||
return Token.String;
|
||||
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case '-': case '+': case '.':
|
||||
return Token.Number;
|
||||
|
||||
case ':':
|
||||
return Token.Colon;
|
||||
|
||||
case 'f':
|
||||
if (json.Length - index >= 4 &&
|
||||
json[index + 0] == 'a' &&
|
||||
json[index + 1] == 'l' &&
|
||||
json[index + 2] == 's' &&
|
||||
json[index + 3] == 'e')
|
||||
{
|
||||
index += 4;
|
||||
return Token.False;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (json.Length - index >= 3 &&
|
||||
json[index + 0] == 'r' &&
|
||||
json[index + 1] == 'u' &&
|
||||
json[index + 2] == 'e')
|
||||
{
|
||||
index += 3;
|
||||
return Token.True;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (json.Length - index >= 3 &&
|
||||
json[index + 0] == 'u' &&
|
||||
json[index + 1] == 'l' &&
|
||||
json[index + 2] == 'l')
|
||||
{
|
||||
index += 3;
|
||||
return Token.Null;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
throw new Exception("Could not find token at index " + --index);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue