예제 #1
0
        // parses a comma separated list of providers
        internal void ParseProviderList(string providerListText, CounterSet counters)
        {
            bool inParen  = false;
            int  startIdx = -1;
            int  i        = 0;

            for (; i < providerListText.Length; i++)
            {
                if (!inParen)
                {
                    if (providerListText[i] == '[')
                    {
                        inParen = true;
                        continue;
                    }
                    else if (providerListText[i] == ',')
                    {
                        if (startIdx < 0)
                        {
                            throw new FormatException("Expected non-empty counter_provider");
                        }
                        ParseCounterProvider(providerListText.Substring(startIdx, i - startIdx), counters);
                        startIdx = -1;
                    }
                    else if (startIdx == -1 && providerListText[i] != ' ')
                    {
                        startIdx = i;
                    }
                }
                else if (inParen && providerListText[i] == ']')
                {
                    inParen = false;
                }
            }
            if (inParen)
            {
                throw new FormatException("Expected to find closing ']' in counter_provider");
            }
            if (startIdx < 0)
            {
                throw new FormatException("Expected non-empty counter_provider");
            }
            ParseCounterProvider(providerListText.Substring(startIdx, i - startIdx), counters);
        }
예제 #2
0
        internal CounterSet ConfigureCounters(string commaSeparatedProviderListText, List <string> providerList)
        {
            CounterSet counters = new CounterSet();

            try
            {
                if (commaSeparatedProviderListText != null)
                {
                    ParseProviderList(commaSeparatedProviderListText, counters);
                }
            }
            catch (FormatException e)
            {
                // the FormatException message strings thrown by ParseProviderList are controlled
                // by us and anticipate being integrated into the command-line error text.
                throw new CommandLineErrorException("Error parsing --counters argument: " + e.Message);
            }

            if (providerList != null)
            {
                try
                {
                    foreach (string providerText in providerList)
                    {
                        ParseCounterProvider(providerText, counters);
                    }
                }
                catch (FormatException e)
                {
                    // the FormatException message strings thrown by ParseCounterProvider are controlled
                    // by us and anticipate being integrated into the command-line error text.
                    throw new CommandLineErrorException("Error parsing counter_list: " + e.Message);
                }
            }

            if (counters.IsEmpty)
            {
                _console.Out.WriteLine($"--counters is unspecified. Monitoring System.Runtime counters by default.");
                counters.AddAllProviderCounters("System.Runtime");
            }
            return(counters);
        }
예제 #3
0
        public async Task <int> Collect(
            CancellationToken ct,
            List <string> counter_list,
            string counters,
            IConsole console,
            int processId,
            int refreshInterval,
            CountersExportFormat format,
            string output,
            string name,
            string diagnosticPort,
            bool resumeRuntime,
            int maxHistograms,
            int maxTimeSeries)
        {
            try
            {
                // System.CommandLine does have an option to specify arguments as uint and it would validate they are non-negative. However the error
                // message is "Cannot parse argument '-1' for option '--maxTimeSeries' as expected type System.UInt32" which is not as user friendly.
                // If there was another option to leverage System.CommandLine that provides a little more user friendly error message we could switch
                // to it.
                ValidateNonNegative(maxHistograms, nameof(maxHistograms));
                ValidateNonNegative(maxTimeSeries, nameof(maxTimeSeries));
                if (!ProcessLauncher.Launcher.HasChildProc && !CommandUtils.ValidateArgumentsForAttach(processId, name, diagnosticPort, out _processId))
                {
                    return(ReturnCode.ArgumentError);
                }

                _ct.Register(() => _shouldExit.TrySetResult(ReturnCode.Ok));

                DiagnosticsClientBuilder builder = new DiagnosticsClientBuilder("dotnet-counters", 10);
                using (DiagnosticsClientHolder holder = await builder.Build(ct, _processId, diagnosticPort, showChildIO: false, printLaunchCommand: false))
                {
                    if (holder == null)
                    {
                        return(ReturnCode.Ok);
                    }

                    try
                    {
                        _console = console;
                        // the launch command may misinterpret app arguments as the old space separated
                        // provider list so we need to ignore it in that case
                        _counterList       = ConfigureCounters(counters, _processId != 0 ? counter_list : null);
                        _ct                = ct;
                        _interval          = refreshInterval;
                        _maxHistograms     = maxHistograms;
                        _maxTimeSeries     = maxTimeSeries;
                        _output            = output;
                        _diagnosticsClient = holder.Client;
                        if (_output.Length == 0)
                        {
                            _console.Error.WriteLine("Output cannot be an empty string");
                            return(ReturnCode.ArgumentError);
                        }
                        if (format == CountersExportFormat.csv)
                        {
                            _renderer = new CSVExporter(output);
                        }
                        else if (format == CountersExportFormat.json)
                        {
                            // Try getting the process name.
                            string processName = "";
                            try
                            {
                                if (ProcessLauncher.Launcher.HasChildProc)
                                {
                                    _processId = ProcessLauncher.Launcher.ChildProc.Id;
                                }
                                processName = Process.GetProcessById(_processId).ProcessName;
                            }
                            catch (Exception) { }
                            _renderer = new JSONExporter(output, processName);
                        }
                        else
                        {
                            _console.Error.WriteLine($"The output format {format} is not a valid output format.");
                            return(ReturnCode.ArgumentError);
                        }
                        _resumeRuntime = resumeRuntime;
                        int ret = await Start();

                        return(ret);
                    }
                    catch (OperationCanceledException)
                    {
                        try
                        {
                            _session.Stop();
                        }
                        catch (Exception) { } // session.Stop() can throw if target application already stopped before we send the stop command.
                        return(ReturnCode.Ok);
                    }
                }
            }
            catch (CommandLineErrorException e)
            {
                console.Error.WriteLine(e.Message);
                return(ReturnCode.ArgumentError);
            }
        }
예제 #4
0
        public async Task <int> Monitor(
            CancellationToken ct,
            List <string> counter_list,
            string counters,
            IConsole console,
            int processId,
            int refreshInterval,
            string name,
            string diagnosticPort,
            bool resumeRuntime,
            int maxHistograms,
            int maxTimeSeries)
        {
            try
            {
                // System.CommandLine does have an option to specify arguments as uint and it would validate they are non-negative. However the error
                // message is "Cannot parse argument '-1' for option '--maxTimeSeries' as expected type System.UInt32" which is not as user friendly.
                // If there was another option to leverage System.CommandLine that provides a little more user friendly error message we could switch
                // to it.
                ValidateNonNegative(maxHistograms, nameof(maxHistograms));
                ValidateNonNegative(maxTimeSeries, nameof(maxTimeSeries));
                if (!ProcessLauncher.Launcher.HasChildProc && !CommandUtils.ValidateArgumentsForAttach(processId, name, diagnosticPort, out _processId))
                {
                    return(ReturnCode.ArgumentError);
                }
                _ct.Register(() => _shouldExit.TrySetResult(ReturnCode.Ok));

                DiagnosticsClientBuilder builder = new DiagnosticsClientBuilder("dotnet-counters", 10);
                using (DiagnosticsClientHolder holder = await builder.Build(ct, _processId, diagnosticPort, showChildIO: false, printLaunchCommand: false))
                {
                    if (holder == null)
                    {
                        return(ReturnCode.Ok);
                    }
                    try
                    {
                        _console = console;
                        // the launch command may misinterpret app arguments as the old space separated
                        // provider list so we need to ignore it in that case
                        _counterList       = ConfigureCounters(counters, _processId != 0 ? counter_list : null);
                        _ct                = ct;
                        _interval          = refreshInterval;
                        _maxHistograms     = maxHistograms;
                        _maxTimeSeries     = maxTimeSeries;
                        _renderer          = new ConsoleWriter();
                        _diagnosticsClient = holder.Client;
                        _resumeRuntime     = resumeRuntime;
                        int ret = await Start();

                        ProcessLauncher.Launcher.Cleanup();
                        return(ret);
                    }
                    catch (OperationCanceledException)
                    {
                        try
                        {
                            _session.Stop();
                        }
                        catch (Exception) { } // Swallow all exceptions for now.

                        console.Out.WriteLine($"Complete");
                        return(ReturnCode.Ok);
                    }
                }
            }
            catch (CommandLineErrorException e)
            {
                console.Error.WriteLine(e.Message);
                return(ReturnCode.ArgumentError);
            }
        }