/// <summary> /// Binary writes a multicast log entry. /// </summary> /// <param name="w">Binary writer to use.</param> /// <param name="monitorId">Identifier of the monitor.</param> /// <param name="previousEntryType">Log type of the previous entry in the monitor..</param> /// <param name="previousLogTime">Time stamp of the previous entry in the monitor.</param> /// <param name="depth">Depth of the line (number of opened groups above).</param> /// <param name="isOpenGroup">True if this the opening of a group. False for a line.</param> /// <param name="text">Text of the log entry.</param> /// <param name="level">Log level of the log entry.</param> /// <param name="logTime">Time stamp of the log entry.</param> /// <param name="tags">Tags of the log entry</param> /// <param name="ex">Exception of the log entry.</param> /// <param name="fileName">Source file name of the log entry</param> /// <param name="lineNumber">Source line number of the log entry</param> static public void WriteLog(CKBinaryWriter w, Guid monitorId, LogEntryType previousEntryType, DateTimeStamp previousLogTime, int depth, bool isOpenGroup, LogLevel level, DateTimeStamp logTime, string text, CKTrait tags, CKExceptionData ex, string fileName, int lineNumber) { if (w == null) { throw new ArgumentNullException("w"); } StreamLogType type = StreamLogType.IsMultiCast | (isOpenGroup ? StreamLogType.TypeOpenGroup : StreamLogType.TypeLine); type = UpdateTypeWithPrevious(type, previousEntryType, ref previousLogTime); DoWriteLog(w, type, level, logTime, text, tags, ex, fileName, lineNumber); WriteMulticastFooter(w, monitorId, previousEntryType, previousLogTime, depth); }
static void ReadLogTypeAndLevel( BinaryReader r, out StreamLogType t, out LogLevel l ) { Debug.Assert( (int)StreamLogType.MaxFlag < (1 << 16) ); Debug.Assert( (int)LogLevel.NumberOfBits < 8 ); t = StreamLogType.EndOfStream; l = LogLevel.Trace; byte level = r.ReadByte(); // Found the 0 end marker? if( level != 0 ) { if( level >= (1 << (int)LogLevel.NumberOfBits) ) throw new InvalidDataException(); l = (LogLevel)level; ushort type = r.ReadUInt16(); if( type >= ((int)StreamLogType.MaxFlag * 2 - 1) ) throw new InvalidDataException(); t = (StreamLogType)type; } }
static void WriteLogTypeAndLevel( BinaryWriter w, StreamLogType t, LogLevel level ) { Debug.Assert( (int)StreamLogType.MaxFlag < (1 << 16) ); Debug.Assert( (int)LogLevel.NumberOfBits < 8 ); w.Write( (byte)level ); if( !StringAndStringBuilderExtension.IsCRLF ) t |= StreamLogType.IsLFOnly; w.Write( (ushort)t ); }
static ILogEntry ReadGroupClosed( int streamVersion, CKBinaryReader r, StreamLogType t, LogLevel logLevel ) { DateTimeStamp time = new DateTimeStamp( DateTime.FromBinary( r.ReadInt64() ), (t & StreamLogType.HasUniquifier) != 0 ? r.ReadByte() : (Byte)0 ); ActivityLogGroupConclusion[] conclusions = Util.Array.Empty<ActivityLogGroupConclusion>(); if( (t & StreamLogType.HasConclusions) != 0 ) { int conclusionsCount = streamVersion < 6 ? r.ReadInt32() : r.ReadNonNegativeSmallInt32(); conclusions = new ActivityLogGroupConclusion[conclusionsCount]; for( int i = 0; i < conclusionsCount; i++ ) { CKTrait cTags = ActivityMonitor.Tags.Register( r.ReadString() ); string cText = r.ReadString(); conclusions[i] = new ActivityLogGroupConclusion( cText, cTags ); } } if( (t & StreamLogType.IsMultiCast) == 0 ) { return new LECloseGroup( time, logLevel, conclusions ); } Guid mId; int depth; LogEntryType prevType; DateTimeStamp prevTime; ReadMulticastFooter( streamVersion, r, t, out mId, out depth, out prevType, out prevTime ); return new LEMCCloseGroup( mId, depth, prevTime, prevType, time, logLevel, conclusions ); }
static void ReadMulticastFooter( int streamVersion, CKBinaryReader r, StreamLogType t, out Guid mId, out int depth, out LogEntryType prevType, out DateTimeStamp prevTime ) { Debug.Assert( Guid.Empty.ToByteArray().Length == 16 ); mId = new Guid( r.ReadBytes( 16 ) ); depth = streamVersion < 6 ? r.ReadInt32() : r.ReadNonNegativeSmallInt32(); if( depth < 0 ) throw new InvalidDataException(); prevType = LogEntryType.None; prevTime = DateTimeStamp.Unknown; if( (t & StreamLogType.IsPreviousKnown) != 0 ) { prevTime = new DateTimeStamp( DateTime.FromBinary( r.ReadInt64() ), (t & StreamLogType.IsPreviousKnownHasUniquifier) != 0 ? r.ReadByte() : (Byte)0 ); prevType = (LogEntryType)r.ReadByte(); } }
static void DoWriteCloseGroup( CKBinaryWriter w, StreamLogType t, LogLevel level, DateTimeStamp closeTime, IReadOnlyList<ActivityLogGroupConclusion> conclusions ) { if( conclusions != null && conclusions.Count > 0 ) t |= StreamLogType.HasConclusions; if( closeTime.Uniquifier != 0 ) t |= StreamLogType.HasUniquifier; WriteLogTypeAndLevel( w, t, level ); w.Write( closeTime.TimeUtc.ToBinary() ); if( closeTime.Uniquifier != 0 ) w.Write( closeTime.Uniquifier ); if( (t & StreamLogType.HasConclusions) != 0 ) { w.WriteNonNegativeSmallInt32( conclusions.Count ); foreach( ActivityLogGroupConclusion c in conclusions ) { w.Write( c.Tag.ToString() ); w.Write( c.Text ); } } }
static StreamLogType UpdateTypeWithPrevious( StreamLogType type, LogEntryType previousEntryType, ref DateTimeStamp previousStamp ) { if( previousStamp.IsKnown ) { type |= StreamLogType.IsPreviousKnown; if( previousEntryType == LogEntryType.None ) throw new ArgumentException( "Must not be None since previousStamp is known.", "previousEntryType" ); if( previousStamp.Uniquifier != 0 ) type |= StreamLogType.IsPreviousKnownHasUniquifier; } return type; }
static void DoWriteLog( CKBinaryWriter w, StreamLogType t, LogLevel level, DateTimeStamp logTime, string text, CKTrait tags, CKExceptionData ex, string fileName, int lineNumber ) { if( tags != null && !tags.IsEmpty ) t |= StreamLogType.HasTags; if( ex != null ) { t |= StreamLogType.HasException; if( text == ex.Message ) t |= StreamLogType.IsTextTheExceptionMessage; } if( fileName != null ) t |= StreamLogType.HasFileName; if( logTime.Uniquifier != 0 ) t |= StreamLogType.HasUniquifier; WriteLogTypeAndLevel( w, t, level ); w.Write( logTime.TimeUtc.ToBinary() ); if( logTime.Uniquifier != 0 ) w.Write( logTime.Uniquifier ); if( (t & StreamLogType.HasTags) != 0 ) w.Write( tags.ToString() ); if( (t & StreamLogType.HasFileName) != 0 ) { w.Write( fileName ); w.WriteNonNegativeSmallInt32( lineNumber ); } if( (t & StreamLogType.HasException) != 0 ) ex.Write( w ); if( (t & StreamLogType.IsTextTheExceptionMessage) == 0 ) w.Write( text ); }