For classifying error reports, I need to generate an ID from an exception. That ID should be
- (more or less) unique
- a short alpha numeric string
- equal for equivalent exceptions (even on different systems)
The following code seems to do the job:
public static string GetExceptionID(this Exception ex)
{
if (ex == null) return "0000";
int hash = 31;
var innerException = ex;
while (innerException != null)
{
hash ^= GetHash(innerException.GetType().ToString());
hash ^= innerException.StackTrace
.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
// If *.pdb file is provided, the file and line no. (e.g. "... in C:\Path...") is part of the stacktrace.
// The next line cutting off that part
.Select(line => line.Substring(0, line.IndexOf(" in ") < 0 ? line.Length : line.IndexOf(" in ")))
.Aggregate(31, (currentHash, val) => currentHash ^= val.GetHash());
innerException = innerException.InnerException;
}
return Convert.ToBase64String(BitConverter.GetBytes(hash))
.Replace('+', 'P')
.Replace('-', 'M')
.Replace("=", "")
.ToUpper();
}
// https://en.wikipedia.org/wiki/Jenkins_hash_function
private static int GetHash(this string str)
{
if (str == null) return 1;
int hash = 31;
foreach (char c in str)
{
unchecked
{
hash += c;
hash += hash << 10;
hash ^= hash >> 6;
}
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
Do you see any problems with the code?