c9e2489b29393e9730a9ffc4139f9e9153fbab40
[mono.git] / mcs / class / System.Web / System.Web / TraceData.cs
1 //
2 // System.Web.TraceData
3 //
4 // Author(s):
5 //  Jackson Harper (jackson@ximian.com)
6 //
7 // (C) 2004 Novell, Inc (http://www.novell.com)
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31
32 using System;
33 using System.Collections;
34 using System.IO;
35 using System.Text;
36 using System.Web.UI;
37 using System.Web.UI.WebControls;
38
39 #if NET_2_0
40 using System.Collections.Generic;
41 #endif
42
43 namespace System.Web {
44
45         class InfoTraceData
46         {
47                 public string Category;
48                 public string Message;
49                 public string Exception;
50                 public double TimeSinceFirst;
51                 public double TimeSinceLast;
52                 public bool IsWarning;
53
54                 public InfoTraceData (string category, string message, string exception, double timeSinceFirst, double timeSinceLast, bool isWarning)
55                 {
56                         this.Category = category;
57                         this.Message = message;
58                         this.Exception = exception;
59                         this.TimeSinceFirst = timeSinceFirst;
60                         this.TimeSinceLast = timeSinceLast;
61                         this.IsWarning = isWarning;
62                 }
63         }
64
65         class ControlTraceData
66         {
67                 public string ControlId;
68                 public Type Type;
69                 public int RenderSize;
70                 public int ViewstateSize;
71                 public int Depth;
72 #if NET_2_0
73                 public int ControlstateSize;
74 #endif
75
76 #if NET_2_0
77                 public ControlTraceData (string controlId, Type type, int renderSize, int viewstateSize, int controlstateSize, int depth)
78 #else
79                 public ControlTraceData (string controlId, Type type, int renderSize, int viewstateSize, int depth)
80 #endif
81                 {
82                         this.ControlId = controlId;
83                         this.Type = type;
84                         this.RenderSize = renderSize;
85                         this.ViewstateSize = viewstateSize;
86                         this.Depth = depth;
87 #if NET_2_0
88                         this.ControlstateSize = controlstateSize;
89 #endif
90                 }
91         }
92
93         class NameValueTraceData
94         {
95                 public string Name;
96                 public string Value;
97
98                 public NameValueTraceData (string name, string value)
99                 {
100                         this.Name = name;
101                         this.Value = value;
102                 }
103         }
104         
105         internal class TraceData {
106
107                 bool is_first_time;
108                 DateTime first_time;
109                 double prev_time;
110
111 #if NET_2_0
112                 Queue <InfoTraceData> info;
113                 Queue <ControlTraceData> control_data;
114                 Queue <NameValueTraceData> cookie_data;
115                 Queue <NameValueTraceData> header_data;
116                 Queue <NameValueTraceData> servervar_data;
117                 Hashtable ctrl_cs;
118 #else
119                 Queue info;
120                 Queue control_data;
121                 Queue cookie_data;
122                 Queue header_data;
123                 Queue servervar_data;
124                 //DataTable viewstate_data;
125 #endif
126                 
127                 string request_path;
128                 string session_id;
129                 DateTime request_time;
130                 Encoding request_encoding;
131                 Encoding response_encoding;
132                 string request_type;
133                 int status_code;
134                 Page page;
135                 TraceMode _traceMode = HttpRuntime.TraceManager.TraceMode;
136
137                 public TraceData ()
138                 {
139 #if NET_2_0
140                         info = new Queue <InfoTraceData> ();
141                         control_data = new Queue <ControlTraceData> ();
142                         cookie_data = new Queue <NameValueTraceData> ();
143                         header_data = new Queue <NameValueTraceData> ();
144                         servervar_data = new Queue <NameValueTraceData> ();
145 #else
146                         info = new Queue ();
147                         control_data = new Queue ();
148                         cookie_data = new Queue ();
149                         header_data = new Queue ();
150                         servervar_data = new Queue ();
151 #endif
152
153                         /* TODO
154                         viewstate_data = new DataTable ();
155                         viewstate_data.Columns.Add (new DataColumn ("ControlId", typeof (string)));
156                         viewstate_data.Columns.Add (new DataColumn ("Data", typeof (string)));
157                         */
158
159                         is_first_time = true;
160                 }
161
162                 public TraceMode TraceMode {
163                         get { return _traceMode; }
164                         set { _traceMode = value; }
165                 }
166
167                 public string RequestPath {
168                         get { return request_path; }
169                         set { request_path = value; }
170                 }
171                 
172                 public string SessionID {
173                         get { return session_id; }
174                         set { session_id = value; }
175                 }
176
177                 public DateTime RequestTime {
178                         get { return request_time; }
179                         set { request_time = value; }
180                 }
181
182                 public Encoding RequestEncoding {
183                         get { return request_encoding; }
184                         set { request_encoding = value; }
185                 }
186
187                 public Encoding ResponseEncoding {
188                         get { return response_encoding; }
189                         set { response_encoding = value; }
190                 }
191
192                 public string RequestType {
193                         get { return request_type; }
194                         set { request_type = value; }
195                 }
196
197                 public int StatusCode {
198                         get { return status_code; }
199                         set { status_code = value; }
200                 }
201
202                 public void Write (string category, string msg, Exception error, bool Warning)
203                 {
204                         double time;
205                         double time_from_last;
206                         if (is_first_time) {
207                                 time = 0;
208                                 time_from_last = 0; 
209                                 prev_time = 0;
210                                 is_first_time = false;
211                                 first_time = DateTime.Now;
212                         }
213                         else {
214                                 time = (DateTime.Now - first_time).TotalSeconds;
215                                 time_from_last = time - prev_time;
216                                 prev_time = time;
217                         }
218
219                         info.Enqueue (
220                                 new InfoTraceData (category,
221                                                    HtmlEncode (msg),
222                                                    (error != null ? error.ToString () : null),
223                                                    time,
224                                                    time_from_last,
225                                                    Warning));
226                 }
227
228                 static string HtmlEncode (string s)
229                 {
230                         if (s == null)
231                                 return "";
232
233                         string res = HttpUtility.HtmlEncode (s);
234                         res = res.Replace ("\n", "<br>");
235                         return res.Replace (" ", "&nbsp;");
236                 }
237                 
238 #if NET_2_0
239                 public void AddControlTree (Page page, Hashtable ctrl_vs, Hashtable ctrl_cs, Hashtable sizes)
240 #else
241                 public void AddControlTree (Page page, Hashtable ctrl_vs, Hashtable sizes)
242 #endif
243                 {
244                         this.page = page;
245                         this.ctrl_vs = ctrl_vs;
246                         this.sizes = sizes;
247 #if NET_2_0
248                         this.ctrl_cs = ctrl_cs;
249 #endif
250                         AddControl (page, 0);
251                 }
252
253                 Hashtable sizes;
254                 Hashtable ctrl_vs;
255                 void AddControl (Control c, int control_pos)
256                 {
257                         control_data.Enqueue (
258                                 new ControlTraceData (
259                                         c.UniqueID,
260                                         c.GetType (),
261                                         GetRenderSize (c),
262                                         GetViewStateSize (c, (ctrl_vs != null) ? ctrl_vs [c] : null),
263 #if NET_2_0
264                                         GetViewStateSize (c, (ctrl_cs != null) ? ctrl_cs [c] : null),
265 #endif
266                                         control_pos));
267                         
268                         if (c.HasControls ()) {
269                                 foreach (Control child in c.Controls)
270                                         AddControl (child, control_pos + 1);
271                         }
272                 }
273
274                 int GetRenderSize (Control ctrl)
275                 {
276                         if (sizes == null)
277                                 return 0;
278
279                         object s = sizes [ctrl];
280                         return s == null ? 0 : (int) s;
281                 }
282
283                 static int GetViewStateSize (Control ctrl, object vs)
284                 {
285                         if (vs == null)
286                                 return 0;
287
288                         StringWriter sr = new StringWriter ();
289                         LosFormatter fmt = new LosFormatter ();
290                         fmt.Serialize (sr, vs);
291                         return sr.GetStringBuilder ().Length;
292                 }
293
294                 public void AddCookie (string name, string value)
295                 {
296                         cookie_data.Enqueue (new NameValueTraceData (name, value));
297                 }
298
299                 public void AddHeader (string name, string value)
300                 {
301                         header_data.Enqueue (new NameValueTraceData (name, value));
302                 }
303
304                 public void AddServerVar (string name, string value)
305                 {
306                         servervar_data.Enqueue (new NameValueTraceData (name, value));
307                 }
308                 
309                 public void Render (HtmlTextWriter output)
310                 {
311                         output.AddAttribute ("id", "__asptrace");
312                         output.RenderBeginTag (HtmlTextWriterTag.Div);
313                         
314                         RenderStyleSheet (output);
315                         
316                         output.AddAttribute ("class", "tracecontent");
317                         output.RenderBeginTag (HtmlTextWriterTag.Span);
318                         
319                         RenderRequestDetails (output);
320                         RenderTraceInfo (output);
321                         RenderControlTree (output);
322                         RenderCookies (output);
323                         RenderHeaders (output);
324                         RenderServerVars (output);
325                         
326                         output.RenderEndTag ();
327                         output.RenderEndTag ();
328                 }
329                 
330                 void RenderRequestDetails (HtmlTextWriter output)
331                 {
332                         Table table = CreateTable ();
333                         
334                         table.Rows.Add (AltRow ("Request Details:"));
335                         table.Rows.Add (InfoRow2 ("Session Id:", session_id,
336                                                         "Request Type", request_type));
337                         table.Rows.Add (InfoRow2 ("Time of Request:", request_time.ToString (),
338                                                         "State Code:", status_code.ToString ()));
339                         table.Rows.Add (InfoRow2 ("Request Encoding:", request_encoding.EncodingName,
340                                                    "Response Encoding:", response_encoding.EncodingName));           
341                         table.RenderControl (output);
342                 }
343                 
344                 void RenderTraceInfo (HtmlTextWriter output)
345                 {
346                         Table table = CreateTable ();
347                         
348                         table.Rows.Add (AltRow ("Trace Information"));
349                         table.Rows.Add (SubHeadRow ("Category", "Message", "From First(s)", "From Lasts(s)"));
350                         
351                         int pos = 0;
352 #if NET_2_0
353                         IEnumerable<InfoTraceData> enumerable = info;
354
355                         if (TraceMode == TraceMode.SortByCategory) {
356                                 List<InfoTraceData> list = new List<InfoTraceData> (info);
357                                 list.Sort (delegate (InfoTraceData x, InfoTraceData y) { return String.Compare (x.Category, y.Category); });
358                                 enumerable = list;
359                         }
360
361                         foreach (InfoTraceData i in enumerable)
362                                 RenderTraceInfoRow (table, i, pos++);
363 #else
364                         foreach (object o in info)
365                                 RenderTraceInfoRow (table, o as InfoTraceData, pos++);
366 #endif
367                         table.RenderControl (output);
368                 }
369                 
370                 void RenderControlTree (HtmlTextWriter output)
371                 {
372                         Table table = CreateTable ();
373                         
374                         int page_vs_size = page == null ? 0 : GetViewStateSize (page, page.GetSavedViewState ());
375                         table.Rows.Add (AltRow ("Control Tree"));
376                         table.Rows.Add (SubHeadRow ("Control Id", "Type",
377                                                 "Render Size Bytes (including children)",
378 #if TARGET_J2EE
379                                                 "ViewState Size (excluding children)"
380 #else
381                                                 String.Format ("ViewState Size (total: {0} bytes)(excluding children)",
382                                                                 page_vs_size)
383 #endif
384 #if NET_2_0
385                                                 ,"ControlState Size (excluding children)"
386 #endif
387                                                         ));
388                         
389                         int pos = 0;
390 #if NET_2_0
391                         foreach (ControlTraceData r in control_data)
392                                 RenderControlTraceDataRow (table, r, pos++);
393 #else
394                         foreach (object o in control_data)
395                                 RenderControlTraceDataRow (table, o as ControlTraceData, pos++);
396 #endif
397                         table.RenderControl (output);
398                 }
399
400                 void RenderControlTraceDataRow (Table table, ControlTraceData r, int pos)
401                 {
402                         if (r == null)
403                                 return;
404                         
405                         int depth = r.Depth;
406                         string prefix = String.Empty;
407                         for (int i=0; i<depth; i++)
408                                 prefix += "&nbsp;&nbsp;&nbsp;&nbsp;";
409                         RenderAltRow (table, pos, prefix + r.ControlId,
410                                       r.Type.ToString (), r.RenderSize.ToString (),
411 #if NET_2_0
412                                           r.ViewstateSize.ToString (), r.ControlstateSize.ToString ());
413 #else
414                                       r.ViewstateSize.ToString ());
415 #endif
416                 }
417                 
418                 void RenderCookies (HtmlTextWriter output)
419                 {
420                         Table table = CreateTable ();
421                         
422                         table.Rows.Add (AltRow ("Cookies Collection"));
423                         table.Rows.Add (SubHeadRow ("Name", "Value", "Size"));
424                         
425                         int pos = 0;
426 #if NET_2_0
427                         foreach (NameValueTraceData r in cookie_data)
428                                 RenderCookieDataRow (table, r, pos++);
429 #else
430                         foreach (object o in cookie_data)
431                                 RenderCookieDataRow (table, o as NameValueTraceData, pos++);
432 #endif          
433                         
434                         table.RenderControl (output);
435                 }
436
437                 void RenderCookieDataRow (Table table, NameValueTraceData r, int pos)
438                 {
439                         if (r == null)
440                                 return;
441                         
442                         int length = r.Name.Length + (r.Value == null ? 0 : r.Value.Length);
443                         RenderAltRow (table, pos++, r.Name, r.Value, length.ToString ());
444                 }
445                 
446                 void RenderHeaders (HtmlTextWriter output)
447                 {
448                         Table table = CreateTable ();
449                         
450                         table.Rows.Add (AltRow ("Headers Collection"));
451                         table.Rows.Add (SubHeadRow ("Name", "Value"));
452                         
453                         int pos = 0;
454 #if NET_2_0
455                         foreach (NameValueTraceData r in header_data)
456                                 RenderAltRow (table, pos++, r.Name, r.Value);
457 #else
458                         NameValueTraceData r;
459                         foreach (object o in header_data) {
460                                 r = o as NameValueTraceData;
461                                 if (r == null)
462                                         continue;
463                                 
464                                 RenderAltRow (table, pos++, r.Name, r.Value);
465                         }
466 #endif
467                         table.RenderControl (output);
468                 }
469                 
470                 void RenderServerVars (HtmlTextWriter output)
471                 {
472                         Table table = CreateTable ();
473                         
474                         table.Rows.Add (AltRow ("Server Variables"));
475                         table.Rows.Add (SubHeadRow ("Name", "Value"));
476                         
477                         int pos = 0;
478 #if NET_2_0
479                         foreach (NameValueTraceData r in servervar_data)
480                                 RenderAltRow (table, pos++, r.Name, r.Value);
481 #else
482                         NameValueTraceData r;
483                         foreach (object o in servervar_data) {
484                                 r = o as NameValueTraceData;
485                                 if (r == null)
486                                         continue;
487                                 
488                                 RenderAltRow (table, pos++, r.Name, r.Value);
489                         }
490 #endif                  
491                         table.RenderControl (output);
492                 }
493
494                 internal static TableRow AltRow (string title)
495                 {
496                         TableRow row = new TableRow ();
497                         TableHeaderCell header = new TableHeaderCell ();
498                         header.CssClass = "alt";
499                         header.HorizontalAlign = HorizontalAlign.Left;
500                         header.Attributes [" colspan"] = "10";
501                         header.Text = "<h3><b>" + title + "</b></h3>";
502
503                         row.Cells.Add (header);
504                         return row;
505                 }
506                 
507                 void RenderTraceInfoRow (Table table, InfoTraceData i, int pos)
508                 {
509                         if (i == null)
510                                 return;
511                         
512                         string open, close;
513                         open = close = String.Empty;
514                         if ((bool) i.IsWarning) {
515                                 open = "<font color=\"Red\">";
516                                 close = "</font>";
517                         }
518
519                         string t1, t2;
520 #if !TARGET_J2EE
521                         if (i.TimeSinceFirst == 0) {
522                                 t1 = t2 = String.Empty;
523                         } else
524 #endif
525                         {
526                                 t1 = i.TimeSinceFirst.ToString ("0.000000");
527                                 t2 = i.TimeSinceLast.ToString ("0.000000");
528                         }
529                         
530                         RenderAltRow (table, pos, open + (string) i.Category + close,
531                                       open + (string) i.Message + close, t1, t2);
532                 }
533            
534                 internal static TableRow SubHeadRow (params string[] cells)
535                 {
536                         TableRow row = new TableRow ();
537                         foreach (string s in cells) {
538                                 TableHeaderCell cell = new TableHeaderCell ();
539                                 cell.Text = s;
540                                 row.Cells.Add (cell);
541                         }
542                         
543                         row.CssClass = "subhead";
544                         row.HorizontalAlign = HorizontalAlign.Left;
545                         
546                         return row;
547                 }
548                 
549                 internal static TableRow RenderAltRow (Table table, int pos, params string[] cells)
550                 {
551                         TableRow row = new TableRow ();
552                         foreach (string s in cells) {
553                                 TableCell cell = new TableCell ();
554                                 cell.Text = s;
555                                 row.Cells.Add (cell);
556                    }
557                         
558                         if ((pos % 2) != 0)
559                                 row.CssClass = "alt";
560                         
561                         table.Rows.Add (row);
562                         return row;
563                 }
564            
565                 TableRow InfoRow2 (string title1, string info1, string title2, string info2)
566                 {
567                         TableRow row = new TableRow ();
568                         TableHeaderCell header1 = new TableHeaderCell ();
569                         TableHeaderCell header2 = new TableHeaderCell ();
570                         TableCell cell1 = new TableCell ();
571                         TableCell cell2 = new TableCell ();
572                         
573                         header1.Text = title1;
574                         header2.Text = title2;
575                         cell1.Text = info1;
576                         cell2.Text = info2;
577                         
578                         row.Cells.Add (header1);
579                         row.Cells.Add (cell1);
580                         row.Cells.Add (header2);
581                         row.Cells.Add (cell2);
582
583                         row.HorizontalAlign = HorizontalAlign.Left;
584                         
585                         return row;
586                 }
587                 
588                 internal static Table CreateTable ()
589                 {
590                         Table table = new Table ();
591                         
592                         table.Width = Unit.Percentage (100);
593                         table.CellSpacing = 0;
594                         table.CellPadding = 0;
595                         
596                         return table;
597                 }
598                 
599                 internal static void RenderStyleSheet (HtmlTextWriter o)
600                 {
601                         o.WriteLine ("<style type=\"text/css\">");
602                         o.Write ("span.tracecontent { background-color:white; ");
603                         o.WriteLine ("color:black;font: 10pt verdana, arial; }");
604                         o.Write ("span.tracecontent table { font: 10pt verdana, ");
605                         o.WriteLine ("arial; cellspacing:0; cellpadding:0; margin-bottom:25}");
606                         o.WriteLine ("span.tracecontent tr.subhead { background-color:cccccc;}");
607                         o.WriteLine ("span.tracecontent th { padding:0,3,0,3 }");
608                         o.WriteLine ("span.tracecontent th.alt { background-color:black; color:white; padding:3,3,2,3; }");
609                         o.WriteLine ("span.tracecontent td { padding:0,3,0,3 }");
610                         o.WriteLine ("span.tracecontent tr.alt { background-color:eeeeee }");
611                         o.WriteLine ("span.tracecontent h1 { font: 24pt verdana, arial; margin:0,0,0,0}");
612                         o.WriteLine ("span.tracecontent h2 { font: 18pt verdana, arial; margin:0,0,0,0}");
613                         o.WriteLine ("span.tracecontent h3 { font: 12pt verdana, arial; margin:0,0,0,0}");
614                         o.WriteLine ("span.tracecontent th a { color:darkblue; font: 8pt verdana, arial; }");
615                         o.WriteLine ("span.tracecontent a { color:darkblue;text-decoration:none }");
616                         o.WriteLine ("span.tracecontent a:hover { color:darkblue;text-decoration:underline; }");
617                         o.WriteLine ("span.tracecontent div.outer { width:90%; margin:15,15,15,15}");
618                         o.Write ("span.tracecontent table.viewmenu td { background-color:006699; ");
619                         o.WriteLine ("color:white; padding:0,5,0,5; }");
620                         o.WriteLine ("span.tracecontent table.viewmenu td.end { padding:0,0,0,0; }");
621                         o.WriteLine ("span.tracecontent table.viewmenu a {color:white; font: 8pt verdana, arial; }");
622                         o.WriteLine ("span.tracecontent table.viewmenu a:hover {color:white; font: 8pt verdana, arial; }");
623                         o.WriteLine ("span.tracecontent a.tinylink {color:darkblue; font: 8pt verdana, ");
624                         o.WriteLine ("arial;text-decoration:underline;}");
625                         o.WriteLine ("span.tracecontent a.link {color:darkblue; text-decoration:underline;}");
626                         o.WriteLine ("span.tracecontent div.buffer {padding-top:7; padding-bottom:17;}");
627                         o.WriteLine ("span.tracecontent .small { font: 8pt verdana, arial }");
628                         o.WriteLine ("span.tracecontent table td { padding-right:20 }");
629                         o.WriteLine ("span.tracecontent table td.nopad { padding-right:5 }");
630                         o.WriteLine ("</style>");
631                 }
632         }
633 }
634