Adds SQL logging from WhiteX's fork; closes #869

This commit is contained in:
Lucas Nicodemus 2015-02-25 14:52:28 -07:00
parent c215ff8e10
commit 0459dfca11
10 changed files with 743 additions and 144 deletions

View file

@ -67,7 +67,7 @@ namespace TShockAPI
SaveManager.Instance.SaveWorld(); SaveManager.Instance.SaveWorld();
Console.WriteLine("World backed up."); Console.WriteLine("World backed up.");
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Log.Info(string.Format("World backed up ({0}).", Main.worldPathName)); TShock.Log.Info(string.Format("World backed up ({0}).", Main.worldPathName));
Main.worldPathName = worldname; Main.worldPathName = worldname;
} }
@ -76,8 +76,8 @@ namespace TShockAPI
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Backup failed!"); Console.WriteLine("Backup failed!");
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
Log.Error("Backup failed!"); TShock.Log.Error("Backup failed!");
Log.Error(ex.ToString()); TShock.Log.Error(ex.ToString());
} }
} }

View file

@ -151,7 +151,7 @@ namespace TShockAPI
catch (Exception e) catch (Exception e)
{ {
ply.SendErrorMessage("Command failed, check logs for more details."); ply.SendErrorMessage("Command failed, check logs for more details.");
Log.Error(e.ToString()); TShock.Log.Error(e.ToString());
} }
return true; return true;
@ -711,7 +711,7 @@ namespace TShockAPI
{ {
if (args.Player.LoginAttempts > TShock.Config.MaximumLoginAttempts && (TShock.Config.MaximumLoginAttempts != -1)) if (args.Player.LoginAttempts > TShock.Config.MaximumLoginAttempts && (TShock.Config.MaximumLoginAttempts != -1))
{ {
Log.Warn(String.Format("{0} ({1}) had {2} or more invalid login attempts and was kicked automatically.", TShock.Log.Warn(String.Format("{0} ({1}) had {2} or more invalid login attempts and was kicked automatically.",
args.Player.IP, args.Player.Name, TShock.Config.MaximumLoginAttempts)); args.Player.IP, args.Player.Name, TShock.Config.MaximumLoginAttempts));
TShock.Utils.Kick(args.Player, "Too many invalid login attempts."); TShock.Utils.Kick(args.Player, "Too many invalid login attempts.");
return; return;
@ -799,7 +799,7 @@ namespace TShockAPI
} }
args.Player.SendSuccessMessage("Authenticated as " + user.Name + " successfully."); args.Player.SendSuccessMessage("Authenticated as " + user.Name + " successfully.");
Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user: " + user.Name + "."); TShock.Log.ConsoleInfo(args.Player.Name + " authenticated successfully as user: " + user.Name + ".");
if ((args.Player.LoginHarassed) && (TShock.Config.RememberLeavePos)) if ((args.Player.LoginHarassed) && (TShock.Config.RememberLeavePos))
{ {
if (TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP) != Vector2.Zero) if (TShock.RememberedPos.GetLeavePos(args.Player.Name, args.Player.IP) != Vector2.Zero)
@ -824,14 +824,14 @@ namespace TShockAPI
{ {
args.Player.SendErrorMessage("Invalid password!"); args.Player.SendErrorMessage("Invalid password!");
} }
Log.Warn(args.Player.IP + " failed to authenticate as user: " + user.Name + "."); TShock.Log.Warn(args.Player.IP + " failed to authenticate as user: " + user.Name + ".");
args.Player.LoginAttempts++; args.Player.LoginAttempts++;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
args.Player.SendErrorMessage("There was an error processing your request."); args.Player.SendErrorMessage("There was an error processing your request.");
Log.Error(ex.ToString()); TShock.Log.Error(ex.ToString());
} }
} }
@ -847,12 +847,12 @@ namespace TShockAPI
{ {
args.Player.SendSuccessMessage("You changed your password!"); args.Player.SendSuccessMessage("You changed your password!");
TShock.Users.SetUserPassword(user, args.Parameters[1]); // SetUserPassword will hash it for you. TShock.Users.SetUserPassword(user, args.Parameters[1]); // SetUserPassword will hash it for you.
Log.ConsoleInfo(args.Player.IP + " named " + args.Player.Name + " changed the password of account " + user.Name + "."); TShock.Log.ConsoleInfo(args.Player.IP + " named " + args.Player.Name + " changed the password of account " + user.Name + ".");
} }
else else
{ {
args.Player.SendErrorMessage("You failed to change your password!"); args.Player.SendErrorMessage("You failed to change your password!");
Log.ConsoleError(args.Player.IP + " named " + args.Player.Name + " failed to change password for account: " + TShock.Log.ConsoleError(args.Player.IP + " named " + args.Player.Name + " failed to change password for account: " +
user.Name + "."); user.Name + ".");
} }
} }
@ -864,7 +864,7 @@ namespace TShockAPI
catch (UserManagerException ex) catch (UserManagerException ex)
{ {
args.Player.SendErrorMessage("Sorry, an error occured: " + ex.Message + "."); args.Player.SendErrorMessage("Sorry, an error occured: " + ex.Message + ".");
Log.ConsoleError("PasswordUser returned an error: " + ex); TShock.Log.ConsoleError("PasswordUser returned an error: " + ex);
} }
} }
@ -898,18 +898,18 @@ namespace TShockAPI
args.Player.SendSuccessMessage("Account \"{0}\" has been registered.", user.Name); args.Player.SendSuccessMessage("Account \"{0}\" has been registered.", user.Name);
args.Player.SendSuccessMessage("Your password is {0}.", user.Password); args.Player.SendSuccessMessage("Your password is {0}.", user.Password);
TShock.Users.AddUser(user); TShock.Users.AddUser(user);
Log.ConsoleInfo("{0} registered an account: \"{1}\".", args.Player.Name, user.Name); TShock.Log.ConsoleInfo("{0} registered an account: \"{1}\".", args.Player.Name, user.Name);
} }
else else
{ {
args.Player.SendErrorMessage("Account " + user.Name + " has already been registered."); args.Player.SendErrorMessage("Account " + user.Name + " has already been registered.");
Log.ConsoleInfo(args.Player.Name + " failed to register an existing account: " + user.Name); TShock.Log.ConsoleInfo(args.Player.Name + " failed to register an existing account: " + user.Name);
} }
} }
catch (UserManagerException ex) catch (UserManagerException ex)
{ {
args.Player.SendErrorMessage("Sorry, an error occured: " + ex.Message + "."); args.Player.SendErrorMessage("Sorry, an error occured: " + ex.Message + ".");
Log.ConsoleError("RegisterUser returned an error: " + ex); TShock.Log.ConsoleError("RegisterUser returned an error: " + ex);
} }
} }
@ -939,7 +939,7 @@ namespace TShockAPI
{ {
TShock.Users.AddUser(user); TShock.Users.AddUser(user);
args.Player.SendSuccessMessage("Account " + user.Name + " has been added to group " + user.Group + "!"); args.Player.SendSuccessMessage("Account " + user.Name + " has been added to group " + user.Group + "!");
Log.ConsoleInfo(args.Player.Name + " added Account " + user.Name + " to group " + user.Group); TShock.Log.ConsoleInfo(args.Player.Name + " added Account " + user.Name + " to group " + user.Group);
} }
catch (GroupNotExistsException e) catch (GroupNotExistsException e)
{ {
@ -952,7 +952,7 @@ namespace TShockAPI
catch (UserManagerException e) catch (UserManagerException e)
{ {
args.Player.SendErrorMessage("User " + user.Name + " could not be added, check console for details."); args.Player.SendErrorMessage("User " + user.Name + " could not be added, check console for details.");
Log.ConsoleError(e.ToString()); TShock.Log.ConsoleError(e.ToString());
} }
} }
else else
@ -970,7 +970,7 @@ namespace TShockAPI
{ {
TShock.Users.RemoveUser(user); TShock.Users.RemoveUser(user);
args.Player.SendSuccessMessage("Account removed successfully."); args.Player.SendSuccessMessage("Account removed successfully.");
Log.ConsoleInfo(args.Player.Name + " successfully deleted account: " + args.Parameters[1] + "."); TShock.Log.ConsoleInfo(args.Player.Name + " successfully deleted account: " + args.Parameters[1] + ".");
} }
catch (UserNotExistException e) catch (UserNotExistException e)
{ {
@ -979,7 +979,7 @@ namespace TShockAPI
catch (UserManagerException ex) catch (UserManagerException ex)
{ {
args.Player.SendMessage(ex.Message, Color.Red); args.Player.SendMessage(ex.Message, Color.Red);
Log.ConsoleError(ex.ToString()); TShock.Log.ConsoleError(ex.ToString());
} }
} }
@ -994,7 +994,7 @@ namespace TShockAPI
try try
{ {
TShock.Users.SetUserPassword(user, args.Parameters[2]); TShock.Users.SetUserPassword(user, args.Parameters[2]);
Log.ConsoleInfo(args.Player.Name + " changed the password of account " + user.Name); TShock.Log.ConsoleInfo(args.Player.Name + " changed the password of account " + user.Name);
args.Player.SendSuccessMessage("Password change succeeded for " + user.Name + "."); args.Player.SendSuccessMessage("Password change succeeded for " + user.Name + ".");
} }
catch (UserNotExistException e) catch (UserNotExistException e)
@ -1004,7 +1004,7 @@ namespace TShockAPI
catch (UserManagerException e) catch (UserManagerException e)
{ {
args.Player.SendErrorMessage("Password change for " + user.Name + " failed! Check console!"); args.Player.SendErrorMessage("Password change for " + user.Name + " failed! Check console!");
Log.ConsoleError(e.ToString()); TShock.Log.ConsoleError(e.ToString());
} }
} }
else else
@ -1023,7 +1023,7 @@ namespace TShockAPI
try try
{ {
TShock.Users.SetUserGroup(user, args.Parameters[2]); TShock.Users.SetUserGroup(user, args.Parameters[2]);
Log.ConsoleInfo(args.Player.Name + " changed account " + user.Name + " to group " + args.Parameters[2] + "."); TShock.Log.ConsoleInfo(args.Player.Name + " changed account " + user.Name + " to group " + args.Parameters[2] + ".");
args.Player.SendSuccessMessage("Account " + user.Name + " has been changed to group " + args.Parameters[2] + "!"); args.Player.SendSuccessMessage("Account " + user.Name + " has been changed to group " + args.Parameters[2] + "!");
} }
catch (GroupNotExistsException e) catch (GroupNotExistsException e)
@ -1626,7 +1626,7 @@ namespace TShockAPI
{ {
if (ServerApi.RunningMono) if (ServerApi.RunningMono)
{ {
Log.ConsoleInfo("Sorry, this command has not yet been implemented in Mono."); TShock.Log.ConsoleInfo("Sorry, this command has not yet been implemented in Mono.");
} }
else else
{ {
@ -3688,7 +3688,7 @@ namespace TShockAPI
} }
plr.DamagePlayer(damage); plr.DamagePlayer(damage);
TSPlayer.All.SendInfoMessage("{0} slapped {1} for {2} damage.", args.Player.Name, plr.Name, damage); TSPlayer.All.SendInfoMessage("{0} slapped {1} for {2} damage.", args.Player.Name, plr.Name, damage);
Log.Info("{0} slapped {1} for {2} damage.", args.Player.Name, plr.Name, damage); TShock.Log.Info("{0} slapped {1} for {2} damage.", args.Player.Name, plr.Name, damage);
} }
} }
@ -4381,7 +4381,7 @@ namespace TShockAPI
if (TShock.AuthToken == 0) if (TShock.AuthToken == 0)
{ {
args.Player.SendWarningMessage("Auth is disabled. This incident has been logged."); args.Player.SendWarningMessage("Auth is disabled. This incident has been logged.");
Log.Warn(args.Player.IP + " attempted to use /auth even though it's disabled."); TShock.Log.Warn(args.Player.IP + " attempted to use /auth even though it's disabled.");
return; return;
} }
int givenCode = Convert.ToInt32(args.Parameters[0]); int givenCode = Convert.ToInt32(args.Parameters[0]);
@ -4398,7 +4398,7 @@ namespace TShockAPI
} }
catch (UserManagerException ex) catch (UserManagerException ex)
{ {
Log.ConsoleError(ex.ToString()); TShock.Log.ConsoleError(ex.ToString());
args.Player.SendErrorMessage(ex.Message); args.Player.SendErrorMessage(ex.Message);
} }
return; return;
@ -4414,7 +4414,7 @@ namespace TShockAPI
} }
args.Player.SendErrorMessage("Incorrect auth code. This incident has been logged."); args.Player.SendErrorMessage("Incorrect auth code. This incident has been logged.");
Log.Warn(args.Player.IP + " attempted to use an incorrect auth code."); TShock.Log.Warn(args.Player.IP + " attempted to use an incorrect auth code.");
} }
private static void AuthVerify(CommandArgs args) private static void AuthVerify(CommandArgs args)

View file

@ -325,6 +325,12 @@ namespace TShockAPI
[Description("The path of the directory where logs should be written into.")] [Description("The path of the directory where logs should be written into.")]
public string LogPath = "tshock"; public string LogPath = "tshock";
[Description("Save logs to an SQL database instead of a text file. Default = false")]
public bool UseSqlLogs = false;
[Description("Number of times the SQL log must fail to insert logs before falling back to the text log")]
public int RevertToTextLogsOnSqlFailures = 10;
[Description("Prevents players from placing tiles with an invalid style.")] [Description("Prevents players from placing tiles with an invalid style.")]
public bool PreventInvalidPlaceStyle = true; public bool PreventInvalidPlaceStyle = true;

140
TShockAPI/ILog.cs Normal file
View file

@ -0,0 +1,140 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
namespace TShockAPI
{
[Flags]
public enum LogLevel
{
None = 0,
Debug = 1,
Info = 2,
Warning = 4,
Error = 8,
Data = 16,
All = 31
}
/// <summary>
/// Logging interface
/// </summary>
public interface ILog
{
/// <summary>
/// Log name
/// </summary>
string Name { get; }
/// <summary>
/// Returns true if the ILog is using SQL or false if not
/// </summary>
bool Sql { get; }
/// <summary>
/// Checks whether the log level contains the specified flag.
/// </summary>
/// <param name="type">The <see cref="LogLevel" /> value to check.</param>
bool MayWriteType(LogLevel type);
/// <summary>
/// Writes an informative string to the log and to the console.
/// </summary>
/// <param name="message">The message to be written.</param>
void ConsoleInfo(string message);
/// <summary>
/// Writes an informative string to the log and to the console.
/// </summary>
/// <param name="message">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
void ConsoleInfo(string format, params object[] args);
/// <summary>
/// Writes an error message to the log and to the console.
/// </summary>
/// <param name="message">The message to be written.</param>
void ConsoleError(string message);
/// <summary>
/// Writes an error message to the log and to the console.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
void ConsoleError(string format, params object[] args);
/// <summary>
/// Writes a warning to the log.
/// </summary>
/// <param name="message">The message to be written.</param>
void Warn(string message);
/// <summary>
/// Writes a warning to the log.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
void Warn(string format, params object[] args);
/// <summary>
/// Writes an error to the log.
/// </summary>
/// <param name="message">The message to be written.</param>
void Error(string message);
/// <summary>
/// Writes an error to the log.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
void Error(string format, params object[] args);
/// <summary>
/// Writes an informative string to the log.
/// </summary>
/// <param name="message">The message to be written.</param>
void Info(string message);
/// <summary>
/// Writes an informative string to the log.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
void Info(string format, params object[] args);
/// <summary>
/// Writes data to the log.
/// </summary>
/// <param name="message">The message to be written.</param>
void Data(string message);
/// <summary>
/// Writes data to the log.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
void Data(string format, params object[] args);
/// <summary>
/// Writes a message to the log
/// </summary>
/// <param name="message">Message to write</param>
/// <param name="level">LogLevel assosciated with the message</param>
void Write(string message, LogLevel level);
/// <summary>
/// Dispose the Log
/// </summary>
void Dispose();
}
}

View file

@ -17,57 +17,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System; using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
namespace TShockAPI namespace TShockAPI
{ {
[Flags]
public enum LogLevel
{
None = 0,
Debug = 1,
Info = 2,
Warning = 4,
Error = 8,
Data = 16,
All = 31
}
public static class Log public static class Log
{ {
public static string _filename { get; private set; }
private static LogLevel _logLevel;
private static StreamWriter _logWriter;
/// <summary>
/// Creates the log file stream and sets the initial log level.
/// </summary>
/// <param name="filename">The output filename. This file will be overwritten if 'clear' is set.</param>
/// <param name="logLevel">The <see cref="LogLevel" /> value which sets the type of messages to output.</param>
/// <param name="clear">Whether or not to clear the log file on initialization.</param>
public static void Initialize(string filename, LogLevel logLevel, bool clear)
{
_filename = filename;
_logLevel = logLevel;
_logWriter = new StreamWriter(filename, !clear);
}
/// <summary>
/// Checks whether the log level contains the specified flag.
/// </summary>
/// <param name="type">The <see cref="LogLevel" /> value to check.</param>
private static bool MayWriteType(LogLevel type)
{
return ((_logLevel & type) == type);
}
/// <summary> /// <summary>
/// Writes data to the log file. /// Writes data to the log file.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.Data")]
public static void Data(String message) public static void Data(String message)
{ {
Write(message, LogLevel.Data); Write(message, LogLevel.Data);
@ -78,6 +37,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.Data")]
public static void Data(string format, params object[] args) public static void Data(string format, params object[] args)
{ {
Data(String.Format(format, args)); Data(String.Format(format, args));
@ -87,6 +47,7 @@ namespace TShockAPI
/// Writes an error to the log file. /// Writes an error to the log file.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.Error")]
public static void Error(String message) public static void Error(String message)
{ {
Write(message, LogLevel.Error); Write(message, LogLevel.Error);
@ -97,6 +58,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.Error")]
public static void Error(string format, params object[] args) public static void Error(string format, params object[] args)
{ {
Error(String.Format(format, args)); Error(String.Format(format, args));
@ -106,6 +68,7 @@ namespace TShockAPI
/// Writes an error to the log file. /// Writes an error to the log file.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.ConsoleError")]
public static void ConsoleError(String message) public static void ConsoleError(String message)
{ {
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
@ -119,6 +82,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.ConsoleError")]
public static void ConsoleError(string format, params object[] args) public static void ConsoleError(string format, params object[] args)
{ {
ConsoleError(String.Format(format, args)); ConsoleError(String.Format(format, args));
@ -128,6 +92,7 @@ namespace TShockAPI
/// Writes a warning to the log file. /// Writes a warning to the log file.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.Warn")]
public static void Warn(String message) public static void Warn(String message)
{ {
Write(message, LogLevel.Warning); Write(message, LogLevel.Warning);
@ -138,6 +103,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.Warn")]
public static void Warn(string format, params object[] args) public static void Warn(string format, params object[] args)
{ {
Warn(String.Format(format, args)); Warn(String.Format(format, args));
@ -147,6 +113,7 @@ namespace TShockAPI
/// Writes an informative string to the log file. /// Writes an informative string to the log file.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.Info")]
public static void Info(String message) public static void Info(String message)
{ {
Write(message, LogLevel.Info); Write(message, LogLevel.Info);
@ -157,6 +124,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.Info")]
public static void Info(string format, params object[] args) public static void Info(string format, params object[] args)
{ {
Info(String.Format(format, args)); Info(String.Format(format, args));
@ -166,6 +134,7 @@ namespace TShockAPI
/// Writes an informative string to the log file. Also outputs to the console. /// Writes an informative string to the log file. Also outputs to the console.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.ConsoleInfo")]
public static void ConsoleInfo(String message) public static void ConsoleInfo(String message)
{ {
Console.ForegroundColor = ConsoleColor.Yellow; Console.ForegroundColor = ConsoleColor.Yellow;
@ -179,6 +148,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.ConsoleInfo")]
public static void ConsoleInfo(string format, params object[] args) public static void ConsoleInfo(string format, params object[] args)
{ {
ConsoleInfo(String.Format(format, args)); ConsoleInfo(String.Format(format, args));
@ -188,6 +158,7 @@ namespace TShockAPI
/// Writes a debug string to the log file. /// Writes a debug string to the log file.
/// </summary> /// </summary>
/// <param name="message">The message to be written.</param> /// <param name="message">The message to be written.</param>
[Obsolete("Please use TShock.Log.Debug")]
public static void Debug(String message) public static void Debug(String message)
{ {
Write(message, LogLevel.Debug); Write(message, LogLevel.Debug);
@ -198,6 +169,7 @@ namespace TShockAPI
/// </summary> /// </summary>
/// <param name="format">The format of the message to be written.</param> /// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param> /// <param name="args">The format arguments.</param>
[Obsolete("Please use TShock.Log.Debug")]
public static void Debug(string format, params object[] args) public static void Debug(string format, params object[] args)
{ {
Debug(String.Format(format, args)); Debug(String.Format(format, args));
@ -208,7 +180,7 @@ namespace TShockAPI
/// </summary> /// </summary>
public static void Dispose() public static void Dispose()
{ {
_logWriter.Dispose(); TShock.Log.Dispose();
} }
/// <summary> /// <summary>
@ -216,35 +188,7 @@ namespace TShockAPI
/// </summary> /// </summary>
private static void Write(String message, LogLevel level) private static void Write(String message, LogLevel level)
{ {
if (!MayWriteType(level)) TShock.Log.Write(message, level);
{
return;
}
string caller = "TShock";
StackFrame frame = new StackTrace().GetFrame(2);
if (frame != null)
{
var meth = frame.GetMethod();
if (meth != null)
caller = meth.DeclaringType.Name;
}
try
{
_logWriter.WriteLine(string.Format("{0} - {1}: {2}: {3}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
caller, level.ToString().ToUpper(), message));
_logWriter.Flush();
}
catch (ObjectDisposedException)
{
Console.WriteLine("Unable to write to log as log has been disposed.");
Console.WriteLine("{0} - {1}: {2}: {3}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
caller, level.ToString().ToUpper(), message);
}
} }
} }
} }

View file

@ -145,7 +145,7 @@ namespace TShockAPI
} }
catch (Exception e) catch (Exception e)
{ {
Log.ConsoleError(e.ToString()); TShock.Log.ConsoleError(e.ToString());
} }
return false; return false;
} }
@ -206,7 +206,7 @@ namespace TShockAPI
} }
catch (ObjectDisposedException e) catch (ObjectDisposedException e)
{ {
Log.Warn(e.ToString()); TShock.Log.Warn(e.ToString());
} }
catch (SocketException e) catch (SocketException e)
{ {
@ -216,7 +216,7 @@ namespace TShockAPI
case 10053: case 10053:
break; break;
default: default:
Log.Warn(e.ToString()); TShock.Log.Warn(e.ToString());
break; break;
} }
} }
@ -230,12 +230,12 @@ namespace TShockAPI
case SocketError.ConnectionReset: case SocketError.ConnectionReset:
break; break;
default: default:
Log.Warn(e.ToString()); TShock.Log.Warn(e.ToString());
break; break;
} }
} }
else else
Log.Warn(e.ToString()); TShock.Log.Warn(e.ToString());
} }
return false; return false;
} }

248
TShockAPI/SqlLog.cs Normal file
View file

@ -0,0 +1,248 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using TShockAPI.DB;
namespace TShockAPI
{
/// <summary>
/// Class inheriting ILog for writing logs to TShock's SQL database
/// </summary>
public class SqlLog : ILog, IDisposable
{
private readonly LogLevel _logLevel;
private readonly IDbConnection _database;
private readonly TextLog _backupLog;
private int _failures;
private bool _useTextLog;
public string Name
{
get { return "SQL Log Writer"; }
}
public bool Sql
{
get { return true; }
}
public SqlLog(LogLevel logLevel, IDbConnection db, string textlogFilepath, bool clearTextLog)
{
_logLevel = logLevel;
_database = db;
_backupLog = new TextLog(textlogFilepath, logLevel, clearTextLog);
}
public bool MayWriteType(LogLevel type)
{
return ((_logLevel & type) == type);
}
/// <summary>
/// Writes data to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Data(String message)
{
Write(message, LogLevel.Data);
}
/// <summary>
/// Writes data to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Data(string format, params object[] args)
{
Data(String.Format(format, args));
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Error(String message)
{
Write(message, LogLevel.Error);
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Error(string format, params object[] args)
{
Error(String.Format(format, args));
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void ConsoleError(String message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray;
Write(message, LogLevel.Error);
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void ConsoleError(string format, params object[] args)
{
ConsoleError(String.Format(format, args));
}
/// <summary>
/// Writes a warning to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Warn(String message)
{
Write(message, LogLevel.Warning);
}
/// <summary>
/// Writes a warning to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Warn(string format, params object[] args)
{
Warn(String.Format(format, args));
}
/// <summary>
/// Writes an informative string to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Info(String message)
{
Write(message, LogLevel.Info);
}
/// <summary>
/// Writes an informative string to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Info(string format, params object[] args)
{
Info(String.Format(format, args));
}
/// <summary>
/// Writes an informative string to the log file. Also outputs to the console.
/// </summary>
/// <param name="message">The message to be written.</param>
public void ConsoleInfo(String message)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray;
Write(message, LogLevel.Info);
}
/// <summary>
/// Writes an informative string to the log file. Also outputs to the console.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void ConsoleInfo(string format, params object[] args)
{
ConsoleInfo(String.Format(format, args));
}
/// <summary>
/// Writes a debug string to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Debug(String message)
{
Write(message, LogLevel.Debug);
}
/// <summary>
/// Writes a debug string to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Debug(string format, params object[] args)
{
Debug(String.Format(format, args));
}
public void Write(string message, LogLevel level)
{
if (!MayWriteType(level))
return;
var caller = "TShock";
var frame = new StackTrace().GetFrame(2);
if (frame != null)
{
var meth = frame.GetMethod();
if (meth != null && meth.DeclaringType != null)
caller = meth.DeclaringType.Name;
}
try
{
if (_useTextLog)
{
_backupLog.Write(message, level);
return;
}
_database.Query("INSERT INTO Logs (LogLevel, TimeStamp, Caller, Message) VALUES (@0, @1, @2, @3)",
level, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
caller, message);
if (_failures > 0)
_failures--;
}
catch (Exception ex)
{
_backupLog.ConsoleError("SQL Log insert query failed: {0}", ex);
_failures++;
_backupLog.Error("SQL logging will revert to text logging if {0} more failures occur.",
TShock.Config.RevertToTextLogsOnSqlFailures - _failures);
if (_failures >= TShock.Config.RevertToTextLogsOnSqlFailures)
{
_useTextLog = true;
_backupLog.ConsoleError("SQL Logging disabled due to errors. Reverting to text logging.");
}
}
}
public void Dispose()
{
_backupLog.Dispose();
}
}
}

View file

@ -36,8 +36,6 @@ using Terraria;
using TerrariaApi.Server; using TerrariaApi.Server;
using TShockAPI.DB; using TShockAPI.DB;
using TShockAPI.Net; using TShockAPI.Net;
using System.Threading;
using System.Threading.Tasks;
using TShockAPI.ServerSideCharacters; using TShockAPI.ServerSideCharacters;
namespace TShockAPI namespace TShockAPI
@ -53,7 +51,7 @@ namespace TShockAPI
private static string LogFormat = LogFormatDefault; private static string LogFormat = LogFormatDefault;
private const string LogPathDefault = "tshock"; private const string LogPathDefault = "tshock";
private static string LogPath = LogPathDefault; private static string LogPath = LogPathDefault;
private static bool LogClear = false; private static bool LogClear;
public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers]; public static TSPlayer[] Players = new TSPlayer[Main.maxPlayers];
public static BanManager Bans; public static BanManager Bans;
@ -77,6 +75,7 @@ namespace TShockAPI
public static RestManager RestManager; public static RestManager RestManager;
public static Utils Utils = Utils.Instance; public static Utils Utils = Utils.Instance;
public static UpdateManager UpdateManager; public static UpdateManager UpdateManager;
public static ILog Log;
/// <summary> /// <summary>
/// Used for implementing REST Tokens prior to the REST system starting up. /// Used for implementing REST Tokens prior to the REST system starting up.
/// </summary> /// </summary>
@ -126,6 +125,9 @@ namespace TShockAPI
[SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")] [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands")]
public override void Initialize() public override void Initialize()
{ {
string logFilename;
string logPathSetupWarning;
try try
{ {
HandleCommandLine(Environment.GetCommandLineArgs()); HandleCommandLine(Environment.GetCommandLineArgs());
@ -142,37 +144,29 @@ namespace TShockAPI
Main.ServerSideCharacter = ServerSideCharacterConfig.Enabled; Main.ServerSideCharacter = ServerSideCharacterConfig.Enabled;
DateTime now = DateTime.Now; DateTime now = DateTime.Now;
string logFilename;
string logPathSetupWarning = null;
// Log path was not already set by the command line parameter? // Log path was not already set by the command line parameter?
if (LogPath == LogPathDefault) if (LogPath == LogPathDefault)
LogPath = Config.LogPath; LogPath = Config.LogPath;
try try
{ {
logFilename = Path.Combine(LogPath, now.ToString(LogFormat)+".log"); logFilename = Path.Combine(LogPath, now.ToString(LogFormat) + ".log");
if (!Directory.Exists(LogPath)) if (!Directory.Exists(LogPath))
Directory.CreateDirectory(LogPath); Directory.CreateDirectory(LogPath);
} }
catch(Exception ex) catch (Exception ex)
{ {
logPathSetupWarning = "Could not apply the given log path / log format, defaults will be used. Exception details:\n" + ex; logPathSetupWarning =
"Could not apply the given log path / log format, defaults will be used. Exception details:\n" + ex;
Console.ForegroundColor = ConsoleColor.Red; Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(logPathSetupWarning); Console.WriteLine(logPathSetupWarning);
Console.ForegroundColor = ConsoleColor.Gray; Console.ForegroundColor = ConsoleColor.Gray;
// Problem with the log path or format use the default // Problem with the log path or format use the default
logFilename = Path.Combine(LogPathDefault, now.ToString(LogFormatDefault) + ".log"); logFilename = Path.Combine(LogPathDefault, now.ToString(LogFormatDefault) + ".log");
} }
#if DEBUG
Log.Initialize(logFilename, LogLevel.All, false);
#else
Log.Initialize(logFilename, LogLevel.All & ~LogLevel.Debug, LogClear);
#endif
if (logPathSetupWarning != null)
Log.Warn(logPathSetupWarning);
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
} }
catch(Exception ex) catch (Exception ex)
{ {
// Will be handled by the server api and written to its crashlog.txt. // Will be handled by the server api and written to its crashlog.txt.
throw new Exception("Fatal TShock initialization exception. See inner exception for details.", ex); throw new Exception("Fatal TShock initialization exception. See inner exception for details.", ex);
@ -181,16 +175,6 @@ namespace TShockAPI
// Further exceptions are written to TShock's log from now on. // Further exceptions are written to TShock's log from now on.
try try
{ {
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
{
Log.ConsoleInfo(
"TShock was improperly shut down. Please use the exit command in the future to prevent this.");
File.Delete(Path.Combine(SavePath, "tshock.pid"));
}
File.WriteAllText(Path.Combine(SavePath, "tshock.pid"), Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture));
HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
if (Config.StorageType.ToLower() == "sqlite") if (Config.StorageType.ToLower() == "sqlite")
{ {
string sql = Path.Combine(SavePath, "tshock.sqlite"); string sql = Path.Combine(SavePath, "tshock.sqlite");
@ -204,16 +188,18 @@ namespace TShockAPI
DB = new MySqlConnection(); DB = new MySqlConnection();
DB.ConnectionString = DB.ConnectionString =
String.Format("Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};", String.Format("Server={0}; Port={1}; Database={2}; Uid={3}; Pwd={4};",
hostport[0], hostport[0],
hostport.Length > 1 ? hostport[1] : "3306", hostport.Length > 1 ? hostport[1] : "3306",
Config.MySqlDbName, Config.MySqlDbName,
Config.MySqlUsername, Config.MySqlUsername,
Config.MySqlPassword Config.MySqlPassword
); );
} }
catch (MySqlException ex) catch (MySqlException ex)
{ {
Log.Error(ex.ToString()); Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex);
Console.ResetColor();
throw new Exception("MySql not setup correctly"); throw new Exception("MySql not setup correctly");
} }
} }
@ -222,12 +208,34 @@ namespace TShockAPI
throw new Exception("Invalid storage type"); throw new Exception("Invalid storage type");
} }
#if DEBUG
var level = LogLevel.All;
#else
var level = LogLevel.All & ~LogLevel.Debug;
#endif
if (Config.UseSqlLogs)
Log = new SqlLog(level, DB, logFilename, LogClear);
else
Log = new TextLog(logFilename, level, LogClear);
if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
{
Log.ConsoleInfo(
"TShock was improperly shut down. Please use the exit command in the future to prevent this.");
File.Delete(Path.Combine(SavePath, "tshock.pid"));
}
File.WriteAllText(Path.Combine(SavePath, "tshock.pid"),
Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture));
HandleCommandLinePostConfigLoad(Environment.GetCommandLineArgs());
Backups = new BackupManager(Path.Combine(SavePath, "backups")); Backups = new BackupManager(Path.Combine(SavePath, "backups"));
Backups.KeepFor = Config.BackupKeepFor; Backups.KeepFor = Config.BackupKeepFor;
Backups.Interval = Config.BackupInterval; Backups.Interval = Config.BackupInterval;
Bans = new BanManager(DB); Bans = new BanManager(DB);
Warps = new WarpManager(DB); Warps = new WarpManager(DB);
Regions = new RegionManager(DB); Regions = new RegionManager(DB);
Users = new UserManager(DB); Users = new UserManager(DB);
Groups = new GroupManager(DB); Groups = new GroupManager(DB);
Itembans = new ItemManager(DB); Itembans = new ItemManager(DB);
@ -294,7 +302,7 @@ namespace TShockAPI
} }
} }
private static void getTShockAscii() private static void getTShockAscii()
{ {
// ReSharper disable LocalizableElement // ReSharper disable LocalizableElement
Console.Write(" ___ ___ ___ ___ ___ \n" + Console.Write(" ___ ___ ___ ___ ___ \n" +
@ -1210,24 +1218,24 @@ namespace TShockAPI
player.LoginMS = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; player.LoginMS = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
if (TShock.Config.EnableGeoIP && TShock.Geo != null) if (Config.EnableGeoIP && TShock.Geo != null)
{ {
Log.Info(string.Format("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", player.Name, player.IP, Log.Info(string.Format("{0} ({1}) from '{2}' group from '{3}' joined. ({4}/{5})", player.Name, player.IP,
player.Group.Name, player.Country, TShock.Utils.ActivePlayers(), player.Group.Name, player.Country, TShock.Utils.ActivePlayers(),
TShock.Config.MaxSlots)); TShock.Config.MaxSlots));
if (!player.SilentJoinInProgress) if (!player.SilentJoinInProgress)
TShock.Utils.Broadcast(string.Format("{0} ({1}) has joined.", player.Name, player.Country), Color.Yellow); Utils.Broadcast(string.Format("{0} ({1}) has joined.", player.Name, player.Country), Color.Yellow);
} }
else else
{ {
Log.Info(string.Format("{0} ({1}) from '{2}' group joined. ({3}/{4})", player.Name, player.IP, Log.Info(string.Format("{0} ({1}) from '{2}' group joined. ({3}/{4})", player.Name, player.IP,
player.Group.Name, TShock.Utils.ActivePlayers(), TShock.Config.MaxSlots)); player.Group.Name, TShock.Utils.ActivePlayers(), TShock.Config.MaxSlots));
if (!player.SilentJoinInProgress) if (!player.SilentJoinInProgress)
TShock.Utils.Broadcast(player.Name + " has joined.", Color.Yellow); Utils.Broadcast(player.Name + " has joined.", Color.Yellow);
} }
if (TShock.Config.DisplayIPToAdmins) if (Config.DisplayIPToAdmins)
TShock.Utils.SendLogs(string.Format("{0} has joined. IP: {1}", player.Name, player.IP), Color.Blue); Utils.SendLogs(string.Format("{0} has joined. IP: {1}", player.Name, player.IP), Color.Blue);
Utils.ShowFileToUser(player, "motd.txt"); Utils.ShowFileToUser(player, "motd.txt");

View file

@ -78,6 +78,10 @@
<Compile Include="Hooks\AccountHooks.cs" /> <Compile Include="Hooks\AccountHooks.cs" />
<Compile Include="Hooks\GeneralHooks.cs" /> <Compile Include="Hooks\GeneralHooks.cs" />
<Compile Include="Hooks\PlayerHooks.cs" /> <Compile Include="Hooks\PlayerHooks.cs" />
<Compile Include="ILog.cs" />
<Compile Include="Log.cs" />
<Compile Include="SqlLog.cs" />
<Compile Include="TextLog.cs" />
<Compile Include="PaginationTools.cs" /> <Compile Include="PaginationTools.cs" />
<Compile Include="Rest\RestPermissions.cs" /> <Compile Include="Rest\RestPermissions.cs" />
<Compile Include="SaveManager.cs" /> <Compile Include="SaveManager.cs" />
@ -102,7 +106,6 @@
<Compile Include="GetDataHandlers.cs" /> <Compile Include="GetDataHandlers.cs" />
<Compile Include="Group.cs" /> <Compile Include="Group.cs" />
<Compile Include="Extensions\LinqExt.cs" /> <Compile Include="Extensions\LinqExt.cs" />
<Compile Include="Log.cs" />
<Compile Include="Net\BaseMsg.cs" /> <Compile Include="Net\BaseMsg.cs" />
<Compile Include="Net\DisconnectMsg.cs" /> <Compile Include="Net\DisconnectMsg.cs" />
<Compile Include="Net\NetTile.cs" /> <Compile Include="Net\NetTile.cs" />
@ -182,7 +185,7 @@
</PropertyGroup> </PropertyGroup>
<ProjectExtensions> <ProjectExtensions>
<VisualStudio> <VisualStudio>
<UserProperties BuildVersion_UpdateAssemblyVersion="True" BuildVersion_UpdateFileVersion="True" BuildVersion_BuildAction="Both" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_StartDate="2011/6/17" BuildVersion_IncrementBeforeBuild="False" /> <UserProperties BuildVersion_IncrementBeforeBuild="False" BuildVersion_StartDate="2011/6/17" BuildVersion_BuildVersioningStyle="None.None.None.MonthAndDayStamp" BuildVersion_BuildAction="Both" BuildVersion_UpdateFileVersion="True" BuildVersion_UpdateAssemblyVersion="True" />
</VisualStudio> </VisualStudio>
</ProjectExtensions> </ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

250
TShockAPI/TextLog.cs Normal file
View file

@ -0,0 +1,250 @@
/*
TShock, a server mod for Terraria
Copyright (C) 2011-2015 Nyx Studios (fka. The TShock Team)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
namespace TShockAPI
{
/// <summary>
/// Class inheriting ILog for writing logs to a text file
/// </summary>
public class TextLog : ILog, IDisposable
{
private readonly StreamWriter _logWriter;
private readonly LogLevel _logLevel;
/// <summary>
/// Log file name
/// </summary>
public static string fileName { get; private set; }
/// <summary>
/// Name of the TextLog
/// </summary>
public string Name
{
get { return "Text Log Writer"; }
}
public bool Sql
{
get { return false; }
}
/// <summary>
/// Creates the log file stream and sets the initial log level.
/// </summary>
/// <param name="filename">The output filename. This file will be overwritten if 'clear' is set.</param>
/// <param name="logLevel">The <see cref="LogLevel" /> value which sets the type of messages to output.</param>
/// <param name="clear">Whether or not to clear the log file on initialization.</param>
public TextLog(string filename, LogLevel logLevel, bool clear)
{
fileName = filename;
_logLevel = logLevel;
_logWriter = new StreamWriter(filename, !clear);
}
public bool MayWriteType(LogLevel type)
{
return ((_logLevel & type) == type);
}
/// <summary>
/// Writes data to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Data(String message)
{
Write(message, LogLevel.Data);
}
/// <summary>
/// Writes data to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Data(string format, params object[] args)
{
Data(String.Format(format, args));
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Error(String message)
{
Write(message, LogLevel.Error);
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Error(string format, params object[] args)
{
Error(String.Format(format, args));
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void ConsoleError(String message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray;
Write(message, LogLevel.Error);
}
/// <summary>
/// Writes an error to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void ConsoleError(string format, params object[] args)
{
ConsoleError(String.Format(format, args));
}
/// <summary>
/// Writes a warning to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Warn(String message)
{
Write(message, LogLevel.Warning);
}
/// <summary>
/// Writes a warning to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Warn(string format, params object[] args)
{
Warn(String.Format(format, args));
}
/// <summary>
/// Writes an informative string to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Info(String message)
{
Write(message, LogLevel.Info);
}
/// <summary>
/// Writes an informative string to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Info(string format, params object[] args)
{
Info(String.Format(format, args));
}
/// <summary>
/// Writes an informative string to the log file. Also outputs to the console.
/// </summary>
/// <param name="message">The message to be written.</param>
public void ConsoleInfo(String message)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.Gray;
Write(message, LogLevel.Info);
}
/// <summary>
/// Writes an informative string to the log file. Also outputs to the console.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void ConsoleInfo(string format, params object[] args)
{
ConsoleInfo(String.Format(format, args));
}
/// <summary>
/// Writes a debug string to the log file.
/// </summary>
/// <param name="message">The message to be written.</param>
public void Debug(String message)
{
Write(message, LogLevel.Debug);
}
/// <summary>
/// Writes a debug string to the log file.
/// </summary>
/// <param name="format">The format of the message to be written.</param>
/// <param name="args">The format arguments.</param>
public void Debug(string format, params object[] args)
{
Debug(String.Format(format, args));
}
/// <summary>
/// Writes a message to the log
/// </summary>
/// <param name="message"></param>
/// <param name="level"></param>
public void Write(string message, LogLevel level)
{
if (!MayWriteType(level))
return;
var caller = "TShock";
var frame = new StackTrace().GetFrame(2);
if (frame != null)
{
var meth = frame.GetMethod();
if (meth != null && meth.DeclaringType != null)
caller = meth.DeclaringType.Name;
}
try
{
_logWriter.WriteLine("{0} - {1}: {2}: {3}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
caller, level.ToString().ToUpper(), message);
_logWriter.Flush();
}
catch (ObjectDisposedException)
{
Console.WriteLine("Unable to write to log as log has been disposed.");
Console.WriteLine("{0} - {1}: {2}: {3}",
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
caller, level.ToString().ToUpper(), message);
}
}
public void Dispose()
{
_logWriter.Dispose();
}
}
}