1 //
2 // Copyright (c) 2010-2024 Antmicro
3 // Copyright (c) 2011-2015 Realtime Embedded
4 //
5 // This file is licensed under the MIT License.
6 // Full license text is available in 'licenses/MIT.txt'.
7 //
8 using Antmicro.Renode.UserInterface.Tokenizer;
9 using AntShell.Commands;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Core;
12 using Antmicro.Renode.Peripherals;
13 using System.Linq;
14 using System.Collections.Generic;
15 
16 namespace Antmicro.Renode.UserInterface.Commands
17 {
18     public class LogLevelCommand : AutoLoadCommand
19     {
PrintHelp(ICommandInteraction writer)20         public override void PrintHelp(ICommandInteraction writer)
21         {
22             base.PrintHelp(writer);
23             writer.WriteLine();
24             writer.WriteLine("Usages:");
25             writer.WriteLine(" logLevel");
26             writer.WriteLine(" logLevel [LEVEL]");
27             writer.WriteLine(" logLevel [LEVEL] [OBJECT]");
28             writer.WriteLine(" logLevel [LEVEL] [BACKEND]");
29             writer.WriteLine(" logLevel [LEVEL] [BACKEND] [OBJECT]");
30             writer.WriteLine();
31             writer.WriteLine("To see currently available backends execute command: logLevel");
32             writer.WriteLine();
33             PrintAvailableLevels(writer);
34         }
35 
36         [Runnable]
Run(ICommandInteraction writer)37         public void Run(ICommandInteraction writer)
38         {
39             PrintCurrentLevels(writer);
40         }
41 
42         [Runnable]
Run([Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level)43         public void Run([Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level)
44         {
45             TrySetLogLevel((LogLevel)level.Value);
46         }
47 
48         [Runnable]
Run([Values(R, R, R, R, R)] StringToken level)49         public void Run([Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level)
50         {
51             TrySetLogLevel(LogLevel.Parse(level.Value));
52         }
53 
54         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken emulationElementOrBackendName)55         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken emulationElementOrBackendName)
56         {
57             RunInner(writer, (LogLevel)level.Value, emulationElementOrBackendName.Value);
58         }
59 
60         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, StringToken emulationElementOrBackendName)61         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, StringToken emulationElementOrBackendName)
62         {
63             RunInner(writer, (LogLevel)level.Value, emulationElementOrBackendName.Value);
64         }
65 
66         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken emulationElementOrBackendName, BooleanToken recursive)67         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken emulationElementOrBackendName, BooleanToken recursive)
68         {
69             RunInner(writer, (LogLevel)level.Value, emulationElementOrBackendName.Value, recursive.Value);
70         }
71 
72         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, StringToken emulationElementOrBackendName, BooleanToken recursive)73         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, StringToken emulationElementOrBackendName, BooleanToken recursive)
74         {
75             RunInner(writer, (LogLevel)level.Value, emulationElementOrBackendName.Value, recursive.Value);
76         }
77 
78         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, LiteralToken emulationElementOrBackendName)79         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, LiteralToken emulationElementOrBackendName)
80         {
81             RunInner(writer, LogLevel.Parse(level.Value), emulationElementOrBackendName.Value);
82         }
83 
84         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, StringToken emulationElementOrBackendName)85         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, StringToken emulationElementOrBackendName)
86         {
87             RunInner(writer, LogLevel.Parse(level.Value), emulationElementOrBackendName.Value);
88         }
89 
90         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, LiteralToken emulationElementOrBackendName, BooleanToken recursive)91         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, LiteralToken emulationElementOrBackendName, BooleanToken recursive)
92         {
93             RunInner(writer, LogLevel.Parse(level.Value), emulationElementOrBackendName.Value, recursive.Value);
94         }
95 
96         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, StringToken emulationElementOrBackendName, BooleanToken recursive)97         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, StringToken emulationElementOrBackendName, BooleanToken recursive)
98         {
99             RunInner(writer, LogLevel.Parse(level.Value), emulationElementOrBackendName.Value, recursive.Value);
100         }
101 
102         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, LiteralToken emulationElementName)103         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, LiteralToken emulationElementName)
104         {
105             RunInner(writer, (LogLevel)level.Value, backendName.Value, emulationElementName.Value);
106         }
107 
108         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, StringToken emulationElementName)109         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, StringToken emulationElementName)
110         {
111             RunInner(writer, (LogLevel)level.Value, backendName.Value, emulationElementName.Value);
112         }
113 
114         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, LiteralToken emulationElementName, BooleanToken recursive)115         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, LiteralToken emulationElementName, BooleanToken recursive)
116         {
117             RunInner(writer, (LogLevel)level.Value, backendName.Value, emulationElementName.Value, recursive.Value);
118         }
119 
120         [Runnable]
Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, StringToken emulationElementName, BooleanToken recursive)121         public void Run(ICommandInteraction writer, [Values(-1L, 0L, 1L, 2L, 3L)] DecimalIntegerToken level, LiteralToken backendName, StringToken emulationElementName, BooleanToken recursive)
122         {
123             RunInner(writer, (LogLevel)level.Value, backendName.Value, emulationElementName.Value, recursive.Value);
124         }
125 
126         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, LiteralToken backendName, LiteralToken emulationElementName)127         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, LiteralToken backendName, LiteralToken emulationElementName)
128         {
129             RunInner(writer, LogLevel.Parse(level.Value), backendName.Value, emulationElementName.Value);
130         }
131 
132         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, LiteralToken backendName, StringToken emulationElementName)133         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, LiteralToken backendName, StringToken emulationElementName)
134         {
135             RunInner(writer, LogLevel.Parse(level.Value), backendName.Value, emulationElementName.Value);
136         }
137 
138         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, LiteralToken backendName, LiteralToken emulationElementName, BooleanToken recursive)139         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, LiteralToken backendName, LiteralToken emulationElementName, BooleanToken recursive)
140         {
141             RunInner(writer, LogLevel.Parse(level.Value), backendName.Value, emulationElementName.Value, recursive.Value);
142         }
143 
144         [Runnable]
Run(ICommandInteraction writer, [Values(R, R, R, R, R)] StringToken level, LiteralToken backendName, StringToken emulationElementName, BooleanToken recursive)145         public void Run(ICommandInteraction writer, [Values("Noisy", "Debug", "Info", "Warning", "Error")] StringToken level, LiteralToken backendName, StringToken emulationElementName, BooleanToken recursive)
146         {
147             RunInner(writer, LogLevel.Parse(level.Value), backendName.Value, emulationElementName.Value, recursive.Value);
148         }
149 
RunInner(ICommandInteraction writer, LogLevel level, string emulationElementOrBackendName, bool recursive = true)150         private void RunInner(ICommandInteraction writer, LogLevel level, string emulationElementOrBackendName, bool recursive = true)
151         {
152             if(!TrySetLogLevel(level, null, emulationElementOrBackendName, recursive)
153                 && !TrySetLogLevel(level, emulationElementOrBackendName, null))
154             {
155                 writer.WriteError(string.Format("Could not find emulation element or backend named: {0}", emulationElementOrBackendName));
156             }
157         }
158 
RunInner(ICommandInteraction writer, LogLevel level, string backendName, string emulationElementName, bool recursive = true)159         private void RunInner(ICommandInteraction writer, LogLevel level, string backendName, string emulationElementName, bool recursive = true)
160         {
161             if(!TrySetLogLevel(level, backendName, emulationElementName, recursive))
162             {
163                 writer.WriteError(string.Format("Could not find emulation element or backend"));
164             }
165         }
166 
TrySetLogLevel(LogLevel level, string backendName = null, string emulationElementName = null, bool recursive = true)167         private bool TrySetLogLevel(LogLevel level, string backendName = null, string emulationElementName = null, bool recursive = true)
168         {
169             IEnumerable<IEmulationElement> emulationElements = null;
170             var emulation = EmulationManager.Instance.CurrentEmulation;
171 
172             if(emulationElementName != null)
173             {
174                 if(!emulation.TryGetEmulationElementByName(emulationElementName, monitor.Machine, out var emulationElement))
175                 {
176                     return false;
177                 }
178 
179                 emulationElements = ((emulationElement is IMachine) && recursive)
180                     ? (emulationElement as Machine).GetRegisteredPeripherals().Select(x => x.Peripheral).Cast<IEmulationElement>()
181                     : new[] { emulationElement };
182             }
183 
184             var emulationElementsIds = (emulationElements == null)
185                 ? new[] { -1 }
186                 : emulationElements.Select(x => emulation.CurrentLogger.GetOrCreateSourceId(x)).ToArray();
187 
188             bool somethingWasSet = false;
189             foreach(var b in Logger.GetBackends()
190                 .Where(x => x.Value.IsControllable)
191                 .Where(x => (backendName == null || x.Key == backendName)))
192             {
193                 foreach(var emulationElementId in emulationElementsIds)
194                 {
195                     b.Value.SetLogLevel(level, emulationElementId);
196                     somethingWasSet = true;
197                 }
198             }
199 
200             return somethingWasSet;
201         }
202 
PrintAvailableLevels(ICommandInteraction writer)203         private void PrintAvailableLevels(ICommandInteraction writer)
204         {
205             writer.WriteLine("Available levels:\n");
206             writer.WriteLine(string.Format("{0,-18}| {1}", "Level", "Name"));
207             writer.WriteLine("=======================================");
208             foreach(var item in LogLevel.AvailableLevels)
209             {
210                 writer.WriteLine(string.Format("{0,-18}: {1}", item.NumericLevel, item));
211             }
212             writer.WriteLine();
213         }
214 
PrintCurrentLevels(ICommandInteraction writer)215         private void PrintCurrentLevels(ICommandInteraction writer)
216         {
217             string objectName;
218             string machineName;
219 
220             writer.WriteLine("Currently set levels:\n");
221             writer.WriteLine(string.Format("{0,-18}| {1,-36}| {2}", "Backend", "Emulation element", "Level"));
222             writer.WriteLine("=================================================================");
223             foreach(var backend in Logger.GetBackends().Where(b => b.Value.IsControllable))
224             {
225                 writer.WriteLine(string.Format("{0,-18}: {1,-36}: {2}", backend.Key, string.Empty, backend.Value.GetLogLevel()));
226                 foreach (var custom in backend.Value.GetCustomLogLevels())
227                 {
228                     EmulationManager.Instance.CurrentEmulation.CurrentLogger.TryGetName(custom.Key, out objectName, out machineName);
229                     writer.WriteLine(string.Format("{0,-18}: {1,-36}: {2}", string.Empty, string.Format("{0}:{1}", machineName, objectName), custom.Value));
230                 }
231                 writer.WriteLine("-----------------------------------------------------------------");
232             }
233         }
234 
LogLevelCommand(Monitor monitor)235         public LogLevelCommand(Monitor monitor) : base(monitor, "logLevel", "sets logging level for backends.")
236         {
237         }
238     }
239 }
240 
241