summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Diagnostics/log.cs
blob: f38eaccabc2efc343966a14738ad5b576a81e9a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Diagnostics
{
    using System;
    using System.IO;
    using System.Collections;
    using System.Runtime.CompilerServices;
    using Encoding = System.Text.Encoding;
    using System.Runtime.Versioning;
    using System.Diagnostics.CodeAnalysis;

    using Console = Internal.Console;

    // LogSwitchLevelHandlers are triggered when the level of a LogSwitch is modified
    // NOTE: These are NOT triggered when the log switch setting is changed from the 
    // attached debugger.
    // 
    internal delegate void LogSwitchLevelHandler(LogSwitch ls, LoggingLevels newLevel);


    internal static class Log
    {
        // Switches allow relatively fine level control of which messages are
        // actually shown.  Normally most debugging messages are not shown - the
        // user will typically enable those which are relevant to what is being
        // investigated.
        // 
        // An attached debugger can enable or disable which messages will
        // actually be reported to the user through the COM+ debugger
        // services API.  This info is communicated to the runtime so only
        // desired events are actually reported to the debugger.  
        internal static Hashtable m_Hashtable;
        private static volatile bool m_fConsoleDeviceEnabled;
        private static volatile LogSwitchLevelHandler _LogSwitchLevelHandler;
        private static Object locker;

        // Constant representing the global switch
        public static readonly LogSwitch GlobalSwitch;


        static Log()
        {
            m_Hashtable = new Hashtable();
            m_fConsoleDeviceEnabled = false;
            //pConsole = null;
            //iNumOfMsgHandlers = 0;
            //iMsgHandlerArraySize = 0;
            locker = new Object();

            // allocate the GlobalSwitch object
            GlobalSwitch = new LogSwitch("Global", "Global Switch for this log");

            GlobalSwitch.MinimumLevel = LoggingLevels.ErrorLevel;
        }

        internal static void InvokeLogSwitchLevelHandlers(LogSwitch ls, LoggingLevels newLevel)
        {
            LogSwitchLevelHandler handler = _LogSwitchLevelHandler;
            if (handler != null)
                handler(ls, newLevel);
        }


        // Property to Enable/Disable ConsoleDevice. Enabling the console device 
        // adds the console device as a log output, causing any
        // log messages which make it through filters to be written to the 
        // application console.  The console device is enabled by default if the 
        // ??? registry entry or ??? environment variable is set.
        public static bool IsConsoleEnabled
        {
            get { return m_fConsoleDeviceEnabled; }
            set { m_fConsoleDeviceEnabled = value; }
        }

        // Generates a log message. If its switch (or a parent switch) allows the 
        // level for the message, it is "broadcast" to all of the log
        // devices.
        // 
        public static void LogMessage(LoggingLevels level, LogSwitch logswitch, String message)
        {
            if (logswitch == null)
                throw new ArgumentNullException("LogSwitch");

            if (level < 0)
                throw new ArgumentOutOfRangeException(nameof(level), SR.ArgumentOutOfRange_NeedNonNegNum);

            // Is logging for this level for this switch enabled?
            if (logswitch.CheckLevel(level) == true)
            {
                // Send message for logging

                // first send it to the debugger
                Debugger.Log((int)level, logswitch.strName, message);

                // Send to the console device
                if (m_fConsoleDeviceEnabled)
                {
                    Console.Write(message);
                }
            }
        }

        /*
        * Following are convenience entry points; all go through Log()
        * Note that the (Switch switch, String message) variations 
        * are preferred.
        */
        public static void Trace(LogSwitch logswitch, String message)
        {
            LogMessage(LoggingLevels.TraceLevel0, logswitch, message);
        }

        public static void Trace(String message)
        {
            LogMessage(LoggingLevels.TraceLevel0, GlobalSwitch, message);
        }


        // Native method to inform the EE about the creation of a new LogSwitch
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void AddLogSwitch(LogSwitch logSwitch);
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void ModifyLogSwitch(int iNewLevel, String strSwitchName, String strParentName);
    }
}