From 6471d7c3a6e8c0dac183dee42d5be7f13ac2fb36 Mon Sep 17 00:00:00 2001 From: Daniel Cazzulino Date: Mon, 13 Jan 2014 04:15:11 -0300 Subject: [PATCH] Added initial version of a SignalR-based realtime trace listener and console. --- .gitattributes | 63 +++ LICENSE | 202 +++++++++ .../External/Diagnostics/Tracer/ITracer.cs | 64 +++ .../Diagnostics/Tracer/ITracerExtensions.cs | 224 ++++++++++ .../Diagnostics/Tracer/ITracerManager.cs | 47 ++ .../StartActivityExtension.cs | 246 +++++++++++ .../Tracer/SystemDiagnostics/TracerManager.cs | 416 ++++++++++++++++++ .../External/Diagnostics/Tracer/Tracer.cs | 160 +++++++ .../External/Diagnostics/Tracer/Visibility.cs | 42 ++ Tracer.Console/Program.cs | 82 ++++ Tracer.Console/Properties/AssemblyInfo.cs | 36 ++ Tracer.Console/Tracer.Console.csproj | 83 ++++ Tracer.Console/app.config | 19 + Tracer.Console/netfx/System/AppDomainData.cs | 89 ++++ .../Collections/Generic/DictionaryGetOrAdd.cs | 56 +++ Tracer.Console/packages.config | 9 + .../External/Diagnostics/Tracer/ITracer.cs | 64 +++ .../Diagnostics/Tracer/ITracerExtensions.cs | 224 ++++++++++ .../Diagnostics/Tracer/ITracerManager.cs | 47 ++ .../External/Diagnostics/Tracer/Tracer.cs | 160 +++++++ .../External/Diagnostics/Tracer/Visibility.cs | 42 ++ Tracer.Realtime/Package.nuspec | 26 ++ Tracer.Realtime/Properties/AssemblyInfo.cs | 36 ++ .../Tracer.Hub.Listener.t4properties | 4 + Tracer.Realtime/Tracer.Realtime.csproj | 92 ++++ Tracer.Realtime/Tracer.Realtime.t4properties | 15 + .../Tracer/RealtimeTraceListener.cs | 139 ++++++ .../Tracer/RealtimeTraceListener.cs.pp | 139 ++++++ .../Tracer/RealtimeTraceListener.tt | 4 + .../External/Diagnostics/Tracer/TraceEvent.cs | 57 +++ .../Diagnostics/Tracer/TraceEvent.cs.pp | 57 +++ .../External/Diagnostics/Tracer/TraceEvent.tt | 4 + Tracer.Realtime/packages.config | 6 + .../Tracer.SystemDiagnostics.csproj | 232 +++++----- Tracer.UnitTests/RealtimeSpec.cs | 55 +++ Tracer.UnitTests/Tracer.UnitTests.csproj | 154 +++---- Tracer.UnitTests/packages.config | 10 +- Tracer.licenseheader | 35 ++ Tracer.sln | 150 ++++--- 39 files changed, 3326 insertions(+), 264 deletions(-) create mode 100644 .gitattributes create mode 100644 LICENSE create mode 100644 Tracer.Console/External/Diagnostics/Tracer/ITracer.cs create mode 100644 Tracer.Console/External/Diagnostics/Tracer/ITracerExtensions.cs create mode 100644 Tracer.Console/External/Diagnostics/Tracer/ITracerManager.cs create mode 100644 Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/StartActivityExtension.cs create mode 100644 Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/TracerManager.cs create mode 100644 Tracer.Console/External/Diagnostics/Tracer/Tracer.cs create mode 100644 Tracer.Console/External/Diagnostics/Tracer/Visibility.cs create mode 100644 Tracer.Console/Program.cs create mode 100644 Tracer.Console/Properties/AssemblyInfo.cs create mode 100644 Tracer.Console/Tracer.Console.csproj create mode 100644 Tracer.Console/app.config create mode 100644 Tracer.Console/netfx/System/AppDomainData.cs create mode 100644 Tracer.Console/netfx/System/Collections/Generic/DictionaryGetOrAdd.cs create mode 100644 Tracer.Console/packages.config create mode 100644 Tracer.Realtime/External/Diagnostics/Tracer/ITracer.cs create mode 100644 Tracer.Realtime/External/Diagnostics/Tracer/ITracerExtensions.cs create mode 100644 Tracer.Realtime/External/Diagnostics/Tracer/ITracerManager.cs create mode 100644 Tracer.Realtime/External/Diagnostics/Tracer/Tracer.cs create mode 100644 Tracer.Realtime/External/Diagnostics/Tracer/Visibility.cs create mode 100644 Tracer.Realtime/Package.nuspec create mode 100644 Tracer.Realtime/Properties/AssemblyInfo.cs create mode 100644 Tracer.Realtime/Tracer.Hub.Listener.t4properties create mode 100644 Tracer.Realtime/Tracer.Realtime.csproj create mode 100644 Tracer.Realtime/Tracer.Realtime.t4properties create mode 100644 Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs create mode 100644 Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs.pp create mode 100644 Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.tt create mode 100644 Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs create mode 100644 Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs.pp create mode 100644 Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.tt create mode 100644 Tracer.Realtime/packages.config create mode 100644 Tracer.UnitTests/RealtimeSpec.cs create mode 100644 Tracer.licenseheader diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e06d208 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Tracer.Console/External/Diagnostics/Tracer/ITracer.cs b/Tracer.Console/External/Diagnostics/Tracer/ITracer.cs new file mode 100644 index 0000000..2544be9 --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/ITracer.cs @@ -0,0 +1,64 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + using System; + using System.Diagnostics; + + /// + /// Interface used by the application components to log messages. + /// + /// + partial interface ITracer + { + /// + /// Traces the specified message with the given . + /// + void Trace(TraceEventType type, object message); + + /// + /// Traces the specified formatted message with the given . + /// + void Trace(TraceEventType type, string format, params object[] args); + + /// + /// Traces an exception with the specified message and . + /// + void Trace(TraceEventType type, Exception exception, object message); + + /// + /// Traces an exception with the specified formatted message and . + /// + void Trace(TraceEventType type, Exception exception, string format, params object[] args); + } +} diff --git a/Tracer.Console/External/Diagnostics/Tracer/ITracerExtensions.cs b/Tracer.Console/External/Diagnostics/Tracer/ITracerExtensions.cs new file mode 100644 index 0000000..a56d96a --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/ITracerExtensions.cs @@ -0,0 +1,224 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + using System; + using System.Diagnostics; + + /// + /// Provides usability overloads for tracing to a . + /// + /// + static partial class ITracerExtensions + { + #region Critical overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Critical(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Critical, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Critical(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Critical, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Critical(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Critical, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Critical(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Critical, exception, format, args); + } + + #endregion + + #region Error overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Error(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Error, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Error(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Error, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Error(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Error, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Error(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Error, exception, format, args); + } + + #endregion + + #region Warn overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Warn(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Warning, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Warn(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Warning, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Warn(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Warning, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Warn(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Warning, exception, format, args); + } + + #endregion + + #region Info overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Info(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Information, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Info(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Information, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Info(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Information, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Info(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Information, exception, format, args); + } + + #endregion + + #region Verbose overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Verbose(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Verbose, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Verbose(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Verbose, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Verbose(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Verbose, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Verbose(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Verbose, exception, format, args); + } + + #endregion + } +} diff --git a/Tracer.Console/External/Diagnostics/Tracer/ITracerManager.cs b/Tracer.Console/External/Diagnostics/Tracer/ITracerManager.cs new file mode 100644 index 0000000..b6c95b5 --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/ITracerManager.cs @@ -0,0 +1,47 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + /// + /// Manages instances. Provides the implementation + /// for the static facade class. + /// + /// + partial interface ITracerManager + { + /// + /// Gets a tracer instance with the specified name. + /// + ITracer Get(string name); + } +} diff --git a/Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/StartActivityExtension.cs b/Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/StartActivityExtension.cs new file mode 100644 index 0000000..b116dd3 --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/StartActivityExtension.cs @@ -0,0 +1,246 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.Xml; + using System.Xml.Linq; + using System.Xml.XPath; + + /// + /// Extensions to for activity tracing. + /// + static partial class StartActivityExtension + { + /// + /// Starts a new activity scope. + /// + public static IDisposable StartActivity(this ITracer tracer, string format, params object[] args) + { + return new TraceActivity(tracer, format, args); + } + + /// + /// Starts a new activity scope. + /// + public static IDisposable StartActivity(this ITracer tracer, string displayName) + { + return new TraceActivity(tracer, displayName); + } + + /// + /// In order for activity tracing to happen, the trace source needs to + /// have enabled. + /// + partial class TraceActivity : IDisposable + { + string displayName; + bool disposed; + ITracer tracer; + Guid oldId; + Guid newId; + + public TraceActivity(ITracer tracer, string displayName) + : this(tracer, displayName, null) + { + } + + public TraceActivity(ITracer tracer, string displayName, params object[] args) + { + this.tracer = tracer; + this.displayName = displayName; + if (args != null && args.Length > 0) + this.displayName = string.Format(displayName, args, CultureInfo.CurrentCulture); + + newId = Guid.NewGuid(); + oldId = Trace.CorrelationManager.ActivityId; + + tracer.Trace(TraceEventType.Transfer, this.newId); + Trace.CorrelationManager.ActivityId = newId; + + // The XmlWriterTraceListener expects Start/Stop events to receive an XPathNavigator + // with XML in a specific format so that the Service Trace Viewer can properly render + // the activity graph. + tracer.Trace(TraceEventType.Start, new ActivityData(this.displayName, true)); + } + + public void Dispose() + { + if (!this.disposed) + { + tracer.Trace(TraceEventType.Stop, new ActivityData(displayName, false)); + tracer.Trace(TraceEventType.Transfer, oldId); + Trace.CorrelationManager.ActivityId = oldId; + } + + this.disposed = true; + } + + class ActivityData : XPathNavigator + { + string displayName; + XPathNavigator xml; + + public ActivityData(string displayName, bool isStart) + { + this.displayName = displayName; + + // The particular XML format expected by the Service Trace Viewer was + // inferred from the actual tool behavior and usage. + this.xml = XDocument.Parse(string.Format(@" + + http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ActivityBoundary.aspx + Activity boundary. + client.vshost.exe + + {1} + ActivityTracing + + ", isStart ? "Start" : "Stop", displayName)).CreateNavigator(); + } + + public override string BaseURI + { + get { return xml.BaseURI; } + } + + public override XPathNavigator Clone() + { + return xml.Clone(); + } + + public override bool IsEmptyElement + { + get { return xml.IsEmptyElement; } + } + + public override bool IsSamePosition(XPathNavigator other) + { + return xml.IsSamePosition(other); + } + + public override string LocalName + { + get { return xml.LocalName; } + } + + public override bool MoveTo(XPathNavigator other) + { + return xml.MoveTo(other); + } + + public override bool MoveToFirstAttribute() + { + return xml.MoveToFirstAttribute(); + } + + public override bool MoveToFirstChild() + { + return xml.MoveToFirstChild(); + } + + public override bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope) + { + return xml.MoveToFirstNamespace(namespaceScope); + } + + public override bool MoveToId(string id) + { + return xml.MoveToId(id); + } + + public override bool MoveToNext() + { + return xml.MoveToNext(); + } + + public override bool MoveToNextAttribute() + { + return xml.MoveToNextAttribute(); + } + + public override bool MoveToNextNamespace(XPathNamespaceScope namespaceScope) + { + return xml.MoveToNextNamespace(namespaceScope); + } + + public override bool MoveToParent() + { + return xml.MoveToParent(); + } + + public override bool MoveToPrevious() + { + return xml.MoveToPrevious(); + } + + public override string Name + { + get { return xml.Name; } + } + + public override XmlNameTable NameTable + { + get { return xml.NameTable; } + } + + public override string NamespaceURI + { + get { return xml.NamespaceURI; } + } + + public override XPathNodeType NodeType + { + get { return xml.NodeType; } + } + + public override string Prefix + { + get { return xml.Prefix; } + } + + public override string Value + { + get { return xml.Value; } + } + + public override string ToString() + { + return displayName; + } + } + } + } +} diff --git a/Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/TracerManager.cs b/Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/TracerManager.cs new file mode 100644 index 0000000..a6a11e3 --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/SystemDiagnostics/TracerManager.cs @@ -0,0 +1,416 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Configuration; + using System.Diagnostics; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Threading; + using System.Threading.Tasks; + using System.Xml.Linq; + using System.Xml.XPath; + + /// + /// Implements the common tracer interface using instances. + /// + /// + /// All tracing is performed asynchronously transparently for faster speed. + /// + /// + partial class TracerManager : ITracerManager, IDisposable + { + /// + /// Implicit default trace source name which can be used to setup + /// global tracing and listeners. + /// + public const string DefaultSourceName = "*"; + + // To handle concurrency for the async tracing. + private BlockingCollection> traceQueue = new BlockingCollection>(); + private CancellationTokenSource cancellation = new CancellationTokenSource(); + + /// + /// Initializes a new instance of the class. + /// + public TracerManager() + { + // Note we have only one async task to perform all tracing. This + // is an optimization, so that we don't consume too much resources + // from the running app for this. + Task.Factory.StartNew(DoTrace, cancellation.Token, TaskCreationOptions.LongRunning, TaskScheduler.Current); + + InitializeConfiguredSources(); + } + + private void InitializeConfiguredSources() + { + var configFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + if (!File.Exists(configFile)) + return; + + var sourceNames = from diagnostics in XDocument.Load(configFile).Root.Elements("system.diagnostics") + from sources in diagnostics.Elements("sources") + from source in sources.Elements("source") + select source.Attribute("name").Value; + + foreach (var sourceName in sourceNames) + { + // Cause eager initialization, which is needed for the trace source configuration + // to be properly read. + GetSource(sourceName); + } + } + + /// + /// Gets a tracer instance with the specified name. + /// + public ITracer Get(string name) + { + return new AggregateTracer(this, name, CompositeFor(name) + .Select(tracerName => new DiagnosticsTracer( + this.GetOrAdd(tracerName, sourceName => CreateSource(sourceName))))); + } + + /// + /// Gets the underlying for the given name. + /// + public TraceSource GetSource(string name) + { + return this.GetOrAdd(name, sourceName => CreateSource(sourceName)); + } + + /// + /// Adds a listener to the source with the given . + /// + public void AddListener(string sourceName, TraceListener listener) + { + this.GetOrAdd(sourceName, name => CreateSource(name)).Listeners.Add(listener); + } + + /// + /// Removes a listener from the source with the given . + /// + public void RemoveListener(string sourceName, TraceListener listener) + { + this.GetOrAdd(sourceName, name => CreateSource(name)).Listeners.Remove(listener); + } + + /// + /// Removes a listener from the source with the given . + /// + public void RemoveListener(string sourceName, string listenerName) + { + this.GetOrAdd(sourceName, name => CreateSource(name)).Listeners.Remove(listenerName); + } + + /// + /// Sets the tracing level for the source with the given + /// + public void SetTracingLevel(string sourceName, SourceLevels level) + { + this.GetOrAdd(sourceName, name => CreateSource(name)).Switch.Level = level; + } + + /// + /// Cleans up the manager, cancelling any pending tracing + /// messages. + /// + public void Dispose() + { + cancellation.Cancel(); + traceQueue.Dispose(); + } + + /// + /// Enqueues the specified trace action to be executed by the trace + /// async task. + /// + internal void Enqueue(Action traceAction) + { + traceQueue.Add(Tuple.Create(ExecutionContext.Capture(), traceAction)); + } + + private TraceSource CreateSource(string name) + { + var source = new TraceSource(name); + source.TraceInformation("Initialized with initial level {0}", source.Switch.Level); + return source; + } + + private void DoTrace() + { + foreach (var action in traceQueue.GetConsumingEnumerable()) + { + if (cancellation.IsCancellationRequested) + break; + + // Tracing should never cause the app to fail. + // Since this is async, it might if we don't catch. + try + { + ExecutionContext.Run(action.Item1, state => action.Item2(), null); + } + catch { } + } + } + + /// + /// Gets the list of trace source names that are used to inherit trace source logging for the given . + /// + private static IEnumerable CompositeFor(string name) + { + if (name != DefaultSourceName) + yield return DefaultSourceName; + + var indexOfGeneric = name.IndexOf('<'); + var indexOfLastDot = name.LastIndexOf('.'); + + if (indexOfGeneric == -1 && indexOfLastDot == -1) + { + yield return name; + yield break; + } + + var parts = default(string[]); + + if (indexOfGeneric == -1) + parts = name + .Substring(0, name.LastIndexOf('.')) + .Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); + else + parts = name + .Substring(0, indexOfGeneric) + .Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries); + + for (int i = 1; i <= parts.Length; i++) + { + yield return string.Join(".", parts, 0, i); + } + + yield return name; + } + + /// + /// Gets an AppDomain-cached trace source of the given name, or creates it. + /// This means that even if multiple libraries are using their own + /// trace manager instance, they will all still share the same + /// underlying sources. + /// + private TraceSource GetOrAdd(string sourceName, Func factory) + { + var cachedSources = AppDomain.CurrentDomain.GetData>(); + if (cachedSources == null) + { + // This lock guarantees that throughout the current + // app domain, only a single root trace source is + // created ever. + lock (AppDomain.CurrentDomain) + { + cachedSources = AppDomain.CurrentDomain.GetData>(); + if (cachedSources == null) + { + cachedSources = new Dictionary(); + AppDomain.CurrentDomain.SetData(cachedSources); + } + } + } + + return cachedSources.GetOrAdd(sourceName, factory); + } + + /// + /// Logs to multiple tracers simulateously. Used for the + /// source "inheritance" + /// + private class AggregateTracer : ITracer + { + private TracerManager manager; + private List tracers; + private string name; + + public AggregateTracer(TracerManager manager, string name, IEnumerable tracers) + { + this.manager = manager; + this.name = name; + this.tracers = tracers.ToList(); + } + + /// + /// Traces the specified message with the given . + /// + public void Trace(TraceEventType type, object message) + { + manager.Enqueue(() => tracers.AsParallel().ForAll(tracer => tracer.Trace(name, type, message))); + } + + /// + /// Traces the specified formatted message with the given . + /// + public void Trace(TraceEventType type, string format, params object[] args) + { + manager.Enqueue(() => tracers.AsParallel().ForAll(tracer => tracer.Trace(name, type, format, args))); + } + + /// + /// Traces an exception with the specified message and . + /// + public void Trace(TraceEventType type, Exception exception, object message) + { + manager.Enqueue(() => tracers.AsParallel().ForAll(tracer => tracer.Trace(name, type, exception, message))); + } + + /// + /// Traces an exception with the specified formatted message and . + /// + public void Trace(TraceEventType type, Exception exception, string format, params object[] args) + { + manager.Enqueue(() => tracers.AsParallel().ForAll(tracer => tracer.Trace(name, type, exception, format, args))); + } + + public override string ToString() + { + return "Aggregate for " + this.name; + } + } + + partial class DiagnosticsTracer + { + private TraceSource source; + + public DiagnosticsTracer(TraceSource source) + { + this.source = source; + } + + public void Trace(string sourceName, TraceEventType type, object message) + { + // Because we know there is a single tracer thread executing these, + // we know it's safe to replace the name without locking. + using (new SourceNameReplacer(source, sourceName)) + { + // Add support for Xml-based Service Trace Viewer-compatible + // activity tracing. + var data = message as XPathNavigator; + // Transfers with a Guid payload should instead trace a transfer + // with that as the related Guid. + var guid = message as Guid?; + if (data != null) + source.TraceData(type, 0, data); + else if (guid != null && type == TraceEventType.Transfer) + source.TraceTransfer(0, "", guid.Value); + else + source.TraceEvent(type, 0, message.ToString()); + } + } + + public void Trace(string sourceName, TraceEventType type, string format, params object[] args) + { + // Because we know there is a single tracer thread executing these, + // we know it's safe to replace the name without locking. + using (new SourceNameReplacer(source, sourceName)) + { + source.TraceEvent(type, 0, format, args); + } + } + + public void Trace(string sourceName, TraceEventType type, Exception exception, object message) + { + // Because we know there is a single tracer thread executing these, + // we know it's safe to replace the name without locking. + using (new SourceNameReplacer(source, sourceName)) + { + source.TraceEvent(type, 0, message.ToString() + Environment.NewLine + exception); + } + } + + public void Trace(string sourceName, TraceEventType type, Exception exception, string format, params object[] args) + { + // Because we know there is a single tracer thread executing these, + // we know it's safe to replace the name without locking. + using (new SourceNameReplacer(source, sourceName)) + { + source.TraceEvent(type, 0, string.Format(format, args) + Environment.NewLine + exception); + } + } + + /// + /// The TraceSource instance name matches the name of each of the "segments" + /// we built the aggregate source from. This means that when we trace, we issue + /// multiple trace statements, one for each. If a listener is added to (say) "*" + /// source name, all traces done through it will appear as coming from the source + /// "*", rather than (say) "Foo.Bar" which might be the actual source class. + /// This diminishes the usefulness of hierarchical loggers significantly, since + /// it now means that you need to add listeners too all trace sources you're + /// interested in receiving messages from, and all its "children" potentially, + /// some of them which might not have been created even yet. This is not feasible. + /// Instead, since we issue the trace call to each trace source (which is what + /// enables the configurability of all those sources in the app.config file), + /// we need to fix the source name right before tracing, so that a configured + /// listener at "*" still receives as the source name the original (aggregate) one, + /// and not "*". This requires some private reflection, and a lock to guarantee + /// proper logging, but this decreases its performance. However, since we log + /// asynchronously, it's fine. + /// + private class SourceNameReplacer : IDisposable + { + // Private reflection needed here in order to make the inherited source names still + // log as if the original source name was the one logging, so as not to lose the + // originating class name. + private static readonly FieldInfo sourceNameField = typeof(TraceSource).GetField("sourceName", BindingFlags.Instance | BindingFlags.NonPublic); + + private TraceSource source; + private string originalName; + + public SourceNameReplacer(TraceSource source, string sourceName) + { + this.source = source; + this.originalName = source.Name; + // Transient change of the source name while the trace call + // is issued. Multi-threading might still cause messages to come + // out with wrong source names :( + sourceNameField.SetValue(source, sourceName); + } + + public void Dispose() + { + sourceNameField.SetValue(source, originalName); + } + } + } + } +} diff --git a/Tracer.Console/External/Diagnostics/Tracer/Tracer.cs b/Tracer.Console/External/Diagnostics/Tracer/Tracer.cs new file mode 100644 index 0000000..151dff9 --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/Tracer.cs @@ -0,0 +1,160 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + using System; + using System.Diagnostics; + using System.Linq; + + /// + /// Provides access to tracer instances. + /// + /// + static partial class Tracer + { + private static ITracerManager manager = new DefaultManager(); + + /// + /// Provides the implementation for managing tracers. + /// + internal static void Initialize(ITracerManager manager) + { + Tracer.manager = manager; + } + + /// + /// Gets a tracer instance with the full type name of . + /// + public static ITracer Get() + { + return manager.Get(NameFor(typeof(T))); + } + + /// + /// Gets a tracer instance with the full type name of the . + /// + public static ITracer Get(Type type) + { + return manager.Get(NameFor(type)); + } + + /// + /// Gets a tracer instance with the given name. + /// + public static ITracer Get(string name) + { + return manager.Get(name); + } + + + /// + /// Gets the tracer name for the given type. + /// + public static string NameFor() + { + return NameFor(typeof(T)); + } + + /// + /// Gets the tracer name for the given type. + /// + public static string NameFor(Type type) + { + if (type.IsGenericType) + { + var genericName = type.GetGenericTypeDefinition().FullName; + + return genericName.Substring(0, genericName.IndexOf('`')) + + "<" + + string.Join(",", type.GetGenericArguments().Select(t => NameFor(t)).ToArray()) + + ">"; + } + + return type.FullName; + } + + private partial class DefaultManager : ITracerManager + { + public ITracer Get(string name) + { + return new DefaultTracer(name); + } + + private class DefaultTracer : ITracer + { + private string name; + + public DefaultTracer(string name) + { + this.name = name; + } + + public void Trace(TraceEventType type, object message) + { + Trace(type, message.ToString()); + } + + public void Trace(TraceEventType type, string format, params object[] args) + { + Trace(type, Format(format, args)); + } + + public void Trace(TraceEventType type, Exception exception, object message) + { + Trace(type, message + Environment.NewLine + exception.ToString()); + } + + public void Trace(TraceEventType type, Exception exception, string format, params object[] args) + { + Trace(type, Format(format, args) + Environment.NewLine + exception.ToString()); + } + + private void Trace(TraceEventType type, string message) + { + System.Diagnostics.Debug.Write(string.Format( + "[{0}::{1}] ", + this.name, type, message)); + System.Diagnostics.Debug.WriteLine(message); + } + + private string Format(string format, object[] args) + { + if (args != null && args.Length != 0) + return string.Format(format, args); + + return format; + } + } + } + } +} diff --git a/Tracer.Console/External/Diagnostics/Tracer/Visibility.cs b/Tracer.Console/External/Diagnostics/Tracer/Visibility.cs new file mode 100644 index 0000000..c8f8d77 --- /dev/null +++ b/Tracer.Console/External/Diagnostics/Tracer/Visibility.cs @@ -0,0 +1,42 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace TracerHub.Diagnostics +{ + // Changes to this file will not be overwritten by NuGet when updating. + // To make the entire API public, just uncomment the following code: + + //public partial interface ITracer { } + //public static partial class ITracerExtensions { } + //public partial interface ITracerManager { } + //public static partial class Tracer { } +} diff --git a/Tracer.Console/Program.cs b/Tracer.Console/Program.cs new file mode 100644 index 0000000..3da4d6a --- /dev/null +++ b/Tracer.Console/Program.cs @@ -0,0 +1,82 @@ +namespace TracerHub +{ + using Microsoft.AspNet.SignalR.Client; + using Realtime; + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Diagnostics; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using TracerHub.Diagnostics; + + class Program + { + static readonly ITracer tracer = Tracer.Get(typeof(Program)); + const string TracerHubUrl = "http://tracer.azurewebsites.net/"; + const string HubName = "Tracer"; + + static void Main(string[] args) + { + Tracer.Initialize(new TracerManager()); + + tracer.Info("Starting TracerHub Console"); + + if (args.Length != 1) + { + Console.WriteLine("Usage: " + typeof(Program).Assembly.ManifestModule.FullyQualifiedName + " groupName"); + Console.WriteLine("Press [Enter] to exit."); + Console.ReadLine(); + return; + } + + var data = new Dictionary + { + { "groupName", args[0] } + }; + + using (var hub = new HubConnection(TracerHubUrl, data)) + { + IHubProxy proxy = hub.CreateHubProxy(HubName); + IDisposable handler = proxy.On("TraceEvent", trace => Tracer.Get(trace.Source).Trace(trace.EventType, trace.Message)); + + hub.Start().Wait(); + + Console.WriteLine("Broadcast trace event: [E(rror)|I(nformation)|W(arning)]:[Source]:[Message]"); + Console.WriteLine("Quit: Q|q"); + var line = Console.ReadLine(); + + while (!line.Equals("Q", StringComparison.InvariantCultureIgnoreCase)) + { + var trace = line.Split(new [] { ':' }, StringSplitOptions.RemoveEmptyEntries); + if (trace.Length == 3) + { + TraceEventType type = TraceEventType.Information; + switch (trace[0]) + { + case "E": + type = TraceEventType.Error; + break; + case "W": + type = TraceEventType.Warning; + break; + default: + break; + } + + proxy.Invoke("BroadcastTraceEvent", new TraceEvent + { + EventType = type, + Source = trace[1], + Message = trace[2], + }); + } + + line = Console.ReadLine(); + } + } + } + } +} diff --git a/Tracer.Console/Properties/AssemblyInfo.cs b/Tracer.Console/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..04c1d80 --- /dev/null +++ b/Tracer.Console/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TracerHub.Console")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TracerHub.Console")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("129b66ce-7f4a-4a72-aa90-b254cd868a20")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tracer.Console/Tracer.Console.csproj b/Tracer.Console/Tracer.Console.csproj new file mode 100644 index 0000000..cd47e34 --- /dev/null +++ b/Tracer.Console/Tracer.Console.csproj @@ -0,0 +1,83 @@ + + + + + Debug + AnyCPU + {BBFB96A3-3191-4BFD-8EE3-BE3C38EA8D04} + Exe + Properties + Tracer + Tracer + v4.0 + 512 + + ..\ + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + ..\packages\Microsoft.AspNet.SignalR.Client.2.0.1\lib\net40\Microsoft.AspNet.SignalR.Client.dll + + + ..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll + + + + + + + + + + + + TraceEvent.cs + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tracer.Console/app.config b/Tracer.Console/app.config new file mode 100644 index 0000000..54a3225 --- /dev/null +++ b/Tracer.Console/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Tracer.Console/netfx/System/AppDomainData.cs b/Tracer.Console/netfx/System/AppDomainData.cs new file mode 100644 index 0000000..f235565 --- /dev/null +++ b/Tracer.Console/netfx/System/AppDomainData.cs @@ -0,0 +1,89 @@ +#region BSD License +/* +Copyright (c) 2010, NETFx +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +/// +/// Provides strong-typed access to AppDomain storage data. +/// +/// +internal static class AppDomainData +{ + /// + /// Sets the given data in the storage. The returned + /// can be used to remove the state + /// when disposed. + /// + public static IDisposable SetData(T data) + where T : class + { + return AppDomain.CurrentDomain.SetData(data); + } + + /// + /// Gets the data from the storage. + /// + public static T GetData() + where T : class + { + return AppDomain.CurrentDomain.GetData(); + } + + /// + /// Sets the given data in the storage. The returned + /// can be used to remove the state + /// when disposed. + /// + /// The domain to set the data on. + /// The data to save. + public static IDisposable SetData(this AppDomain domain, T data) + where T : class + { + return new TransientData(domain, data, domain.GetData()); + } + + /// + /// Gets the data from the storage. + /// + /// The domain to get the data. + public static T GetData(this AppDomain domain) + where T : class + { + return (T)domain.GetData(typeof(T).FullName); + } + + private class TransientData : IDisposable + where T : class + { + private T oldData; + private AppDomain domain; + + public TransientData(AppDomain domain, T newData, T oldData) + { + this.domain = domain; + this.oldData = oldData; + this.domain.SetData(typeof(T).FullName, newData); + } + + public void Dispose() + { + this.domain.SetData(typeof(T).FullName, this.oldData); + } + } +} diff --git a/Tracer.Console/netfx/System/Collections/Generic/DictionaryGetOrAdd.cs b/Tracer.Console/netfx/System/Collections/Generic/DictionaryGetOrAdd.cs new file mode 100644 index 0000000..cf9100e --- /dev/null +++ b/Tracer.Console/netfx/System/Collections/Generic/DictionaryGetOrAdd.cs @@ -0,0 +1,56 @@ +#region BSD License +/* +Copyright (c) 2010, NETFx +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#endregion +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +/// +/// Adds a key/value pair to the if the key does not already exist. +/// +internal static partial class DictionaryGetOrAdd +{ + /// + /// Adds a key/value pair to the if the key does not already exist. + /// No locking occurs, so the value may be calculated twice on concurrent scenarios. If you need + /// concurrency assurances, use a concurrent dictionary instead. + /// + /// + /// The dictionary where the key/value pair will be added + /// The key to be added to the dictionary + /// The value factory + public static TValue GetOrAdd(this IDictionary dictionary, TKey key, Func valueFactory) + { + var value = default(TValue); + if (!dictionary.TryGetValue(key, out value)) + { + // ConcurrentDictionary does a bucket-level lock, which is more efficient. + // We don't have access to the inner buckets, so we have to look the entire + // dictionary. + lock (dictionary) + { + if (!dictionary.TryGetValue(key, out value)) + { + value = valueFactory(key); + dictionary[key] = value; + } + } + } + + return value; + } +} \ No newline at end of file diff --git a/Tracer.Console/packages.config b/Tracer.Console/packages.config new file mode 100644 index 0000000..eabe39f --- /dev/null +++ b/Tracer.Console/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Tracer.Realtime/External/Diagnostics/Tracer/ITracer.cs b/Tracer.Realtime/External/Diagnostics/Tracer/ITracer.cs new file mode 100644 index 0000000..07e0273 --- /dev/null +++ b/Tracer.Realtime/External/Diagnostics/Tracer/ITracer.cs @@ -0,0 +1,64 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace System.Diagnostics +{ + using System; + using System.Diagnostics; + + /// + /// Interface used by the application components to log messages. + /// + /// + partial interface ITracer + { + /// + /// Traces the specified message with the given . + /// + void Trace(TraceEventType type, object message); + + /// + /// Traces the specified formatted message with the given . + /// + void Trace(TraceEventType type, string format, params object[] args); + + /// + /// Traces an exception with the specified message and . + /// + void Trace(TraceEventType type, Exception exception, object message); + + /// + /// Traces an exception with the specified formatted message and . + /// + void Trace(TraceEventType type, Exception exception, string format, params object[] args); + } +} diff --git a/Tracer.Realtime/External/Diagnostics/Tracer/ITracerExtensions.cs b/Tracer.Realtime/External/Diagnostics/Tracer/ITracerExtensions.cs new file mode 100644 index 0000000..bcb90d1 --- /dev/null +++ b/Tracer.Realtime/External/Diagnostics/Tracer/ITracerExtensions.cs @@ -0,0 +1,224 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace System.Diagnostics +{ + using System; + using System.Diagnostics; + + /// + /// Provides usability overloads for tracing to a . + /// + /// + static partial class ITracerExtensions + { + #region Critical overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Critical(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Critical, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Critical(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Critical, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Critical(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Critical, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Critical(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Critical, exception, format, args); + } + + #endregion + + #region Error overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Error(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Error, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Error(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Error, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Error(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Error, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Error(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Error, exception, format, args); + } + + #endregion + + #region Warn overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Warn(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Warning, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Warn(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Warning, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Warn(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Warning, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Warn(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Warning, exception, format, args); + } + + #endregion + + #region Info overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Info(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Information, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Info(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Information, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Info(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Information, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Info(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Information, exception, format, args); + } + + #endregion + + #region Verbose overloads + + /// + /// Traces an event of type with the given message; + /// + public static void Verbose(this ITracer tracer, object message) + { + tracer.Trace(TraceEventType.Verbose, message); + } + + /// + /// Traces an event of type with the given format string and arguments. + /// + public static void Verbose(this ITracer tracer, string format, params object[] args) + { + tracer.Trace(TraceEventType.Verbose, format, args); + } + + /// + /// Traces an event of type with the given exception and message. + /// + public static void Verbose(this ITracer tracer, Exception exception, object message) + { + tracer.Trace(TraceEventType.Verbose, exception, message); + } + + /// + /// Traces an event of type with the given exception, format string and arguments. + /// + public static void Verbose(this ITracer tracer, Exception exception, string format, params object[] args) + { + tracer.Trace(TraceEventType.Verbose, exception, format, args); + } + + #endregion + } +} diff --git a/Tracer.Realtime/External/Diagnostics/Tracer/ITracerManager.cs b/Tracer.Realtime/External/Diagnostics/Tracer/ITracerManager.cs new file mode 100644 index 0000000..2a6cbc5 --- /dev/null +++ b/Tracer.Realtime/External/Diagnostics/Tracer/ITracerManager.cs @@ -0,0 +1,47 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace System.Diagnostics +{ + /// + /// Manages instances. Provides the implementation + /// for the static facade class. + /// + /// + partial interface ITracerManager + { + /// + /// Gets a tracer instance with the specified name. + /// + ITracer Get(string name); + } +} diff --git a/Tracer.Realtime/External/Diagnostics/Tracer/Tracer.cs b/Tracer.Realtime/External/Diagnostics/Tracer/Tracer.cs new file mode 100644 index 0000000..92ea329 --- /dev/null +++ b/Tracer.Realtime/External/Diagnostics/Tracer/Tracer.cs @@ -0,0 +1,160 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace System.Diagnostics +{ + using System; + using System.Diagnostics; + using System.Linq; + + /// + /// Provides access to tracer instances. + /// + /// + static partial class Tracer + { + private static ITracerManager manager = new DefaultManager(); + + /// + /// Provides the implementation for managing tracers. + /// + internal static void Initialize(ITracerManager manager) + { + Tracer.manager = manager; + } + + /// + /// Gets a tracer instance with the full type name of . + /// + public static ITracer Get() + { + return manager.Get(NameFor(typeof(T))); + } + + /// + /// Gets a tracer instance with the full type name of the . + /// + public static ITracer Get(Type type) + { + return manager.Get(NameFor(type)); + } + + /// + /// Gets a tracer instance with the given name. + /// + public static ITracer Get(string name) + { + return manager.Get(name); + } + + + /// + /// Gets the tracer name for the given type. + /// + public static string NameFor() + { + return NameFor(typeof(T)); + } + + /// + /// Gets the tracer name for the given type. + /// + public static string NameFor(Type type) + { + if (type.IsGenericType) + { + var genericName = type.GetGenericTypeDefinition().FullName; + + return genericName.Substring(0, genericName.IndexOf('`')) + + "<" + + string.Join(",", type.GetGenericArguments().Select(t => NameFor(t)).ToArray()) + + ">"; + } + + return type.FullName; + } + + private partial class DefaultManager : ITracerManager + { + public ITracer Get(string name) + { + return new DefaultTracer(name); + } + + private class DefaultTracer : ITracer + { + private string name; + + public DefaultTracer(string name) + { + this.name = name; + } + + public void Trace(TraceEventType type, object message) + { + Trace(type, message.ToString()); + } + + public void Trace(TraceEventType type, string format, params object[] args) + { + Trace(type, Format(format, args)); + } + + public void Trace(TraceEventType type, Exception exception, object message) + { + Trace(type, message + Environment.NewLine + exception.ToString()); + } + + public void Trace(TraceEventType type, Exception exception, string format, params object[] args) + { + Trace(type, Format(format, args) + Environment.NewLine + exception.ToString()); + } + + private void Trace(TraceEventType type, string message) + { + System.Diagnostics.Debug.Write(string.Format( + "[{0}::{1}] ", + this.name, type, message)); + System.Diagnostics.Debug.WriteLine(message); + } + + private string Format(string format, object[] args) + { + if (args != null && args.Length != 0) + return string.Format(format, args); + + return format; + } + } + } + } +} diff --git a/Tracer.Realtime/External/Diagnostics/Tracer/Visibility.cs b/Tracer.Realtime/External/Diagnostics/Tracer/Visibility.cs new file mode 100644 index 0000000..3362b62 --- /dev/null +++ b/Tracer.Realtime/External/Diagnostics/Tracer/Visibility.cs @@ -0,0 +1,42 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace System.Diagnostics +{ + // Changes to this file will not be overwritten by NuGet when updating. + // To make the entire API public, just uncomment the following code: + + //public partial interface ITracer { } + //public static partial class ITracerExtensions { } + //public partial interface ITracerManager { } + //public static partial class Tracer { } +} diff --git a/Tracer.Realtime/Package.nuspec b/Tracer.Realtime/Package.nuspec new file mode 100644 index 0000000..13dba27 --- /dev/null +++ b/Tracer.Realtime/Package.nuspec @@ -0,0 +1,26 @@ + + + + Tracer.Realtime + 1.0 + Tracer: Realtime Trace Listener + A trace listener that leverages SignalR to enable remote real-time diagnostics of apps. + A trace listener that leverages SignalR to enable remote real-time diagnostics of apps. + Daniel Cazzulino + en-US + http://netfx.codeplex.com + http://netfx.codeplex.com/license + http://download.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=netfx&DownloadId=199201 + diagnostics tracing signalr clariuslabs + + + + + + + + Version 1.0 + * Issues TraceEvent calls via SignalR for remote real-time diagnostics + + + \ No newline at end of file diff --git a/Tracer.Realtime/Properties/AssemblyInfo.cs b/Tracer.Realtime/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b7545ef --- /dev/null +++ b/Tracer.Realtime/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tracer.Hub.Listener")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tracer.Hub.Listener")] +[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("be663797-2d41-4f3b-a15e-d4db6e69bc78")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tracer.Realtime/Tracer.Hub.Listener.t4properties b/Tracer.Realtime/Tracer.Hub.Listener.t4properties new file mode 100644 index 0000000..351393b --- /dev/null +++ b/Tracer.Realtime/Tracer.Hub.Listener.t4properties @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Tracer.Realtime/Tracer.Realtime.csproj b/Tracer.Realtime/Tracer.Realtime.csproj new file mode 100644 index 0000000..7d58e11 --- /dev/null +++ b/Tracer.Realtime/Tracer.Realtime.csproj @@ -0,0 +1,92 @@ + + + + Debug + AnyCPU + {3427C0BD-B887-4A38-A24D-3C45326440DB} + Library + Properties + System + Tracer.Realtime + v4.0 + 512 + + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.AspNet.SignalR.Client.2.0.1\lib\net40\Microsoft.AspNet.SignalR.Client.dll + + + ..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + Designer + PreserveNewest + + + TextTemplatingFileGenerator + RealtimeTraceListener.cs.pp + + + TextTemplatingFileGenerator + TraceEvent.cs.pp + + + TraceEvent.tt + True + True + PreserveNewest + + + True + True + RealtimeTraceListener.tt + PreserveNewest + + + + + + + + + + \ No newline at end of file diff --git a/Tracer.Realtime/Tracer.Realtime.t4properties b/Tracer.Realtime/Tracer.Realtime.t4properties new file mode 100644 index 0000000..53d0e58 --- /dev/null +++ b/Tracer.Realtime/Tracer.Realtime.t4properties @@ -0,0 +1,15 @@ + + + + + content\net40\External\Diagnostics\Tracer\RealtimeTraceListener.tt + Host + VisualStudio + + + content\net40\External\Diagnostics\Tracer\TraceEvent.tt + Host + VisualStudio + + + \ No newline at end of file diff --git a/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs new file mode 100644 index 0000000..5402f80 --- /dev/null +++ b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs @@ -0,0 +1,139 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace Realtime +{ + using Microsoft.AspNet.SignalR.Client; + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Diagnostics; + using System.Globalization; + + public class RealtimeTraceListener : TraceListener + { + /// + /// The SignalR hosted hub. Change to your own host URL if self-hosting. + /// + const string TracerHubUrl = "http://tracer.azurewebsites.net/"; + const string HubName = "Tracer"; + + static readonly string hubUrl; + string groupName; + HubConnection hub; + IHubProxy proxy; + + /// + /// Initializes the Hub URL from the HubUrl appSettings configuration + /// value, or sets it to the default tracer hub. + /// + static RealtimeTraceListener() + { + hubUrl = ConfigurationManager.AppSettings["HubUrl"]; + if (string.IsNullOrEmpty(hubUrl)) + hubUrl = TracerHubUrl; + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the group within the hub to broadcast traces to. + public RealtimeTraceListener(string groupName) + { + if (string.IsNullOrEmpty(groupName)) + throw new ArgumentException("String value for groupName cannot be empty or null.", "groupName"); + + this.groupName = groupName; + } + + public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) + { + if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null)) + { + DoTraceEvent(eventCache, source, eventType, id, message); + } + } + + public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) + { + if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) + { + if (args == null || args.Length == 0) + DoTraceEvent(eventCache, source, eventType, id, format); + else + DoTraceEvent(eventCache, source, eventType, id, string.Format(CultureInfo.InvariantCulture, format, args)); + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (hub != null) + hub.Dispose(); + } + + // NOTE: Tracer.SystemDiagnostics for .NET 4.0+ (required to use this listener) + // always traces asynchronously, so it's fine to just Wait() here for the connection, + // since this would NOT be slowing down the app in any way. Also, Tracer will trace + // in a single background thread, so this is automatically "thread-safe" without needing + // an explicit lock. + private void DoTraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) + { + if (hub == null) + { + var data = new Dictionary + { + { "groupName", groupName } + }; + + hub = new HubConnection(hubUrl, data); + proxy = hub.CreateHubProxy(HubName); + hub.Start().Wait(); + } + + proxy.Invoke("BroadcastTraceEvent", new TraceEvent + { + EventType = eventType, + Source = source, + Message = message, + }); + } + + public override void Write(string message) + { + } + + public override void WriteLine(string message) + { + } + } +} diff --git a/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs.pp b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs.pp new file mode 100644 index 0000000..1039745 --- /dev/null +++ b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.cs.pp @@ -0,0 +1,139 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace $rootnamespace$ +{ + using Microsoft.AspNet.SignalR.Client; + using System; + using System.Collections.Generic; + using System.Configuration; + using System.Diagnostics; + using System.Globalization; + + public class RealtimeTraceListener : TraceListener + { + /// + /// The SignalR hosted hub. Change to your own host URL if self-hosting. + /// + const string TracerHubUrl = "http://tracer.azurewebsites.net/"; + const string HubName = "Tracer"; + + static readonly string hubUrl; + string groupName; + HubConnection hub; + IHubProxy proxy; + + /// + /// Initializes the Hub URL from the HubUrl appSettings configuration + /// value, or sets it to the default tracer hub. + /// + static RealtimeTraceListener() + { + hubUrl = ConfigurationManager.AppSettings["HubUrl"]; + if (string.IsNullOrEmpty(hubUrl)) + hubUrl = TracerHubUrl; + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the group within the hub to broadcast traces to. + public RealtimeTraceListener(string groupName) + { + if (string.IsNullOrEmpty(groupName)) + throw new ArgumentException("String value for groupName cannot be empty or null.", "groupName"); + + this.groupName = groupName; + } + + public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) + { + if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null)) + { + DoTraceEvent(eventCache, source, eventType, id, message); + } + } + + public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args) + { + if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null)) + { + if (args == null || args.Length == 0) + DoTraceEvent(eventCache, source, eventType, id, format); + else + DoTraceEvent(eventCache, source, eventType, id, string.Format(CultureInfo.InvariantCulture, format, args)); + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (hub != null) + hub.Dispose(); + } + + // NOTE: Tracer.SystemDiagnostics for .NET 4.0+ (required to use this listener) + // always traces asynchronously, so it's fine to just Wait() here for the connection, + // since this would NOT be slowing down the app in any way. Also, Tracer will trace + // in a single background thread, so this is automatically "thread-safe" without needing + // an explicit lock. + private void DoTraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message) + { + if (hub == null) + { + var data = new Dictionary + { + { "groupName", groupName } + }; + + hub = new HubConnection(hubUrl, data); + proxy = hub.CreateHubProxy(HubName); + hub.Start().Wait(); + } + + proxy.Invoke("BroadcastTraceEvent", new TraceEvent + { + EventType = eventType, + Source = source, + Message = message, + }); + } + + public override void Write(string message) + { + } + + public override void WriteLine(string message) + { + } + } +} diff --git a/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.tt b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.tt new file mode 100644 index 0000000..a1eb0a2 --- /dev/null +++ b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/RealtimeTraceListener.tt @@ -0,0 +1,4 @@ +<#@ template debug="false" hostspecific="true" language="C#" #> +<#@ output extension=".cs.pp" #> +<#@ import namespace="System.IO" #> +<#= File.ReadAllText(Path.ChangeExtension(this.Host.TemplateFile, ".cs")).Replace("namespace Realtime", "namespace $rootnamespace$") #> \ No newline at end of file diff --git a/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs new file mode 100644 index 0000000..0a4b599 --- /dev/null +++ b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs @@ -0,0 +1,57 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace Realtime +{ + using System.Diagnostics; + + /// + /// Payload data to send to the hub about the traced event. + /// + public class TraceEvent + { + /// + /// Gets or sets the type of the event trace. + /// + public TraceEventType EventType { get; set; } + + /// + /// Gets or sets the trace message. + /// + public string Message { get; set; } + + /// + /// Gets or sets the source of the trace event. + /// + public string Source { get; set; } + } +} diff --git a/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs.pp b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs.pp new file mode 100644 index 0000000..91bdabd --- /dev/null +++ b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.cs.pp @@ -0,0 +1,57 @@ +#region BSD License +/* +Copyright (c) 2011, Clarius Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of Clarius Consulting nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ +#endregion + +namespace $rootnamespace$ +{ + using System.Diagnostics; + + /// + /// Payload data to send to the hub about the traced event. + /// + public class TraceEvent + { + /// + /// Gets or sets the type of the event trace. + /// + public TraceEventType EventType { get; set; } + + /// + /// Gets or sets the trace message. + /// + public string Message { get; set; } + + /// + /// Gets or sets the source of the trace event. + /// + public string Source { get; set; } + } +} diff --git a/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.tt b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.tt new file mode 100644 index 0000000..a1eb0a2 --- /dev/null +++ b/Tracer.Realtime/content/net40/External/Diagnostics/Tracer/TraceEvent.tt @@ -0,0 +1,4 @@ +<#@ template debug="false" hostspecific="true" language="C#" #> +<#@ output extension=".cs.pp" #> +<#@ import namespace="System.IO" #> +<#= File.ReadAllText(Path.ChangeExtension(this.Host.TemplateFile, ".cs")).Replace("namespace Realtime", "namespace $rootnamespace$") #> \ No newline at end of file diff --git a/Tracer.Realtime/packages.config b/Tracer.Realtime/packages.config new file mode 100644 index 0000000..12e667f --- /dev/null +++ b/Tracer.Realtime/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Tracer.SystemDiagnostics/Tracer.SystemDiagnostics.csproj b/Tracer.SystemDiagnostics/Tracer.SystemDiagnostics.csproj index 69cd3d8..8ec3257 100644 --- a/Tracer.SystemDiagnostics/Tracer.SystemDiagnostics.csproj +++ b/Tracer.SystemDiagnostics/Tracer.SystemDiagnostics.csproj @@ -1,117 +1,117 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {3AFCD64A-029F-4842-A2E0-51D9EE380040} - Library - Properties - System.Diagnostics - Tracer.SystemDiagnostics - v4.0 - 512 - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - TextTemplatingFileGenerator - StartActivityExtension.cs - - - PreserveNewest - - - PreserveNewest - - - StartActivityExtension.tt - True - True - - - TracerManager.tt - True - True - - - PreserveNewest - - - PreserveNewest - - - StartActivityExtension.tt - True - True - - - TracerManager.tt - True - True - - - - - - - - PreserveNewest - Designer - - - - - TextTemplatingFileGenerator - TracerManager.cs - - - TextTemplatingFileGenerator - StartActivityExtension.cs - - - TextTemplatingFileGenerator - TracerManager.cs - - - - - - - - - {EFD24E29-A093-49E4-A1E2-770E39FCC39B} - Tracer.Interfaces - - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {3AFCD64A-029F-4842-A2E0-51D9EE380040} + Library + Properties + System.Diagnostics + Tracer.SystemDiagnostics + v4.0 + 512 + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + TextTemplatingFileGenerator + StartActivityExtension.cs + + + PreserveNewest + + + PreserveNewest + + + StartActivityExtension.tt + True + True + + + TracerManager.tt + True + True + + + PreserveNewest + + + PreserveNewest + + + StartActivityExtension.tt + True + True + + + TracerManager.tt + True + True + + + + + + + + PreserveNewest + Designer + + + + + TextTemplatingFileGenerator + TracerManager.cs + + + TextTemplatingFileGenerator + StartActivityExtension.cs + + + TextTemplatingFileGenerator + TracerManager.cs + + + + + + + + + {EFD24E29-A093-49E4-A1E2-770E39FCC39B} + Tracer.Interfaces + + + + + \ No newline at end of file diff --git a/Tracer.UnitTests/RealtimeSpec.cs b/Tracer.UnitTests/RealtimeSpec.cs new file mode 100644 index 0000000..4fa70f4 --- /dev/null +++ b/Tracer.UnitTests/RealtimeSpec.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNet.SignalR.Client; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using Xunit; + +namespace Tracer.UnitTests +{ + public class RealtimeSpec + { + const string TracerHubUrl = "http://tracer.azurewebsites.net/"; + const string HubName = "Tracer"; + + [Fact] + public void when_tracing_via_hub_then_client_gets_trace() + { + var traces = new List(); + var source = new TraceSource("Source", SourceLevels.Information); + using (var listener = new RealtimeTraceListener("Test")) + { + source.Listeners.Add(listener); + + var data = new Dictionary + { + { "groupName", "Test" } + }; + + using (var hub = new HubConnection(TracerHubUrl, data)) + { + IHubProxy proxy = hub.CreateHubProxy(HubName); + proxy.On("TraceEvent", trace => traces.Add(trace)); + + hub.Start().Wait(); + + source.TraceInformation("Foo"); + + var watch = Stopwatch.StartNew(); + var timeout = TimeSpan.FromSeconds(2); + while (watch.Elapsed < timeout) + { + Thread.Sleep(100); + } + + Assert.Equal(1, traces.Count); + Assert.Equal(TraceEventType.Information, traces[0].EventType); + Assert.Equal("Source", traces[0].Source); + Assert.Equal("Foo", traces[0].Message); + } + } + } + } +} diff --git a/Tracer.UnitTests/Tracer.UnitTests.csproj b/Tracer.UnitTests/Tracer.UnitTests.csproj index 8955f1e..36f5aa3 100644 --- a/Tracer.UnitTests/Tracer.UnitTests.csproj +++ b/Tracer.UnitTests/Tracer.UnitTests.csproj @@ -1,76 +1,80 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {837D4AB8-AE2F-498A-B519-95A1F692FEDD} - Library - Properties - Tracer.UnitTests - Tracer.UnitTests - v4.0 - 512 - ..\ - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\Moq.4.0.10827\lib\NET40\Moq.dll - - - - - - ..\packages\xunit.1.9.1\lib\net20\xunit.dll - - - - - - - - - - {3AFCD64A-029F-4842-A2E0-51D9EE380040} - Tracer.SystemDiagnostics - - - {EFD24E29-A093-49E4-A1E2-770E39FCC39B} - Tracer.Interfaces - - - - - Designer - - - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {837D4AB8-AE2F-498A-B519-95A1F692FEDD} + Library + Properties + Tracer.UnitTests + Tracer.UnitTests + v4.0 + 512 + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Microsoft.AspNet.SignalR.Client.2.0.1\lib\net40\Microsoft.AspNet.SignalR.Client.dll + + + ..\packages\Moq.4.0.10827\lib\NET40\Moq.dll + + + ..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll + + + + + + ..\packages\xunit.1.9.1\lib\net20\xunit.dll + + + + + + + + + + + {3427c0bd-b887-4a38-a24d-3c45326440db} + Tracer.Realtime + + + {3AFCD64A-029F-4842-A2E0-51D9EE380040} + Tracer.SystemDiagnostics + + + {EFD24E29-A093-49E4-A1E2-770E39FCC39B} + Tracer.Interfaces + + + + + Designer + + + + + \ No newline at end of file diff --git a/Tracer.UnitTests/packages.config b/Tracer.UnitTests/packages.config index 4bc4ebd..5462f9e 100644 --- a/Tracer.UnitTests/packages.config +++ b/Tracer.UnitTests/packages.config @@ -1,5 +1,7 @@ - - - - + + + + + + \ No newline at end of file diff --git a/Tracer.licenseheader b/Tracer.licenseheader new file mode 100644 index 0000000..2a7ebc5 --- /dev/null +++ b/Tracer.licenseheader @@ -0,0 +1,35 @@ +extensions: designer.cs generated.cs +extensions: .cs +/* + Copyright 2014 Clarius Consulting + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +*/ + + +extensions: .css +/* + Copyright 2014 Clarius Consulting + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +*/ + + +extensions: .xml .config .html + \ No newline at end of file diff --git a/Tracer.sln b/Tracer.sln index 1ca250e..201b82d 100644 --- a/Tracer.sln +++ b/Tracer.sln @@ -1,69 +1,81 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.Interfaces", "Tracer.Interfaces\Tracer.Interfaces.csproj", "{EFD24E29-A093-49E4-A1E2-770E39FCC39B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.SystemDiagnostics", "Tracer.SystemDiagnostics\Tracer.SystemDiagnostics.csproj", "{3AFCD64A-029F-4842-A2E0-51D9EE380040}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.Log4Net", "Tracer.Log4Net\Tracer.Log4Net.csproj", "{B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3CBD7C4D-9EDC-483D-B973-990B74B2629A}" - ProjectSection(SolutionItems) = preProject - Common.ps1 = Common.ps1 - Drop.ps1 = Drop.ps1 - Push.ps1 = Push.ps1 - README.md = README.md - Tracer.targets = Tracer.targets - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.NLog", "Tracer.NLog\Tracer.NLog.csproj", "{11320BEC-B651-4849-A946-F04B8AE87A0B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.EntLib", "Tracer.EntLib\Tracer.EntLib.csproj", "{D159F0B7-DF31-4E73-BE9E-78634536A000}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.UnitTests", "Tracer.UnitTests\Tracer.UnitTests.csproj", "{837D4AB8-AE2F-498A-B519-95A1F692FEDD}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A21AF209-0D38-4E20-9290-81AA7416451D}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - .nuget\nuget.exe = .nuget\nuget.exe - .nuget\NuGet.targets = .nuget\NuGet.targets - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Release|Any CPU.Build.0 = Release|Any CPU - {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Release|Any CPU.Build.0 = Release|Any CPU - {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Release|Any CPU.Build.0 = Release|Any CPU - {11320BEC-B651-4849-A946-F04B8AE87A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {11320BEC-B651-4849-A946-F04B8AE87A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {11320BEC-B651-4849-A946-F04B8AE87A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {11320BEC-B651-4849-A946-F04B8AE87A0B}.Release|Any CPU.Build.0 = Release|Any CPU - {D159F0B7-DF31-4E73-BE9E-78634536A000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D159F0B7-DF31-4E73-BE9E-78634536A000}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D159F0B7-DF31-4E73-BE9E-78634536A000}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D159F0B7-DF31-4E73-BE9E-78634536A000}.Release|Any CPU.Build.0 = Release|Any CPU - {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35;packages\Unity.Interception.2.1.505.2\lib\NET35;packages\EnterpriseLibrary.Common.5.0.505.0\lib\NET35;packages\EnterpriseLibrary.Logging.5.0.505.1\lib\NET35 - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.Interfaces", "Tracer.Interfaces\Tracer.Interfaces.csproj", "{EFD24E29-A093-49E4-A1E2-770E39FCC39B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.SystemDiagnostics", "Tracer.SystemDiagnostics\Tracer.SystemDiagnostics.csproj", "{3AFCD64A-029F-4842-A2E0-51D9EE380040}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.Log4Net", "Tracer.Log4Net\Tracer.Log4Net.csproj", "{B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3CBD7C4D-9EDC-483D-B973-990B74B2629A}" + ProjectSection(SolutionItems) = preProject + Common.ps1 = Common.ps1 + Drop.ps1 = Drop.ps1 + Push.ps1 = Push.ps1 + README.md = README.md + Tracer.targets = Tracer.targets + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.NLog", "Tracer.NLog\Tracer.NLog.csproj", "{11320BEC-B651-4849-A946-F04B8AE87A0B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.EntLib", "Tracer.EntLib\Tracer.EntLib.csproj", "{D159F0B7-DF31-4E73-BE9E-78634536A000}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.UnitTests", "Tracer.UnitTests\Tracer.UnitTests.csproj", "{837D4AB8-AE2F-498A-B519-95A1F692FEDD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A21AF209-0D38-4E20-9290-81AA7416451D}" + ProjectSection(SolutionItems) = preProject + .nuget\NuGet.Config = .nuget\NuGet.Config + .nuget\nuget.exe = .nuget\nuget.exe + .nuget\NuGet.targets = .nuget\NuGet.targets + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.Console", "Tracer.Console\Tracer.Console.csproj", "{BBFB96A3-3191-4BFD-8EE3-BE3C38EA8D04}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tracer.Realtime", "Tracer.Realtime\Tracer.Realtime.csproj", "{3427C0BD-B887-4A38-A24D-3C45326440DB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFD24E29-A093-49E4-A1E2-770E39FCC39B}.Release|Any CPU.Build.0 = Release|Any CPU + {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AFCD64A-029F-4842-A2E0-51D9EE380040}.Release|Any CPU.Build.0 = Release|Any CPU + {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9D6F750-F0E3-4D4A-B3BD-80A517C7614E}.Release|Any CPU.Build.0 = Release|Any CPU + {11320BEC-B651-4849-A946-F04B8AE87A0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11320BEC-B651-4849-A946-F04B8AE87A0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11320BEC-B651-4849-A946-F04B8AE87A0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11320BEC-B651-4849-A946-F04B8AE87A0B}.Release|Any CPU.Build.0 = Release|Any CPU + {D159F0B7-DF31-4E73-BE9E-78634536A000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D159F0B7-DF31-4E73-BE9E-78634536A000}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D159F0B7-DF31-4E73-BE9E-78634536A000}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D159F0B7-DF31-4E73-BE9E-78634536A000}.Release|Any CPU.Build.0 = Release|Any CPU + {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {837D4AB8-AE2F-498A-B519-95A1F692FEDD}.Release|Any CPU.Build.0 = Release|Any CPU + {BBFB96A3-3191-4BFD-8EE3-BE3C38EA8D04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBFB96A3-3191-4BFD-8EE3-BE3C38EA8D04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBFB96A3-3191-4BFD-8EE3-BE3C38EA8D04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BBFB96A3-3191-4BFD-8EE3-BE3C38EA8D04}.Release|Any CPU.Build.0 = Release|Any CPU + {3427C0BD-B887-4A38-A24D-3C45326440DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3427C0BD-B887-4A38-A24D-3C45326440DB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3427C0BD-B887-4A38-A24D-3C45326440DB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3427C0BD-B887-4A38-A24D-3C45326440DB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35;packages\Unity.Interception.2.1.505.2\lib\NET35;packages\EnterpriseLibrary.Common.5.0.505.0\lib\NET35;packages\EnterpriseLibrary.Logging.5.0.505.1\lib\NET35 + EndGlobalSection +EndGlobal