internal ExceptionTargetSite(StackTrace trace)
        {
            Debug.Assert(trace != null);
            Debug.Assert(trace.FrameCount > 0);

            var frame = trace.GetFrame(0);
            Debug.Assert(frame != null);

            var method = frame.GetMethod();
            Debug.Assert(method != null);

            AssemblyName = method.DeclaringType.Assembly.FullName;
            TypeName = method.DeclaringType.FullName;
            MethodName = method.Name;
            ILOffset = frame.GetILOffset();
            FileName = frame.GetFileName();
            FileLineNumber = frame.GetFileLineNumber();
            FileColumnNumber = frame.GetFileColumnNumber();

            TargetSiteID = Hash.SHA1(GetHashableData());
        }
Exemple #2
0
        /// <summary>
        /// Logs all name/value pairs as a single collection using concurrent MERGE statements.
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="exCollectionID"></param>
        /// <param name="coll"></param>
        /// <returns></returns>
        async Task LogCollection(SqlConnectionContext conn, SHA1Hash exCollectionID, IDictionary<string, string> coll)
        {
            // The exCollectionID should be pre-calculated by `CalcCollectionID`.

            // Check if the exCollectionID exists already:
            int? collectionCount = await conn.ExecReader(
@"SELECT COUNT(exCollectionID) FROM [dbo].[exCollectionKeyValue] WHERE [exCollectionID] = @exCollectionID",
                prms =>
                    prms.AddInParamSHA1("@exCollectionID", exCollectionID),
                    async dr => await dr.ReadAsync() ? dr.GetInt32(0) : (int?)null
            );

            // Don't bother logging name-value pairs if the collection already exists:
            if (!collectionCount.HasValue) return;
            if (collectionCount.Value == coll.Count) return;

            const int numTasksPerPair = 2;

            // Create an array of tasks to wait upon:
            var tasks = new Task[coll.Count * numTasksPerPair];

            // Fill out the array of tasks with concurrent MERGE statements for each name/value pair:
            using (var en = coll.Keys.GetEnumerator())
                for (int i = 0; en.MoveNext(); ++i)
                {
                    string name = en.Current;
                    string value = coll[name];

                    var exCollectionValueID = Hash.SHA1(value);

                    // Merge the Value record:
                    tasks[i * numTasksPerPair + 0] = conn.ExecNonQuery(
    @"MERGE [dbo].[exCollectionValue] WITH (HOLDLOCK) AS target
USING (SELECT @exCollectionValueID) AS source (exCollectionValueID)
ON (target.exCollectionValueID = source.exCollectionValueID)
WHEN NOT MATCHED THEN
    INSERT ([exCollectionValueID], [Value])
    VALUES (@exCollectionValueID,  @Value );",
                        prms =>
                            prms.AddInParamSHA1("@exCollectionValueID", exCollectionValueID)
                                .AddInParamSize("@Value", SqlDbType.VarChar, -1, value)
                    );

                    // Merge the Name-Value record:
                    tasks[i * numTasksPerPair + 1] = conn.ExecNonQuery(
    @"MERGE [dbo].[exCollectionKeyValue] WITH (HOLDLOCK) AS target
USING (SELECT @exCollectionID, @Name, @exCollectionValueID) AS source (exCollectionID, Name, exCollectionValueID)
ON (target.exCollectionID = source.exCollectionID AND target.Name = source.Name AND target.exCollectionValueID = source.exCollectionValueID)
WHEN NOT MATCHED THEN
    INSERT ([exCollectionID], [Name], [exCollectionValueID])
    VALUES (@exCollectionID,  @Name,  @exCollectionValueID );",
                        prms =>
                            prms.AddInParamSHA1("@exCollectionID", exCollectionID)
                                .AddInParamSize("@Name", SqlDbType.VarChar, 96, name)
                                .AddInParamSHA1("@exCollectionValueID", exCollectionValueID)
                    );
                }

            // Our final task's completion depends on all the tasks created thus far:
            await Task.WhenAll(tasks);
        }
        /// <summary>
        /// Represents a thrown exception and some context.
        /// </summary>
        /// <param name="ex">The exception that was thrown.</param>
        /// <param name="isHandled">Whether the exception is explicitly handled or not.</param>
        /// <param name="correlationID">A unique identifier to tie two or more exception reports together.</param>
        /// <param name="webHostingContext">The current web application hosting context, if applicable.</param>
        /// <param name="capturedHttpContext">Captured values from the current HTTP context being handled, if applicable.</param>
        public ExceptionWithCapturedContext(
            Exception ex,
            bool isHandled = false,
            Guid? correlationID = null,
            WebHostingContext webHostingContext = null,
            CapturedHttpContext capturedHttpContext = null
            )
        {
            // Check for a WrappedException to pull out custom Exception info:
            WrappedException wex = ex as WrappedException;
            Exception thrownEx = ex;
            if (wex != null)
            {
                UserState = wex.UserState;
                ex = wex.Wrapped;
            }

            Exception = ex;

            IsHandled = isHandled;
            CorrelationID = correlationID;
            WebHostingContext = webHostingContext;
            CapturedHttpContext = capturedHttpContext;

            RealStackTrace = new StackTrace(thrownEx, true);

            LoggedTimeUTC = DateTime.UtcNow;
            ManagedThreadID = Thread.CurrentThread.ManagedThreadId;
            SequenceNumber = Interlocked.Increment(ref runningSequenceNumber);

            // Capture some details about the exception:
            var exType = ex.GetType();
            AssemblyName = exType.Assembly.FullName;
            TypeName = exType.FullName;
            // TODO(jsd): Sanitize embedded file paths in stack trace
            StackTrace = thrownEx.StackTrace;

            // SHA1 hash the `assemblyName:typeName:stackTrace[:targetSite]`:
            string hashableData = String.Concat(AssemblyName, ":", TypeName, ":", StackTrace);

            if (RealStackTrace != null && RealStackTrace.FrameCount > 0)
            {
                // Add in TargetSite data:
                TargetSite = new ExceptionTargetSite(RealStackTrace);
                hashableData += ":" + TargetSite.GetHashableData();
            }

            ExceptionID = Hash.SHA1(hashableData);

            if (ex.InnerException != null)
                InnerException = new ExceptionWithCapturedContext(ex.InnerException, isHandled, correlationID, webHostingContext, capturedHttpContext);
        }
 public HashedLogIdentifier(SHA1Hash sha1hash, int instanceID)
 {
     _sha1hash = sha1hash;
     _instanceID = instanceID;
 }