"; // this will get HtmlEncoded later...
private const string NULLIDPREFIX = "__UnassignedID";
private ArrayList _traceRecords;
private bool _endDataCollected;
private bool _writing = false;
///
/// Initializes a new instance of the class.
///
public TraceContext(HttpContext context) {
_traceMode = TraceMode.Default;
// Always disable trace in retail deployment mode (DevDiv 36396)
_isEnabled = DeploymentSection.RetailInternal ? TraceEnable.Disable : TraceEnable.Default;
_context = context;
_firstTime = -1;
_lastTime = -1;
_endDataCollected = false;
_traceRecords = new ArrayList();
}
///
/// Indicates the order in which trace messages should be
/// output to a requesting browser. Trace messages can be sorted in the order they
/// were processed, or alphabetically by user-defined category.
///
public TraceMode TraceMode {
get {
if (_traceMode == TraceMode.Default)
return HttpRuntime.Profile.OutputMode;
return _traceMode;
}
set {
if (value < TraceMode.SortByTime || value > TraceMode.Default) {
throw new ArgumentOutOfRangeException("value");
}
_traceMode = value;
if (IsEnabled)
ApplyTraceMode();
}
}
///
/// Indicates whether tracing is enabled for the current Web request.
/// Use this flag to check whether you should output tracing information before
/// writing anything to the trace log.
///
public bool IsEnabled {
get {
if (_isEnabled == TraceEnable.Default)
return HttpRuntime.Profile.IsEnabled;
else {
return (_isEnabled == TraceEnable.Enable) ? true : false;
}
}
set {
// Always disable trace in retail deployment mode (DevDiv 36396)
if (DeploymentSection.RetailInternal) {
System.Web.Util.Debug.Assert(_isEnabled == TraceEnable.Disable);
return;
}
if (value)
_isEnabled = TraceEnable.Enable;
else
_isEnabled = TraceEnable.Disable;
}
}
///
/// Indicates whether trace information should be output to a Web Forms
/// page. This property is used only in application-level tracing situations. You
/// can set this property in your application's config.web configuration file which
/// resides in the root directory of the application.
///
internal bool PageOutput {
get {
if (_isEnabled == TraceEnable.Default)
return HttpRuntime.Profile.PageOutput;
else {
return (_isEnabled == TraceEnable.Enable) ? true : false;
}
}
}
// this is used only for error pages, called from Page.HandleError.
internal int StatusCode {
set {
VerifyStart();
DataRow row = _requestData.Tables[SR.Trace_Request].Rows[0];
row[SR.Trace_Status_Code] = value;
}
}
///
/// Raised after the trace has been finished
///
public event TraceContextEventHandler TraceFinished {
add {
_events.AddHandler(EventTraceFinished, value);
}
remove {
_events.RemoveHandler(EventTraceFinished, value);
}
}
private void ApplyTraceMode() {
VerifyStart();
if (TraceMode == TraceMode.SortByCategory)
_requestData.Tables[SR.Trace_Trace_Information].DefaultView.Sort = SR.Trace_Category;
else
_requestData.Tables[SR.Trace_Trace_Information].DefaultView.Sort = SR.Trace_From_First;
}
internal void CopySettingsTo(TraceContext tc) {
tc._traceMode = this._traceMode;
tc._isEnabled = this._isEnabled;
}
internal void OnTraceFinished(TraceContextEventArgs e) {
TraceContextEventHandler handler = (TraceContextEventHandler)_events[EventTraceFinished];
if (handler != null) {
handler(this, e);
}
}
internal static void SetWriteToDiagnosticsTrace(bool value) {
_writeToDiagnosticsTrace = value;
}
///
/// Writes trace information to the trace log including any
/// user defined categories and trace messages.
///
public void Write(string message) {
Write(String.Empty, message, null, false, _writeToDiagnosticsTrace);
}
///
/// Writes trace information to the trace log including any
/// user defined categories and trace messages.
///
public void Write(string category, string message) {
Write(category, message, null, false, _writeToDiagnosticsTrace);
}
///
/// Writes trace information to the trace log including any user defined
/// categories,trace messages and error information.
///
public void Write(string category, string message, Exception errorInfo) {
Write(category, message, errorInfo, false, _writeToDiagnosticsTrace);
}
internal void WriteInternal(string message, bool writeToDiagnostics) {
Write(String.Empty, message, null, false, writeToDiagnostics);
}
internal void WriteInternal(string category, string message, bool writeToDiagnostics) {
Write(category, message, null, false, writeToDiagnostics);
}
///
/// Writes trace information to the trace log including any
/// user defined categories and trace messages. All warnings appear as red text.
///
public void Warn(string message) {
Write(String.Empty, message, null, true, _writeToDiagnosticsTrace);
}
///
/// Writes trace information to the trace log including any
/// user defined categories and trace messages. All warnings appear as red text.
///
public void Warn(string category, string message) {
Write(category, message, null, true, _writeToDiagnosticsTrace);
}
///
/// Writes trace information to the trace log including any user defined categories,trace messages and error information. All
/// warnings appear as red text.
///
public void Warn(string category, string message, Exception errorInfo) {
Write(category, message, errorInfo, true, _writeToDiagnosticsTrace);
}
internal void WarnInternal(string category, string message, bool writeToDiagnostics) {
Write(category, message, null, true, writeToDiagnostics);
}
void Write(string category, string message, Exception errorInfo, bool isWarning, bool writeToDiagnostics) {
// Guard against
lock(this) {
// Bail if trace isn't enabled or this is from our call to System.Diagonostics.Trace below
if (!IsEnabled || _writing || _endDataCollected)
return;
VerifyStart();
if (category == null)
category = String.Empty;
if (message == null)
message = String.Empty;
long messagetime = Counter.Value;
DataRow row = NewRow(_requestData, SR.Trace_Trace_Information);
row[SR.Trace_Category] = category;
row[SR.Trace_Message] = message;
row[SR.Trace_Warning] = isWarning ? "yes" : "no";
if (errorInfo != null) {
row["ErrorInfoMessage"] = errorInfo.Message;
row["ErrorInfoStack"] = errorInfo.StackTrace;
}
if (_firstTime != -1) {
row[SR.Trace_From_First] = (((double)(messagetime - _firstTime)) / Counter.Frequency);
}
else
_firstTime = messagetime;
if (_lastTime != -1) {
row[SR.Trace_From_Last] = (((double)(messagetime - _lastTime)) / Counter.Frequency);
}
_lastTime = messagetime;
AddRow(_requestData, SR.Trace_Trace_Information, row);
string msg = message;
if (errorInfo != null) {
string eMsg = errorInfo.Message;
if (eMsg == null) eMsg = String.Empty;
string eTrace = errorInfo.StackTrace;
if (eTrace == null) eTrace = String.Empty;
StringBuilder str = new StringBuilder(message.Length + eMsg.Length + eTrace.Length);
str.Append(message);
str.Append(" -- ");
str.Append(eMsg);
str.Append(": ");
str.Append(eTrace);
msg = str.ToString();
}
if (writeToDiagnostics) {
_writing = true;
System.Diagnostics.Trace.WriteLine(msg, category);
_writing = false;
}
// Send to IIS tracing
if (_context != null && _context.WorkerRequest != null) {
_context.WorkerRequest.RaiseTraceEvent(isWarning ? IntegratedTraceType.TraceWarn : IntegratedTraceType.TraceWrite, msg);
}
}
// Add the trace record to our collection
_traceRecords.Add(new TraceContextRecord(category, message, isWarning, errorInfo));
}
internal void AddNewControl(string id, string parentId, string type, int viewStateSize, int controlStateSize) {
VerifyStart();
DataRow row = NewRow(_requestData, SR.Trace_Control_Tree);
if (id == null)
id = NULLIDPREFIX+(_uniqueIdCounter++);
row[SR.Trace_Control_Id] = id;
if (parentId == null)
parentId = PAGEKEYNAME;
row[SR.Trace_Parent_Id] = parentId;
row[SR.Trace_Type] = type;
row[SR.Trace_Viewstate_Size] = viewStateSize;
row[SR.Trace_Controlstate_Size] = controlStateSize;
row[SR.Trace_Render_Size] = 0;
try {
AddRow(_requestData, SR.Trace_Control_Tree, row);
}
catch (ConstraintException) {
throw new HttpException(SR.GetString(SR.Duplicate_id_used, id, "Trace"));
}
}
/*
* Add the render size to the control
*/
internal void AddControlSize(String controlId, int renderSize) {
VerifyStart();
DataTable dt = _requestData.Tables[SR.Trace_Control_Tree];
// find the row for this control
if (controlId == null)
controlId = PAGEKEYNAME;
DataRow row = dt.Rows.Find((object) controlId);
// if the row is null, we couldn't find it, so we'll just skip this control
if (row != null)
row[SR.Trace_Render_Size] = renderSize;
}
internal void AddControlStateSize(String controlId, int viewstateSize, int controlstateSize) {
VerifyStart();
DataTable dt = _requestData.Tables[SR.Trace_Control_Tree];
// find the row for this control
if (controlId == null)
controlId = PAGEKEYNAME;
DataRow row = dt.Rows.Find((object) controlId);
// if the row is null, we couldn't find it, so we'll just skip this control
if (row != null) {
row[SR.Trace_Viewstate_Size] = viewstateSize;
row[SR.Trace_Controlstate_Size] = controlstateSize;
}
}
internal void Render(HtmlTextWriter output) {
if (PageOutput && _requestData != null) {
TraceEnable oldEnabled = _isEnabled;
_isEnabled = TraceEnable.Disable;
Control table;
output.Write("\r\n");
output.Write(TraceHandler.StyleSheet);
output.Write("\r\n");
table = TraceHandler.CreateDetailsTable(_requestData.Tables[SR.Trace_Request]);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTraceTable(_requestData.Tables[SR.Trace_Trace_Information]);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateControlTable(_requestData.Tables[SR.Trace_Control_Tree]);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Session_State], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Application_State], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Request_Cookies_Collection], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Response_Cookies_Collection], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Headers_Collection], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Response_Headers_Collection], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Form_Collection]);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Querystring_Collection]);
if (table != null)
table.RenderControl(output);
table = TraceHandler.CreateTable(_requestData.Tables[SR.Trace_Server_Variables], true /*encodeSpaces*/);
if (table != null)
table.RenderControl(output);
output.Write("
\r\n\r\n");
output.Write(SR.GetString(SR.Error_Formatter_CLR_Build) + VersionInfo.ClrVersion +
SR.GetString(SR.Error_Formatter_ASPNET_Build) + VersionInfo.EngineVersion + "\r\n\r\n");
output.Write("\r\n\r\n");
output.Write("\r\n
\r\n");
_isEnabled = oldEnabled;
}
}
internal DataSet GetData() {
return _requestData;
}
internal void VerifyStart() {
// if we have already started, we can skip the lock
if (_masterRequest == null) {
// otherwise we need to make sure two
// requests don't try to call InitMaster at the same time
lock(this) {
if (_masterRequest == null)
InitMaster();
}
}
if (_requestData == null) {
InitRequest();
}
}
internal void StopTracing() {
_endDataCollected = true;
}
/*
* Finalize the request
*/
internal void EndRequest() {
VerifyStart();
if (_endDataCollected)
return;
// add some more information about the reponse
DataRow row = _requestData.Tables[SR.Trace_Request].Rows[0];
row[SR.Trace_Status_Code] = _context.Response.StatusCode;
row[SR.Trace_Response_Encoding] = _context.Response.ContentEncoding.EncodingName;
IEnumerator en;
string temp;
object obj;
int i;
// Application State info
_context.Application.Lock();
try {
en = _context.Application.GetEnumerator();
while (en.MoveNext()) {
row = NewRow(_requestData, SR.Trace_Application_State);
temp = (string) en.Current;
//the key might be null
row[SR.Trace_Application_Key] = (temp != null) ? temp : NULLSTRING;
obj = _context.Application[temp];
// the value could also be null
if (obj != null) {
row[SR.Trace_Type] = obj.GetType();
row[SR.Trace_Value] = obj.ToString();
}
else {
row[SR.Trace_Type] = NULLSTRING;
row[SR.Trace_Value] = NULLSTRING;
}
AddRow(_requestData, SR.Trace_Application_State, row);
}
}
finally {
_context.Application.UnLock();
}
// request cookie info
HttpCookieCollection cookieCollection = new HttpCookieCollection();
_context.Request.FillInCookiesCollection(cookieCollection, false /*includeResponse */);
HttpCookie[] cookies = new HttpCookie[cookieCollection.Count];
cookieCollection.CopyTo(cookies, 0);
for (i = 0; i