Browse Source

Added CommandService logging

tags/1.0-rc
RogueException 8 years ago
parent
commit
a2b12520b2
6 changed files with 76 additions and 11 deletions
  1. +15
    -0
      src/Discord.Net.Commands/CommandException.cs
  2. +13
    -4
      src/Discord.Net.Commands/CommandService.cs
  3. +3
    -0
      src/Discord.Net.Commands/CommandServiceConfig.cs
  4. +43
    -3
      src/Discord.Net.Commands/Info/CommandInfo.cs
  5. +1
    -3
      src/Discord.Net.Commands/Info/ParameterInfo.cs
  6. +1
    -1
      src/Discord.Net.Core/DiscordConfig.cs

+ 15
- 0
src/Discord.Net.Commands/CommandException.cs View File

@@ -0,0 +1,15 @@
using System;

namespace Discord.Commands
{
public class CommandException : Exception
{
public CommandInfo Command { get; }
public ICommandContext Content { get; }

public CommandException(CommandInfo command, ICommandContext context, Exception ex)
: base($"Error occurred executing {command.GetLogText(context)}.", ex)
{
}
}
}

+ 13
- 4
src/Discord.Net.Commands/CommandService.cs View File

@@ -1,4 +1,6 @@
using System;
using Discord.Commands.Builders;
using Discord.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
@@ -7,12 +9,13 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using Discord.Commands.Builders;

namespace Discord.Commands
{
public class CommandService
{
public event Func<LogMessage, Task> Log { add { _logEvent.Add(value); } remove { _logEvent.Remove(value); } }
internal readonly AsyncEvent<Func<LogMessage, Task>> _logEvent = new AsyncEvent<Func<LogMessage, Task>>();

private readonly SemaphoreSlim _moduleLock;
private readonly ConcurrentDictionary<Type, ModuleInfo> _typedModuleDefs;
private readonly ConcurrentDictionary<Type, ConcurrentDictionary<Type, TypeReader>> _typeReaders;
@@ -24,6 +27,8 @@ namespace Discord.Commands
internal readonly bool _caseSensitive;
internal readonly char _separatorChar;
internal readonly RunMode _defaultRunMode;
internal readonly Logger _cmdLogger;
internal readonly LogManager _logManager;

public IEnumerable<ModuleInfo> Modules => _moduleDefs.Select(x => x);
public IEnumerable<CommandInfo> Commands => _moduleDefs.SelectMany(x => x.Commands);
@@ -36,7 +41,11 @@ namespace Discord.Commands
_separatorChar = config.SeparatorChar;
_defaultRunMode = config.DefaultRunMode;
if (_defaultRunMode == RunMode.Default)
throw new InvalidOperationException("The default run mode cannot be set to Default, it must be one of Sync, Mixed, or Async");
throw new InvalidOperationException("The default run mode cannot be set to Default.");

_logManager = new LogManager(config.LogLevel);
_logManager.Message += async msg => await _logEvent.InvokeAsync(msg).ConfigureAwait(false);
_cmdLogger = _logManager.CreateLogger("Command");

_moduleLock = new SemaphoreSlim(1, 1);
_typedModuleDefs = new ConcurrentDictionary<Type, ModuleInfo>();


+ 3
- 0
src/Discord.Net.Commands/CommandServiceConfig.cs View File

@@ -8,5 +8,8 @@
public char SeparatorChar { get; set; } = ' ';
/// <summary> Should commands be case-sensitive? </summary>
public bool CaseSensitiveCommands { get; set; } = false;

/// <summary> Gets or sets the minimum log level severity that will be sent to the Log event. </summary>
public LogSeverity LogLevel { get; set; } = LogSeverity.Info;
}
}

+ 43
- 3
src/Discord.Net.Commands/Info/CommandInfo.cs View File

@@ -137,16 +137,48 @@ namespace Discord.Commands
return ExecuteResult.FromError(result);
}

await Module.Service._cmdLogger.DebugAsync($"Executing {GetLogText(context)}").ConfigureAwait(false);
switch (RunMode)
{
case RunMode.Sync: //Always sync
await _action(context, args, map).ConfigureAwait(false);
try
{
await _action(context, args, map).ConfigureAwait(false);
}
catch (Exception ex)
{
ex = new CommandException(this, context, ex);
await Module.Service._cmdLogger.ErrorAsync(ex).ConfigureAwait(false);
throw;
}
await Module.Service._cmdLogger.VerboseAsync($"Executed {GetLogText(context)}").ConfigureAwait(false);
break;
case RunMode.Mixed: //Sync until first await statement
var t1 = _action(context, args, map);
var t1 = _action(context, args, map).ContinueWith(async t =>
{
if (t.IsFaulted)
{
var ex = new CommandException(this, context, t.Exception);
await Module.Service._cmdLogger.ErrorAsync(ex).ConfigureAwait(false);
}
else
await Module.Service._cmdLogger.VerboseAsync($"Executed {GetLogText(context)}").ConfigureAwait(false);
});
break;
case RunMode.Async: //Always async
var t2 = Task.Run(() => _action(context, args, map));
var t2 = Task.Run(() =>
{
var _ = _action(context, args, map).ContinueWith(async t =>
{
if (t.IsFaulted)
{
var ex = new CommandException(this, context, t.Exception);
await Module.Service._cmdLogger.ErrorAsync(ex).ConfigureAwait(false);
}
else
await Module.Service._cmdLogger.VerboseAsync($"Executed {GetLogText(context)}").ConfigureAwait(false);
});
});
break;
}
return ExecuteResult.FromSuccess();
@@ -189,5 +221,13 @@ namespace Discord.Commands

private static T[] ConvertParamsList<T>(IEnumerable<object> paramsList)
=> paramsList.Cast<T>().ToArray();

internal string GetLogText(ICommandContext context)
{
if (context.Guild != null)
return $"\"{Name}\" for {context.User} in {context.Guild}/{context.Channel}";
else
return $"\"{Name}\" for {context.User} in {context.Channel}";
}
}
}

+ 1
- 3
src/Discord.Net.Commands/Info/ParameterInfo.cs View File

@@ -1,11 +1,9 @@
using Discord.Commands.Builders;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;

using Discord.Commands.Builders;
using System.Reflection;

namespace Discord.Commands
{
public class ParameterInfo


+ 1
- 1
src/Discord.Net.Core/DiscordConfig.cs View File

@@ -22,7 +22,7 @@ namespace Discord
/// <summary> Gets or sets how a request should act in the case of an error, by default. </summary>
public RetryMode DefaultRetryMode { get; set; } = RetryMode.AlwaysRetry;
/// <summary> Gets or sets the minimum log level severity that will be sent to the LogMessage event. </summary>
/// <summary> Gets or sets the minimum log level severity that will be sent to the Log event. </summary>
public LogSeverity LogLevel { get; set; } = LogSeverity.Info;

/// <summary> Gets or sets whether the initial log entry should be printed. </summary>


Loading…
Cancel
Save