##// END OF EJS Templates
refactoring, interactive tarce log almost complete
cin -
r47:b181f7bcb259 interactive logger
parent child
Show More
@@ -0,0 +1,107
1 using Implab.Parallels;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using System.Windows.Forms;
9
10 namespace Implab.Diagnostics.Interactive
11 {
12 public class InteractiveListener: Disposable
13 {
14 TraceForm m_form;
15
16 SynchronizationContext m_syncGuiThread;
17
18 readonly IPromiseBase m_guiFinished;
19 readonly Promise<object> m_guiStarted = new Promise<object>();
20
21 readonly IPromiseBase m_workerFinished = new Promise<object>();
22
23 readonly MTQueue<TraceViewItem> m_queue = new MTQueue<TraceViewItem>();
24 readonly AutoResetEvent m_queueEvent = new AutoResetEvent(false);
25
26 int m_queueLength;
27 bool m_exitPending;
28
29 readonly object m_pauseLock = new object();
30 bool m_paused;
31 readonly ManualResetEvent m_pauseEvent = new ManualResetEvent(true);
32
33 public InteractiveListener() {
34 m_guiFinished = AsyncPool.InvokeNewThread(() => {
35 GuiThread();
36 return 0;
37 });
38
39 m_guiStarted.Join();
40 }
41
42 void GuiThread() {
43 m_form = new TraceForm(); // will create SynchronizationContext
44 m_syncGuiThread = SynchronizationContext.Current;
45 m_guiStarted.Resolve();
46 Application.Run();
47 }
48
49 void QueueThread() {
50 while (!m_exitPending) {
51 if (m_paused)
52 m_pauseEvent.WaitOne();
53
54 TraceViewItem item;
55 if (m_queue.TryDequeue(out item)) {
56 Interlocked.Decrement(ref m_queueLength);
57
58 m_syncGuiThread.Send(x => m_form.AddTraceEvent(item),null);
59 } else {
60 m_queueEvent.WaitOne();
61 }
62 }
63 }
64
65 public void Pause() {
66 // for consistency we need to set this properties atomically
67 lock (m_pauseLock) {
68 m_pauseEvent.Reset();
69 m_paused = true;
70 }
71 }
72
73 public void Resume() {
74 // for consistency we need to set this properties atomically
75 lock (m_pauseLock) {
76 m_paused = false;
77 m_pauseEvent.Set();
78 }
79 }
80
81 void Enqueue(TraceViewItem item) {
82 m_queue.Enqueue(item);
83 if (Interlocked.Increment(ref m_queueLength) == 1)
84 m_queueEvent.Set();
85 }
86
87 public void ShowForm() {
88 m_syncGuiThread.Post(x => m_form.Show(), null);
89 }
90
91 public void HideForm() {
92 m_syncGuiThread.Post(x => m_form.Hide(), null);
93 }
94
95 void Terminate() {
96 m_syncGuiThread.Post(x => Application.ExitThread(), null);
97 }
98
99 protected override void Dispose(bool disposing) {
100 if (disposing) {
101 Terminate();
102 m_guiFinished.Join();
103 }
104 base.Dispose(disposing);
105 }
106 }
107 }
@@ -0,0 +1,10
1 <?xml version="1.0" encoding="utf-8"?>
2 <!--
3 This file is automatically generated by Visual Studio .Net. It is
4 used to store generic object data source configuration information.
5 Renaming the file extension or editing the content of this file may
6 cause the file to be unrecognizable by the program.
7 -->
8 <GenericObjectDataSource DisplayName="TraceViewItem" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
9 <TypeInfo>Implab.Diagnostics.Interactive.TraceViewItem, Implab.Diagnostics.Interactive</TypeInfo>
10 </GenericObjectDataSource> No newline at end of file
@@ -1,83 +1,77
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3 <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4 4 <PropertyGroup>
5 5 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6 6 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7 7 <ProjectGuid>{1DB7DB0C-8AA9-484B-A681-33AE94038391}</ProjectGuid>
8 8 <OutputType>Library</OutputType>
9 9 <AppDesignerFolder>Properties</AppDesignerFolder>
10 10 <RootNamespace>Implab.Diagnostics.Interactive</RootNamespace>
11 11 <AssemblyName>Implab.Diagnostics.Interactive</AssemblyName>
12 12 <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
13 13 <FileAlignment>512</FileAlignment>
14 14 </PropertyGroup>
15 15 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16 16 <DebugSymbols>true</DebugSymbols>
17 17 <DebugType>full</DebugType>
18 18 <Optimize>false</Optimize>
19 19 <OutputPath>bin\Debug\</OutputPath>
20 20 <DefineConstants>DEBUG;TRACE</DefineConstants>
21 21 <ErrorReport>prompt</ErrorReport>
22 22 <WarningLevel>4</WarningLevel>
23 23 </PropertyGroup>
24 24 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25 25 <DebugType>pdbonly</DebugType>
26 26 <Optimize>true</Optimize>
27 27 <OutputPath>bin\Release\</OutputPath>
28 28 <DefineConstants>TRACE</DefineConstants>
29 29 <ErrorReport>prompt</ErrorReport>
30 30 <WarningLevel>4</WarningLevel>
31 31 </PropertyGroup>
32 32 <ItemGroup>
33 33 <Reference Include="System" />
34 34 <Reference Include="System.Core" />
35 35 <Reference Include="System.Drawing" />
36 36 <Reference Include="System.Windows.Forms" />
37 37 <Reference Include="System.Xml.Linq" />
38 38 <Reference Include="System.Data.DataSetExtensions" />
39 39 <Reference Include="Microsoft.CSharp" />
40 40 <Reference Include="System.Data" />
41 41 <Reference Include="System.Xml" />
42 42 </ItemGroup>
43 43 <ItemGroup>
44 <Compile Include="InteractiveTracer.cs" />
44 <Compile Include="InteractiveListener.cs" />
45 45 <Compile Include="Properties\AssemblyInfo.cs" />
46 46 <Compile Include="TextStyle.cs" />
47 47 <Compile Include="TraceForm.cs">
48 48 <SubType>Form</SubType>
49 49 </Compile>
50 50 <Compile Include="TraceForm.Designer.cs">
51 51 <DependentUpon>TraceForm.cs</DependentUpon>
52 52 </Compile>
53 <Compile Include="TraceViewControl.cs">
54 <SubType>UserControl</SubType>
55 </Compile>
56 <Compile Include="TraceViewControl.Designer.cs">
57 <DependentUpon>TraceViewControl.cs</DependentUpon>
58 </Compile>
59 53 <Compile Include="TraceViewItem.cs" />
60 54 </ItemGroup>
61 55 <ItemGroup>
62 <ProjectReference Include="..\external\Implab\Implab.csproj">
56 <ProjectReference Include="..\Implab\Implab.csproj">
63 57 <Project>{f550f1f8-8746-4ad0-9614-855f4c4b7f05}</Project>
64 58 <Name>Implab</Name>
65 59 </ProjectReference>
66 60 </ItemGroup>
67 61 <ItemGroup>
68 62 <EmbeddedResource Include="TraceForm.resx">
69 63 <DependentUpon>TraceForm.cs</DependentUpon>
70 64 </EmbeddedResource>
71 <EmbeddedResource Include="TraceViewControl.resx">
72 <DependentUpon>TraceViewControl.cs</DependentUpon>
73 </EmbeddedResource>
65 </ItemGroup>
66 <ItemGroup>
67 <None Include="Properties\DataSources\TraceViewItem.datasource" />
74 68 </ItemGroup>
75 69 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
76 70 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
77 71 Other similar extension points exist, see Microsoft.Common.targets.
78 72 <Target Name="BeforeBuild">
79 73 </Target>
80 74 <Target Name="AfterBuild">
81 75 </Target>
82 76 -->
83 77 </Project> No newline at end of file
@@ -1,52 +1,122
1 1 namespace Implab.Diagnostics.Interactive {
2 2 partial class TraceForm {
3 3 /// <summary>
4 4 /// Required designer variable.
5 5 /// </summary>
6 6 private System.ComponentModel.IContainer components = null;
7 7
8 8 /// <summary>
9 9 /// Clean up any resources being used.
10 10 /// </summary>
11 11 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
12 12 protected override void Dispose(bool disposing) {
13 13 if (disposing && (components != null)) {
14 14 components.Dispose();
15 15 }
16 16 base.Dispose(disposing);
17 17 }
18 18
19 19 #region Windows Form Designer generated code
20 20
21 21 /// <summary>
22 22 /// Required method for Designer support - do not modify
23 23 /// the contents of this method with the code editor.
24 24 /// </summary>
25 25 private void InitializeComponent() {
26 this.traceViewControl1 = new Implab.Diagnostics.Interactive.TraceViewControl();
26 this.components = new System.ComponentModel.Container();
27 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
28 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
29 System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
30 this.eventsDataGrid = new System.Windows.Forms.DataGridView();
31 this.traceViewItemBindingSource = new System.Windows.Forms.BindingSource(this.components);
32 this.threadDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
33 this.messageDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
34 ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).BeginInit();
35 ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).BeginInit();
27 36 this.SuspendLayout();
28 37 //
29 // traceViewControl1
38 // eventsDataGrid
30 39 //
31 this.traceViewControl1.Location = new System.Drawing.Point(13, 13);
32 this.traceViewControl1.Name = "traceViewControl1";
33 this.traceViewControl1.Size = new System.Drawing.Size(267, 248);
34 this.traceViewControl1.TabIndex = 0;
40 this.eventsDataGrid.AllowUserToAddRows = false;
41 this.eventsDataGrid.AllowUserToDeleteRows = false;
42 this.eventsDataGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
43 | System.Windows.Forms.AnchorStyles.Left)
44 | System.Windows.Forms.AnchorStyles.Right)));
45 this.eventsDataGrid.AutoGenerateColumns = false;
46 this.eventsDataGrid.BackgroundColor = System.Drawing.SystemColors.Window;
47 dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
48 dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(224)))), ((int)(((byte)(224)))), ((int)(((byte)(224)))));
49 dataGridViewCellStyle1.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
50 dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
51 dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
52 dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
53 dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
54 this.eventsDataGrid.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
55 this.eventsDataGrid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
56 this.eventsDataGrid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
57 this.threadDataGridViewTextBoxColumn,
58 this.messageDataGridViewTextBoxColumn});
59 this.eventsDataGrid.DataSource = this.traceViewItemBindingSource;
60 dataGridViewCellStyle3.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
61 dataGridViewCellStyle3.BackColor = System.Drawing.SystemColors.Window;
62 dataGridViewCellStyle3.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
63 dataGridViewCellStyle3.ForeColor = System.Drawing.SystemColors.ControlText;
64 dataGridViewCellStyle3.SelectionBackColor = System.Drawing.SystemColors.Highlight;
65 dataGridViewCellStyle3.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
66 dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
67 this.eventsDataGrid.DefaultCellStyle = dataGridViewCellStyle3;
68 this.eventsDataGrid.Location = new System.Drawing.Point(12, 12);
69 this.eventsDataGrid.Name = "eventsDataGrid";
70 this.eventsDataGrid.ReadOnly = true;
71 this.eventsDataGrid.RowHeadersWidth = 17;
72 this.eventsDataGrid.RowTemplate.Resizable = System.Windows.Forms.DataGridViewTriState.False;
73 this.eventsDataGrid.Size = new System.Drawing.Size(939, 480);
74 this.eventsDataGrid.TabIndex = 1;
75 this.eventsDataGrid.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.eventsDataGrid_CellFormatting);
76 //
77 // traceViewItemBindingSource
78 //
79 this.traceViewItemBindingSource.DataSource = typeof(Implab.Diagnostics.Interactive.TraceViewItem);
80 //
81 // threadDataGridViewTextBoxColumn
82 //
83 this.threadDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.AllCellsExceptHeader;
84 this.threadDataGridViewTextBoxColumn.DataPropertyName = "Thread";
85 this.threadDataGridViewTextBoxColumn.HeaderText = "TID";
86 this.threadDataGridViewTextBoxColumn.Name = "threadDataGridViewTextBoxColumn";
87 this.threadDataGridViewTextBoxColumn.ReadOnly = true;
88 this.threadDataGridViewTextBoxColumn.Width = 5;
89 //
90 // messageDataGridViewTextBoxColumn
91 //
92 this.messageDataGridViewTextBoxColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
93 this.messageDataGridViewTextBoxColumn.DataPropertyName = "FormattedMessage";
94 dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
95 this.messageDataGridViewTextBoxColumn.DefaultCellStyle = dataGridViewCellStyle2;
96 this.messageDataGridViewTextBoxColumn.HeaderText = "Message";
97 this.messageDataGridViewTextBoxColumn.Name = "messageDataGridViewTextBoxColumn";
98 this.messageDataGridViewTextBoxColumn.ReadOnly = true;
35 99 //
36 100 // TraceForm
37 101 //
38 102 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
39 103 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
40 this.ClientSize = new System.Drawing.Size(292, 273);
41 this.Controls.Add(this.traceViewControl1);
104 this.ClientSize = new System.Drawing.Size(963, 504);
105 this.Controls.Add(this.eventsDataGrid);
42 106 this.Name = "TraceForm";
43 107 this.Text = "TraceForm";
108 ((System.ComponentModel.ISupportInitialize)(this.eventsDataGrid)).EndInit();
109 ((System.ComponentModel.ISupportInitialize)(this.traceViewItemBindingSource)).EndInit();
44 110 this.ResumeLayout(false);
45 111
46 112 }
47 113
48 114 #endregion
49 115
50 private TraceViewControl traceViewControl1;
116 private System.Windows.Forms.DataGridView eventsDataGrid;
117 private System.Windows.Forms.BindingSource traceViewItemBindingSource;
118 private System.Windows.Forms.DataGridViewTextBoxColumn threadDataGridViewTextBoxColumn;
119 private System.Windows.Forms.DataGridViewTextBoxColumn messageDataGridViewTextBoxColumn;
120
51 121 }
52 122 } No newline at end of file
@@ -1,25 +1,58
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.ComponentModel;
4 4 using System.Data;
5 5 using System.Drawing;
6 6 using System.Linq;
7 7 using System.Text;
8 8 using System.Threading.Tasks;
9 9 using System.Windows.Forms;
10 10
11 11 namespace Implab.Diagnostics.Interactive {
12 12 public partial class TraceForm : Form {
13 readonly Dictionary<int, Color> m_threadColors = new Dictionary<int,Color>();
14 readonly Random m_rand = new Random();
15
13 16 public TraceForm() {
14 17 InitializeComponent();
18
15 19 }
16 20
17 21 protected override void OnFormClosing(FormClosingEventArgs e) {
18 22 base.OnFormClosing(e);
19 23 if (!e.Cancel && e.CloseReason == CloseReason.UserClosing) {
20 24 e.Cancel = true;
21 25 Hide();
22 26 }
23 27 }
28
29 public void AddTraceEvent(int indent, int thread, string message) {
30 traceViewItemBindingSource.Add(new TraceViewItem {
31 Indent = indent,
32 Thread = thread,
33 Message = message,
34 Timestamp = Environment.TickCount
35 });
36
37 }
38
39 public void AddTraceEvent(TraceViewItem item) {
40 traceViewItemBindingSource.Add(item);
41 }
42
43 Color GetThreadColor(int thread) {
44 Color result;
45 if (!m_threadColors.TryGetValue(thread, out result)) {
46 result = Color.FromArgb(m_rand.Next(4)*64, m_rand.Next(4)*64, m_rand.Next(4)*64);
47 m_threadColors[thread] = result;
48 }
49 return result;
50 }
51
52 private void eventsDataGrid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) {
53 var data = (TraceViewItem)traceViewItemBindingSource[e.RowIndex];
54 e.CellStyle.Padding = new Padding(data.Indent * 10,0,0,0);
55 e.CellStyle.ForeColor = GetThreadColor(data.Thread);
24 56 }
25 57 }
58 }
@@ -1,120 +1,123
1 1 <?xml version="1.0" encoding="utf-8"?>
2 2 <root>
3 3 <!--
4 4 Microsoft ResX Schema
5 5
6 6 Version 2.0
7 7
8 8 The primary goals of this format is to allow a simple XML format
9 9 that is mostly human readable. The generation and parsing of the
10 10 various data types are done through the TypeConverter classes
11 11 associated with the data types.
12 12
13 13 Example:
14 14
15 15 ... ado.net/XML headers & schema ...
16 16 <resheader name="resmimetype">text/microsoft-resx</resheader>
17 17 <resheader name="version">2.0</resheader>
18 18 <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
19 19 <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
20 20 <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
21 21 <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
22 22 <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
23 23 <value>[base64 mime encoded serialized .NET Framework object]</value>
24 24 </data>
25 25 <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
26 26 <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
27 27 <comment>This is a comment</comment>
28 28 </data>
29 29
30 30 There are any number of "resheader" rows that contain simple
31 31 name/value pairs.
32 32
33 33 Each data row contains a name, and value. The row also contains a
34 34 type or mimetype. Type corresponds to a .NET class that support
35 35 text/value conversion through the TypeConverter architecture.
36 36 Classes that don't support this are serialized and stored with the
37 37 mimetype set.
38 38
39 39 The mimetype is used for serialized objects, and tells the
40 40 ResXResourceReader how to depersist the object. This is currently not
41 41 extensible. For a given mimetype the value must be set accordingly:
42 42
43 43 Note - application/x-microsoft.net.object.binary.base64 is the format
44 44 that the ResXResourceWriter will generate, however the reader can
45 45 read any of the formats listed below.
46 46
47 47 mimetype: application/x-microsoft.net.object.binary.base64
48 48 value : The object must be serialized with
49 49 : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
50 50 : and then encoded with base64 encoding.
51 51
52 52 mimetype: application/x-microsoft.net.object.soap.base64
53 53 value : The object must be serialized with
54 54 : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
55 55 : and then encoded with base64 encoding.
56 56
57 57 mimetype: application/x-microsoft.net.object.bytearray.base64
58 58 value : The object must be serialized into a byte array
59 59 : using a System.ComponentModel.TypeConverter
60 60 : and then encoded with base64 encoding.
61 61 -->
62 62 <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
63 63 <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
64 64 <xsd:element name="root" msdata:IsDataSet="true">
65 65 <xsd:complexType>
66 66 <xsd:choice maxOccurs="unbounded">
67 67 <xsd:element name="metadata">
68 68 <xsd:complexType>
69 69 <xsd:sequence>
70 70 <xsd:element name="value" type="xsd:string" minOccurs="0" />
71 71 </xsd:sequence>
72 72 <xsd:attribute name="name" use="required" type="xsd:string" />
73 73 <xsd:attribute name="type" type="xsd:string" />
74 74 <xsd:attribute name="mimetype" type="xsd:string" />
75 75 <xsd:attribute ref="xml:space" />
76 76 </xsd:complexType>
77 77 </xsd:element>
78 78 <xsd:element name="assembly">
79 79 <xsd:complexType>
80 80 <xsd:attribute name="alias" type="xsd:string" />
81 81 <xsd:attribute name="name" type="xsd:string" />
82 82 </xsd:complexType>
83 83 </xsd:element>
84 84 <xsd:element name="data">
85 85 <xsd:complexType>
86 86 <xsd:sequence>
87 87 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
88 88 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
89 89 </xsd:sequence>
90 90 <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
91 91 <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
92 92 <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
93 93 <xsd:attribute ref="xml:space" />
94 94 </xsd:complexType>
95 95 </xsd:element>
96 96 <xsd:element name="resheader">
97 97 <xsd:complexType>
98 98 <xsd:sequence>
99 99 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
100 100 </xsd:sequence>
101 101 <xsd:attribute name="name" type="xsd:string" use="required" />
102 102 </xsd:complexType>
103 103 </xsd:element>
104 104 </xsd:choice>
105 105 </xsd:complexType>
106 106 </xsd:element>
107 107 </xsd:schema>
108 108 <resheader name="resmimetype">
109 109 <value>text/microsoft-resx</value>
110 110 </resheader>
111 111 <resheader name="version">
112 112 <value>2.0</value>
113 113 </resheader>
114 114 <resheader name="reader">
115 115 <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
116 116 </resheader>
117 117 <resheader name="writer">
118 118 <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119 119 </resheader>
120 <metadata name="traceViewItemBindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
121 <value>17, 17</value>
122 </metadata>
120 123 </root> No newline at end of file
@@ -1,14 +1,25
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5 using System.Threading.Tasks;
6 6
7 7 namespace Implab.Diagnostics.Interactive {
8 public struct TraceViewItem {
9 public string message;
10 public int timestamp;
11 public int indent;
12 public int thread;
8 public class TraceViewItem {
9 string m_formattedValue;
10
11 public string Message { get; set; }
12 public int Timestamp { get; set; }
13 public int Indent { get; set; }
14 public int Thread { get; set; }
15
16 public string FormattedMessage {
17 get {
18 if (m_formattedValue == null) {
19 m_formattedValue = Message.Replace("\r",String.Empty).Replace("\n", " | ");
20 }
21 return m_formattedValue;
13 22 }
14 23 }
24 }
25 }
@@ -1,44 +1,46
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.IO;
4 4 using System.Linq;
5 5 using System.Text;
6 6
7 7 namespace Implab.Diagnostics {
8 8 public class TextFileListener: TextListenerBase {
9 9 readonly TextWriter m_textWriter;
10 10
11 11 public TextFileListener(string fileName, bool local) : base(local) {
12 12 m_textWriter = File.CreateText(fileName);
13 13
14 14 m_textWriter.WriteLine("LOG {0}", DateTime.Now);
15 15 Register(this);
16 16 }
17 17
18 18 protected override void WriteEntry(TraceContext context, EventText text) {
19 19 var msg = new StringBuilder();
20 20 for (int i = 0; i < text.indent; i++)
21 21 msg.Append(" ");
22 22 msg.AppendFormat("[{0}]: {1}", context.ThreadId, text.content);
23 23
24 24 lock (m_textWriter) {
25 25 if (!IsDisposed) {
26 // тут гарантировано еще не освобожден m_textWriter
26 27 m_textWriter.WriteLine(msg.ToString());
27 28 m_textWriter.Flush();
28 29 }
29 30 }
30 31 }
31 32
32 33
33 34 protected override void Dispose(bool disposing) {
34 35 base.Dispose(disposing);
35 36 if (disposing) {
37 // IsDisposed = true
36 38 lock (m_textWriter) {
37 39 Safe.Dispose(m_textWriter);
38 40 }
39 41 }
40 42 }
41 43
42 44
43 45 }
44 46 }
@@ -1,119 +1,128
1 1 using System;
2 2 using System.Collections.Generic;
3 3 using System.Linq;
4 4 using System.Text;
5 5
6 6 namespace Implab.Diagnostics {
7 7 public abstract class TextListenerBase : ServiceLocator, IEventTextFormatter<object>, IEventTextFormatter<TraceEvent> {
8 8
9 9 readonly Dictionary<object, Action> m_subscriptions = new Dictionary<object, Action>();
10 10 readonly LogicalOperation m_boundOperation;
11 11 readonly int m_baseIndent;
12 12
13 13 protected TextListenerBase(bool local) {
14 14 Register(this);
15 15 if (local) {
16 16 m_boundOperation = TraceContext.Current.CurrentOperation;
17 17 m_baseIndent = Math.Max(0, m_boundOperation.Level - 1);
18 18 }
19 19 }
20 20
21 21 public void Subscribe(Type eventType) {
22 22 if (eventType == null)
23 23 throw new ArgumentNullException("eventType");
24 24 GetType().GetMethod("Subscribe", new Type[0]).MakeGenericMethod(eventType).Invoke(this, null);
25 25 }
26 26
27 27 public void Subscribe<TEvent>() {
28 28 Subscribe<TEvent>(LogChannel<TEvent>.Default);
29 29 }
30 30
31 31 public void Subscribe<TEvent>(LogChannel<TEvent> channel) {
32 32 if (channel == null)
33 33 throw new ArgumentNullException("channel");
34 34
35 35 lock (m_subscriptions) {
36 36 AssertNotDisposed();
37 37
38 38 var formatter = GetService<IEventTextFormatter<TEvent>>();
39 39
40 40 EventHandler<ValueEventArgs<TEvent>> handler = (sender, args) => {
41 41 TraceContext context = (TraceContext)sender;
42 42 var text = formatter.Format(context, args.Value);
43 43 text.indent -= m_baseIndent;
44 44
45 45 if (IsRelated(context.CurrentOperation))
46 46 WriteEntry(context, text);
47 47 };
48 48
49 49 if (m_subscriptions.ContainsKey(channel))
50 50 return;
51 51
52 52 channel.Events += handler;
53 53
54 54 Action unsubscribe = () => {
55 55 channel.Events -= handler;
56 56 };
57 57
58 58 m_subscriptions.Add(channel, unsubscribe);
59 59 }
60 60 }
61 61
62 62 public bool IsRelated(LogicalOperation op) {
63 63 if (m_boundOperation == null)
64 64 return true;
65 65
66 66 while (op != m_boundOperation && op.Level > m_boundOperation.Level)
67 67 op = op.Parent;
68 68 return op == m_boundOperation;
69 69 }
70 70
71 71 public void Unsubscribe<TEvent>(LogChannel<TEvent> channel) {
72 72 if (channel == null)
73 73 throw new ArgumentNullException("channel");
74 74
75 75 lock (m_subscriptions) {
76 76 Action subscription;
77 77 if (m_subscriptions.TryGetValue(channel, out subscription)) {
78 78 subscription();
79 79 m_subscriptions.Remove(channel);
80 80 }
81 81 }
82 82 }
83 83
84 84 public void UnsubscribeAll() {
85 85 lock (m_subscriptions) {
86 86 foreach (var subscription in m_subscriptions.Values)
87 87 subscription();
88 88 m_subscriptions.Clear();
89 89 }
90 90 }
91 91
92 /// <summary>
93 /// Вызывается для записи текста сообщения, в журнал.
94 /// </summary>
95 /// <remarks>
96 /// Данный метод может вызваться из разных потоков одновременно. Возможна ситуация, когда
97 /// данный метод вызывается уже после освобождения ообъекта методом <see cref="Dispose()"/>.
98 /// </remarks>
99 /// <param name="context">Контекст трассировки.</param>
100 /// <param name="text">Текст сообщения.</param>
92 101 protected abstract void WriteEntry(TraceContext context, EventText text);
93 102
94 103 public EventText Format(TraceContext context, object data) {
95 104 return new EventText {
96 105 indent = context.CurrentOperation.Level,
97 106 content = data.ToString()
98 107 };
99 108 }
100 109
101 110 public EventText Format(TraceContext context, TraceEvent data) {
102 111 var level = context.CurrentOperation.Level;
103 112 if (data.EventType == TraceEventType.OperationCompleted || data.EventType == TraceEventType.OperationStarted)
104 113 level--;
105 114
106 115 return new EventText {
107 116 indent = level,
108 117 content = data.ToString()
109 118 };
110 119 }
111 120
112 121 protected override void Dispose(bool disposing) {
122 base.Dispose(disposing);
113 123 if (disposing) {
114 124 UnsubscribeAll();
115 125 }
116 base.Dispose(disposing);
117 126 }
118 127 }
119 128 }
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now