275 lines
8.1 KiB
C#
275 lines
8.1 KiB
C#
#define TRACE
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
|
|
namespace FluentFTP {
|
|
/// <summary>
|
|
/// Used for transaction logging and debug information.
|
|
/// </summary>
|
|
public static class FtpTrace {
|
|
|
|
#if !CORE
|
|
private static volatile TraceSource m_traceSource = new TraceSource("FluentFTP") {
|
|
Switch = new SourceSwitch("sourceSwitch", "Verbose") { Level = SourceLevels.All }
|
|
};
|
|
|
|
static bool m_flushOnWrite = true;
|
|
|
|
|
|
/// <summary>
|
|
/// Should the trace listeners be flushed immediately after writing to them?
|
|
/// </summary>
|
|
public static bool FlushOnWrite {
|
|
get { return m_flushOnWrite; }
|
|
set { m_flushOnWrite = value; }
|
|
}
|
|
|
|
static bool m_prefix = false;
|
|
|
|
/// <summary>
|
|
/// Should the log entries be written with a prefix of "FluentFTP"?
|
|
/// Useful if you have a single TraceListener shared across multiple libraries.
|
|
/// </summary>
|
|
public static bool LogPrefix {
|
|
get { return m_prefix; }
|
|
set { m_prefix = value; }
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Add a TraceListner to the collection. You can use one of the predefined
|
|
/// TraceListeners in the System.Diagnostics namespace, such as ConsoleTraceListener
|
|
/// for logging to the console, or you can write your own deriving from
|
|
/// System.Diagnostics.TraceListener.
|
|
/// </summary>
|
|
/// <param name="listener">The TraceListener to add to the collection</param>
|
|
public static void AddListener(TraceListener listener) {
|
|
lock (m_traceSource) {
|
|
m_traceSource.Listeners.Add(listener);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove the specified TraceListener from the collection
|
|
/// </summary>
|
|
/// <param name="listener">The TraceListener to remove from the collection.</param>
|
|
public static void RemoveListener(TraceListener listener) {
|
|
lock (m_traceSource) {
|
|
m_traceSource.Listeners.Remove(listener);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#if CORE
|
|
|
|
static bool m_LogToConsole = false;
|
|
|
|
/// <summary>
|
|
/// Should FTP communication be be logged to console?
|
|
/// </summary>
|
|
public static bool LogToConsole {
|
|
get { return m_LogToConsole; }
|
|
set { m_LogToConsole = value; }
|
|
}
|
|
|
|
static string m_LogToFile = null;
|
|
|
|
/// <summary>
|
|
/// Set this to a file path to append all FTP communication to it.
|
|
/// </summary>
|
|
public static string LogToFile {
|
|
get { return m_LogToFile; }
|
|
set { m_LogToFile = value; }
|
|
}
|
|
|
|
#endif
|
|
static bool m_functions = true;
|
|
|
|
/// <summary>
|
|
/// Should the function calls be logged in Verbose mode?
|
|
/// </summary>
|
|
public static bool LogFunctions {
|
|
get { return m_functions; }
|
|
set { m_functions = value; }
|
|
}
|
|
|
|
static bool m_IP = true;
|
|
|
|
/// <summary>
|
|
/// Should the FTP server IP addresses be included in the logs?
|
|
/// </summary>
|
|
public static bool LogIP {
|
|
get { return m_IP; }
|
|
set { m_IP = value; }
|
|
}
|
|
|
|
static bool m_username = true;
|
|
|
|
/// <summary>
|
|
/// Should the FTP usernames be included in the logs?
|
|
/// </summary>
|
|
public static bool LogUserName {
|
|
get { return m_username; }
|
|
set { m_username = value; }
|
|
}
|
|
|
|
static bool m_password = false;
|
|
|
|
/// <summary>
|
|
/// Should the FTP passwords be included in the logs?
|
|
/// </summary>
|
|
public static bool LogPassword {
|
|
get { return m_password; }
|
|
set { m_password = value; }
|
|
}
|
|
|
|
static bool m_tracing = true;
|
|
|
|
/// <summary>
|
|
/// Should we trace at all?
|
|
/// </summary>
|
|
public static bool EnableTracing
|
|
{
|
|
get { return m_tracing; }
|
|
set { m_tracing = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write to the TraceListeners
|
|
/// </summary>
|
|
/// <param name="message">The message to write</param>
|
|
//[Obsolete("Use overloads with FtpTraceLevel")]
|
|
public static void Write(string message) {
|
|
Write(FtpTraceLevel.Verbose, message);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write to the TraceListeners
|
|
/// </summary>
|
|
/// <param name="message">The message to write</param>
|
|
//[Obsolete("Use overloads with FtpTraceLevel")]
|
|
public static void WriteLine(object message) {
|
|
Write(FtpTraceLevel.Verbose, message.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write to the TraceListeners
|
|
/// </summary>
|
|
/// <param name="eventType">The type of tracing event</param>
|
|
/// <param name="message">The message to write</param>
|
|
public static void WriteLine(FtpTraceLevel eventType, object message) {
|
|
Write(eventType, message.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write to the TraceListeners, adding an automatic prefix to the message based on the `eventType`
|
|
/// </summary>
|
|
/// <param name="eventType">The type of tracing event</param>
|
|
/// <param name="message">The message to write</param>
|
|
public static void WriteStatus(FtpTraceLevel eventType, object message) {
|
|
Write(eventType, TraceLevelPrefix(eventType) + message.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write to the TraceListeners, for the purpose of logging a API function call
|
|
/// </summary>
|
|
/// <param name="function">The name of the API function</param>
|
|
/// <param name="args">The args passed to the function</param>
|
|
public static void WriteFunc(string function, object[] args = null) {
|
|
if (m_functions) {
|
|
Write(FtpTraceLevel.Verbose, "");
|
|
Write(FtpTraceLevel.Verbose, "# " + function + "(" + args.ItemsToString().Join(", ") + ")");
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Write to the TraceListeners
|
|
/// </summary>
|
|
/// <param name="eventType">The type of tracing event</param>
|
|
/// <param name="message">A formattable string to write</param>
|
|
public static void Write(FtpTraceLevel eventType, string message) {
|
|
if(!EnableTracing)
|
|
return;
|
|
#if CORE
|
|
#if DEBUG
|
|
Debug.WriteLine(message);
|
|
#else
|
|
if (m_LogToConsole) {
|
|
Console.WriteLine(message);
|
|
}
|
|
if (m_LogToFile != null) {
|
|
File.AppendAllText(m_LogToFile, message + "\n");
|
|
}
|
|
#endif
|
|
#elif !CORE
|
|
|
|
if (m_prefix) {
|
|
|
|
// if prefix is wanted then use TraceEvent()
|
|
m_traceSource.TraceEvent(TraceLevelTranslation(eventType), 0, message);
|
|
|
|
} else {
|
|
|
|
// if prefix is NOT wanted then write manually
|
|
EmitEvent(m_traceSource, TraceLevelTranslation(eventType), message);
|
|
|
|
}
|
|
if (m_flushOnWrite) {
|
|
m_traceSource.Flush();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
private static string TraceLevelPrefix(FtpTraceLevel level) {
|
|
switch (level) {
|
|
case FtpTraceLevel.Verbose:
|
|
return "Status: ";
|
|
case FtpTraceLevel.Info:
|
|
return "Status: ";
|
|
case FtpTraceLevel.Warn:
|
|
return "Warning: ";
|
|
case FtpTraceLevel.Error:
|
|
return "Error: ";
|
|
}
|
|
return "Status: ";
|
|
}
|
|
|
|
#if !CORE
|
|
|
|
private static TraceEventType TraceLevelTranslation(FtpTraceLevel level) {
|
|
switch (level) {
|
|
case FtpTraceLevel.Verbose:
|
|
return TraceEventType.Verbose;
|
|
case FtpTraceLevel.Info:
|
|
return TraceEventType.Information;
|
|
case FtpTraceLevel.Warn:
|
|
return TraceEventType.Warning;
|
|
case FtpTraceLevel.Error:
|
|
return TraceEventType.Error;
|
|
default:
|
|
return TraceEventType.Verbose;
|
|
}
|
|
}
|
|
|
|
static object traceSync = new object();
|
|
private static void EmitEvent(TraceSource traceSource, TraceEventType eventType, string message) {
|
|
try {
|
|
lock (traceSync) {
|
|
if (traceSource.Switch.ShouldTrace(eventType)) {
|
|
foreach (TraceListener listener in traceSource.Listeners) {
|
|
try {
|
|
listener.WriteLine(message);
|
|
listener.Flush();
|
|
} catch { }
|
|
}
|
|
}
|
|
}
|
|
} catch {
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
} |