diff --git a/Duplicati/Library/Main/Options.cs b/Duplicati/Library/Main/Options.cs
index d28ac6161..4d3196733 100644
--- a/Duplicati/Library/Main/Options.cs
+++ b/Duplicati/Library/Main/Options.cs
@@ -1248,37 +1248,7 @@ namespace Duplicati.Library.Main
}
}
- ///
- /// Helper method to support filters with either a + or - prefix
- ///
- /// The IFilter instance.
- /// The filter string to parse.
- private static IFilter StringToIFilter(string msg)
- {
- if (string.IsNullOrWhiteSpace(msg))
- return new FilterExpression();
- if (msg[0] == '+')
- return new FilterExpression(msg.Substring(1), true);
- if (msg[0] == '-')
- return new FilterExpression(msg.Substring(1), false);
- return new FilterExpression(msg, true);
- }
- ///
- /// Parses a log filter string, and returns the filter instance
- ///
- /// The log filter.
- /// The filter string to parse.
- public static IFilter ParseLogFilter(string value)
- {
- if (string.IsNullOrWhiteSpace(value))
- return new FilterExpression();
-
- return value
- .Split(new char[] { System.IO.Path.PathSeparator, ':', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(StringToIFilter)
- .Aggregate(FilterExpression.Combine);
- }
///
/// Parses a log level string
@@ -1305,7 +1275,7 @@ namespace Duplicati.Library.Main
get
{
m_options.TryGetValue("log-file-log-filter", out var value);
- return ParseLogFilter(value);
+ return Library.Utility.FilterExpression.ParseLogFilter(value);
}
}
@@ -1318,7 +1288,7 @@ namespace Duplicati.Library.Main
get
{
m_options.TryGetValue("console-log-filter", out var value);
- return ParseLogFilter(value);
+ return Library.Utility.FilterExpression.ParseLogFilter(value);
}
}
diff --git a/Duplicati/Library/Modules/Builtin/SendMail.cs b/Duplicati/Library/Modules/Builtin/SendMail.cs
index bc5ca49da..efe831583 100644
--- a/Duplicati/Library/Modules/Builtin/SendMail.cs
+++ b/Duplicati/Library/Modules/Builtin/SendMail.cs
@@ -62,6 +62,14 @@ namespace Duplicati.Library.Modules.Builtin
/// Option used to specify if reports are sent for other operations than backups
///
private const string OPTION_SENDALL = "send-mail-any-operation";
+ ///
+ /// Option used to set the log level for mail reports
+ ///
+ private const string OPTION_LOG_LEVEL = "send-mail-log-level";
+ ///
+ /// Option used to set the log filters for mail reports
+ ///
+ private const string OPTION_LOG_FILTER = "send-mail-log-filter";
#endregion
@@ -142,6 +150,14 @@ namespace Duplicati.Library.Modules.Builtin
/// True to send all operations
///
private bool m_sendAll;
+ ///
+ /// The log scope that should be disposed
+ ///
+ private IDisposable m_logscope;
+ ///
+ /// The log storage
+ ///
+ private Utility.FileBackedStringList m_logstorage;
#endregion
@@ -187,6 +203,10 @@ namespace Duplicati.Library.Modules.Builtin
new CommandLineArgument(OPTION_PASSWORD, CommandLineArgument.ArgumentType.String, Strings.SendMail.OptionPasswordShort, Strings.SendMail.OptionPasswordLong),
new CommandLineArgument(OPTION_SENDLEVEL, CommandLineArgument.ArgumentType.String, Strings.SendMail.OptionSendlevelShort, Strings.SendMail.OptionSendlevelLong(ParsedResultType.Success.ToString(), ParsedResultType.Warning.ToString(), ParsedResultType.Error.ToString(), ParsedResultType.Fatal.ToString(), "All"), DEFAULT_LEVEL, null, Enum.GetNames(typeof(ParsedResultType)).Union(new string [] { "All" }).ToArray()),
new CommandLineArgument(OPTION_SENDALL, CommandLineArgument.ArgumentType.Boolean, Strings.SendMail.OptionSendallShort, Strings.SendMail.OptionSendallLong),
+
+ new CommandLineArgument(OPTION_LOG_LEVEL, CommandLineArgument.ArgumentType.Enumeration, Strings.SendMail.OptionLoglevellShort, Strings.SendMail.OptionLoglevelLong, Logging.LogMessageType.Warning.ToString(), null, Enum.GetNames(typeof(Logging.LogMessageType))),
+ new CommandLineArgument(OPTION_LOG_FILTER, CommandLineArgument.ArgumentType.String, Strings.SendMail.OptionLogfilterShort, Strings.SendMail.OptionLogfilterLong),
+
});
}
}
@@ -236,6 +256,21 @@ namespace Duplicati.Library.Modules.Builtin
m_body = DEFAULT_BODY;
if (string.IsNullOrEmpty(m_from))
m_from = DEFAULT_SENDER;
+
+ m_options.TryGetValue(OPTION_LOG_FILTER, out var logfilterstring);
+ var filter = Utility.FilterExpression.ParseLogFilter(logfilterstring);
+ var logLevel =
+
+ m_logstorage = new FileBackedStringList();
+ m_logscope = Logging.Log.StartScope(m => m_logstorage.Add(m.AsString(true)), m => {
+
+ if (filter.Matches(m.Tag, out var result, out var match))
+ return result;
+ else if (m.Level < loglevel)
+ return false;
+
+ return true;
+ });
}
#endregion
@@ -261,6 +296,14 @@ namespace Duplicati.Library.Modules.Builtin
/// The result object, if this derives from an exception, the operation failed
public void OnFinish(object result)
{
+ // Dispose the current log scope
+ if (m_logscope != null)
+ {
+ try { m_logscope.Dispose(); }
+ catch { }
+ m_logscope = null;
+ }
+
//If no email is supplied, then skip
if (string.IsNullOrEmpty(m_to))
return;
diff --git a/Duplicati/Library/Utility/FilterExpression.cs b/Duplicati/Library/Utility/FilterExpression.cs
index e03139b93..e16fd8a92 100644
--- a/Duplicati/Library/Utility/FilterExpression.cs
+++ b/Duplicati/Library/Utility/FilterExpression.cs
@@ -613,6 +613,38 @@ namespace Duplicati.Library.Utility
return res;
}
+
+ ///
+ /// Parses a log filter string, and returns the filter instance
+ ///
+ /// The log filter.
+ /// The filter string to parse.
+ public static IFilter ParseLogFilter(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ return new FilterExpression();
+
+ return value
+ .Split(new char[] { System.IO.Path.PathSeparator, ':', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(StringToIFilter)
+ .Aggregate(FilterExpression.Combine);
+ }
+
+ ///
+ /// Helper method to support filters with either a + or - prefix
+ ///
+ /// The IFilter instance.
+ /// The filter string to parse.
+ public static IFilter StringToIFilter(string msg)
+ {
+ if (string.IsNullOrWhiteSpace(msg))
+ return new FilterExpression();
+ if (msg[0] == '+')
+ return new FilterExpression(msg.Substring(1), true);
+ if (msg[0] == '-')
+ return new FilterExpression(msg.Substring(1), false);
+ return new FilterExpression(msg, true);
+ }
}
}
diff --git a/Duplicati/Library/Utility/Utility.cs b/Duplicati/Library/Utility/Utility.cs
index 8e840d0aa..28c42f3c2 100644
--- a/Duplicati/Library/Utility/Utility.cs
+++ b/Duplicati/Library/Utility/Utility.cs
@@ -687,7 +687,15 @@ namespace Duplicati.Library.Utility
return ParseBool(opt, true);
else
return false;
+ }
+ public static T ParseEnum(string value, T @default)
+ {
+ foreach (string s in Enum.GetNames(typeof(T)))
+ if (s.Equals(value, StringComparison.OrdinalIgnoreCase))
+ return (T)Enum.Parse(typeof(T), s);
+
+ return @default;
}
///