Implements 29441 - support for 3rd party log engines (like log4net)

[TFS Changeset #79998]
This commit is contained in:
hartvig
2010-11-15 14:12:21 +00:00
parent ea4038f16a
commit 97e55544a0
12 changed files with 469 additions and 318 deletions

View File

@@ -113,6 +113,9 @@
<disabledLogTypes>
<!-- <logTypeAlias>[alias-of-log-type-in-lowercase]</logTypeAlias> -->
</disabledLogTypes>
<!-- You can add your own logging tool by implementing the umbraco.BusinessLogic.Interfaces.ILog interface and add the reference here -->
<!-- The external logger can also act as the audit trail storage by setting the logAuditTrail attribute to true -->
<!--<externalLogger assembly="~/bin/assemblyFileName.dll" type="fully.qualified.namespace.and.type" logAuditTrail="false" /> -->
</logging>
<scheduledTasks>

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using umbraco.DataLayer;
namespace umbraco.BusinessLogic.Interfaces
{
public interface ILog
{
void Add(LogTypes logType, User user, int nodeId, string comment);
void Add(Exception exception);
void CleanLogs(int maximumAgeOfLogsInMinutes);
List<LogItem> GetLogItems(LogTypes Type, DateTime SinceDate);
List<LogItem> GetLogItems(int NodeId);
List<LogItem> GetLogItems(User user, DateTime SinceDate);
List<LogItem> GetLogItems(User user, LogTypes Type, DateTime SinceDate);
List<LogItem> GetAuditLogReader(int NodeId);
}
}

View File

@@ -4,15 +4,57 @@ using System.Diagnostics;
using System.Threading;
using umbraco.DataLayer;
using System.Collections.Generic;
using System.Reflection;
using umbraco.BusinessLogic.Utils;
namespace umbraco.BusinessLogic
{
/// <summary>
/// Summary description for Log.
/// </summary>
public class Log
{
#region Statics
/// <summary>
/// Summary description for Log.
/// </summary>
public class Log
{
#region Statics
private Interfaces.ILog m_externalLogger = null;
private bool m_externalLoggerInitiated = false;
internal Interfaces.ILog ExternalLogger
{
get
{
if (!m_externalLoggerInitiated)
{
m_externalLoggerInitiated = true;
if (!String.IsNullOrEmpty(UmbracoSettings.ExternalLoggerAssembly)
&& !String.IsNullOrEmpty(UmbracoSettings.ExternalLoggerType))
{
try
{
string assemblyPath = IO.IOHelper.MapPath(UmbracoSettings.ExternalLoggerAssembly);
m_externalLogger = Assembly.LoadFrom(assemblyPath).CreateInstance(UmbracoSettings.ExternalLoggerType) as Interfaces.ILog;
}
catch (Exception ee)
{
Log.AddLocally(LogTypes.Error, User.GetUser(0), -1,
"Error loading external logger: " + ee.ToString());
}
}
}
return m_externalLogger;
}
}
#region Singleton
public static Log Instance
{
get { return Singleton<Log>.Instance; }
}
#endregion
private static ISqlHelper SqlHelper
{
@@ -26,25 +68,82 @@ namespace umbraco.BusinessLogic
/// <param name="user">The user adding the item.</param>
/// <param name="nodeId">The affected node id.</param>
/// <param name="comment">Comment.</param>
public static void Add(LogTypes type, User user, int nodeId, string comment)
{
if(!UmbracoSettings.EnableLogging) return;
public static void Add(LogTypes type, User user, int nodeId, string comment)
{
if (Instance.ExternalLogger != null)
{
Instance.ExternalLogger.Add(type, user, nodeId, comment);
if (UmbracoSettings.DisabledLogTypes != null &&
UmbracoSettings.DisabledLogTypes.SelectSingleNode(String.Format("//logTypeAlias [. = '{0}']", type.ToString().ToLower())) == null) {
if (comment.Length > 3999)
comment = comment.Substring(0, 3955) + "...";
if (UmbracoSettings.EnableAsyncLogging) {
ThreadPool.QueueUserWorkItem(
delegate { AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); });
return;
// Audit trail too?
if (!UmbracoSettings.ExternalLoggerLogAuditTrail && type.GetType().GetField(type.ToString()).GetCustomAttributes(typeof(AuditTrailLogItem), true) != null)
{
AddLocally(type, user, nodeId, comment);
}
AddSynced(type, user == null ? 0 : user.Id, nodeId, comment);
}
}
else
{
if (!UmbracoSettings.EnableLogging) return;
if (UmbracoSettings.DisabledLogTypes != null &&
UmbracoSettings.DisabledLogTypes.SelectSingleNode(String.Format("//logTypeAlias [. = '{0}']", type.ToString().ToLower())) == null)
{
if (comment.Length > 3999)
comment = comment.Substring(0, 3955) + "...";
if (UmbracoSettings.EnableAsyncLogging)
{
ThreadPool.QueueUserWorkItem(
delegate { AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); });
return;
}
AddSynced(type, user == null ? 0 : user.Id, nodeId, comment);
}
}
}
public void AddException(Exception ee)
{
if (ExternalLogger != null)
{
ExternalLogger.Add(ee);
}
else
{
Exception ex2 = ee;
string error = String.Empty;
string errorMessage = string.Empty;
while (ex2 != null)
{
error += ex2.ToString();
ex2 = ex2.InnerException;
}
Add(LogTypes.Error, -1, error);
}
}
/// <summary>
/// Adds the specified log item to the Umbraco log no matter if an external logger has been defined.
/// </summary>
/// <param name="type">The log type.</param>
/// <param name="user">The user adding the item.</param>
/// <param name="nodeId">The affected node id.</param>
/// <param name="comment">Comment.</param>
public static void AddLocally(LogTypes type, User user, int nodeId, string comment)
{
if (comment.Length > 3999)
comment = comment.Substring(0, 3955) + "...";
if (UmbracoSettings.EnableAsyncLogging)
{
ThreadPool.QueueUserWorkItem(
delegate { AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); });
return;
}
AddSynced(type, user == null ? 0 : user.Id, nodeId, comment);
}
/// <summary>
/// Adds the specified log item to the log without any user information attached.
@@ -52,10 +151,10 @@ namespace umbraco.BusinessLogic
/// <param name="type">The log type.</param>
/// <param name="nodeId">The affected node id.</param>
/// <param name="comment">Comment.</param>
public static void Add(LogTypes type, int nodeId, string comment)
{
Add(type, null, nodeId, comment);
}
public static void Add(LogTypes type, int nodeId, string comment)
{
Add(type, null, nodeId, comment);
}
/// <summary>
/// Adds a log item to the log immidiately instead of Queuing it as a work item.
@@ -64,23 +163,99 @@ namespace umbraco.BusinessLogic
/// <param name="userId">The user id.</param>
/// <param name="nodeId">The node id.</param>
/// <param name="comment">The comment.</param>
public static void AddSynced(LogTypes type, int userId, int nodeId, string comment)
{
try
{
SqlHelper.ExecuteNonQuery(
"insert into umbracoLog (userId, nodeId, logHeader, logComment) values (@userId, @nodeId, @logHeader, @comment)",
SqlHelper.CreateParameter("@userId", userId),
SqlHelper.CreateParameter("@nodeId", nodeId),
SqlHelper.CreateParameter("@logHeader", type.ToString()),
SqlHelper.CreateParameter("@comment", comment));
}
catch(Exception e)
{
Debug.WriteLine(e.ToString(), "Error");
Trace.WriteLine(e.ToString());
}
}
public static void AddSynced(LogTypes type, int userId, int nodeId, string comment)
{
try
{
SqlHelper.ExecuteNonQuery(
"insert into umbracoLog (userId, nodeId, logHeader, logComment) values (@userId, @nodeId, @logHeader, @comment)",
SqlHelper.CreateParameter("@userId", userId),
SqlHelper.CreateParameter("@nodeId", nodeId),
SqlHelper.CreateParameter("@logHeader", type.ToString()),
SqlHelper.CreateParameter("@comment", comment));
}
catch (Exception e)
{
Debug.WriteLine(e.ToString(), "Error");
Trace.WriteLine(e.ToString());
}
}
public List<LogItem> GetAuditLogItems(int NodeId)
{
if (UmbracoSettings.ExternalLoggerLogAuditTrail && ExternalLogger != null)
return ExternalLogger.GetAuditLogReader(NodeId);
else
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
"select userId, nodeId, logHeader, DateStamp, logComment from umbracoLog where nodeId = @id and logHeader not in ('open','system') order by DateStamp desc",
SqlHelper.CreateParameter("@id", NodeId)));
}
public List<LogItem> GetLogItems(LogTypes type, DateTime sinceDate)
{
if (ExternalLogger != null)
return ExternalLogger.GetLogItems(type, sinceDate);
else
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
SqlHelper.CreateParameter("@logHeader", type),
SqlHelper.CreateParameter("@dateStamp", sinceDate)));
}
public List<LogItem> GetLogItems(int nodeId)
{
if (ExternalLogger != null)
return ExternalLogger.GetLogItems(nodeId);
else
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where id = @id order by dateStamp desc",
SqlHelper.CreateParameter("@id", nodeId)));
}
public List<LogItem> GetLogItems(User user, DateTime sinceDate)
{
if (ExternalLogger != null)
return ExternalLogger.GetLogItems(user, sinceDate);
else
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and DateStamp >= @dateStamp order by dateStamp desc",
SqlHelper.CreateParameter("@user", user.Id),
SqlHelper.CreateParameter("@dateStamp", sinceDate)));
}
public List<LogItem> GetLogItems(User user, LogTypes type, DateTime sinceDate)
{
if (ExternalLogger != null)
return ExternalLogger.GetLogItems(user, type, sinceDate);
else
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
SqlHelper.CreateParameter("@logHeader", type),
SqlHelper.CreateParameter("@user", user.Id),
SqlHelper.CreateParameter("@dateStamp", sinceDate)));
}
public static void CleanLogs(int maximumAgeOfLogsInMinutes)
{
if (Instance.ExternalLogger != null)
Instance.ExternalLogger.CleanLogs(maximumAgeOfLogsInMinutes);
else
{
try
{
DateTime oldestPermittedLogEntry = DateTime.Now.Subtract(new TimeSpan(0, maximumAgeOfLogsInMinutes, 0));
SqlHelper.ExecuteNonQuery("delete from umbracoLog where datestamp < @oldestPermittedLogEntry and logHeader in ('open','system')",
SqlHelper.CreateParameter("@oldestPermittedLogEntry", oldestPermittedLogEntry));
Add(LogTypes.System, -1, "Log scrubbed. Removed all items older than " + oldestPermittedLogEntry);
}
catch (Exception e)
{
Debug.WriteLine(e.ToString(), "Error");
Trace.WriteLine(e.ToString());
}
}
}
#region New GetLog methods - DataLayer layer compatible
/// <summary>
@@ -88,6 +263,7 @@ namespace umbraco.BusinessLogic
/// </summary>
/// <param name="NodeId">The node id.</param>
/// <returns>A reader for the audit log.</returns>
[Obsolete("Use the Instance.GetAuditLogItems method which return a list of LogItems instead")]
public static IRecordsReader GetAuditLogReader(int NodeId)
{
return SqlHelper.ExecuteReader(
@@ -101,6 +277,7 @@ namespace umbraco.BusinessLogic
/// <param name="Type">The type of log message.</param>
/// <param name="SinceDate">The start date.</param>
/// <returns>A reader for the log.</returns>
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
public static IRecordsReader GetLogReader(LogTypes Type, DateTime SinceDate)
{
return SqlHelper.ExecuteReader(
@@ -114,6 +291,7 @@ namespace umbraco.BusinessLogic
/// </summary>
/// <param name="NodeId">The node id.</param>
/// <returns>A reader for the log.</returns>
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
public static IRecordsReader GetLogReader(int NodeId)
{
return SqlHelper.ExecuteReader(
@@ -127,6 +305,7 @@ namespace umbraco.BusinessLogic
/// <param name="user">The user.</param>
/// <param name="SinceDate">The start date.</param>
/// <returns>A reader for the log.</returns>
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
public static IRecordsReader GetLogReader(User user, DateTime SinceDate)
{
return SqlHelper.ExecuteReader(
@@ -142,6 +321,7 @@ namespace umbraco.BusinessLogic
/// <param name="Type">The type of log message.</param>
/// <param name="SinceDate">The since date.</param>
/// <returns>A reader for the log.</returns>
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
public static IRecordsReader GetLogReader(User user, LogTypes Type, DateTime SinceDate)
{
return SqlHelper.ExecuteReader(
@@ -149,358 +329,205 @@ namespace umbraco.BusinessLogic
SqlHelper.CreateParameter("@logHeader", Type.ToString()),
SqlHelper.CreateParameter("@user", user.Id),
SqlHelper.CreateParameter("@dateStamp", SinceDate));
}
}
#endregion
#region Old GetLog methods - DataLayer incompatible
#pragma warning disable 618 // ConvertToDataSet is obsolete
/// <summary>
/// Gets the log.
/// </summary>
/// <param name="Type">The type.</param>
/// <param name="SinceDate">The start date.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)]
public static DataSet GetLog(LogTypes Type, DateTime SinceDate)
{
try
{
return ConvertToDataSet(GetLogReader(Type, SinceDate));
}
catch (Exception)
{
throw new Exception("The GetLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Returns a dataset of Log items with a specific type since a specific date.
/// </summary>
/// <param name="Type">The type.</param>
/// <param name="SinceDate">The start date.</param>
/// <param name="Limit">Maximum number of results.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)]
public static DataSet GetLog(LogTypes Type, DateTime SinceDate, int Limit)
{
try
{
return ConvertToDataSet(SqlHelper.ExecuteReader(
"select top (" + Limit +
") userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
SqlHelper.CreateParameter("@logHeader", Type.ToString()),
SqlHelper.CreateParameter("@dateStamp", SinceDate)));
}
catch (Exception)
{
throw new Exception("The GetLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Returns a dataset of Log items for a specific node
/// </summary>
/// <param name="NodeId">The node id.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)]
public static DataSet GetLog(int NodeId)
{
try
{
return ConvertToDataSet(GetLogReader(NodeId));
}
catch (Exception)
{
throw new Exception("The GetLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Returns a dataset of audit Log items for a specific node with more detailed user information
/// </summary>
/// <param name="NodeId">The node id.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetAuditLogReader instead.", true)]
public static DataSet GetAuditLog(int NodeId)
{
try
{
return ConvertToDataSet(GetAuditLogReader(NodeId));
}
catch (Exception)
{
throw new Exception("The GetAuditLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Returns a dataset of Log items for a specific user, since a specific date
/// </summary>
/// <param name="u">The user.</param>
/// <param name="SinceDate">The start date.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetAuditLogReader instead.", true)]
public static DataSet GetLog(User u, DateTime SinceDate)
{
try
{
return ConvertToDataSet(GetLogReader(u, SinceDate));
}
catch (Exception)
{
throw new Exception("The GetLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Returns a dataset of Log items for a specific user of a specific type, since a specific date
/// </summary>
/// <param name="u">The user.</param>
/// <param name="Type">The type.</param>
/// <param name="SinceDate">The start date.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)]
public static DataSet GetLog(User u, LogTypes Type, DateTime SinceDate)
{
try
{
return ConvertToDataSet(GetLogReader(u, Type, SinceDate));
}
catch (Exception)
{
throw new Exception("The GetLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Returns a dataset of Log items for a specific user of a specific type, since a specific date
/// </summary>
/// <param name="u">The user.</param>
/// <param name="Type">The type.</param>
/// <param name="SinceDate">The since date.</param>
/// <param name="Limit">The limit.</param>
/// <returns>The log.</returns>
/// <remarks>Only guaranteed to work with SQL Server. Obsolete.</remarks>
[Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)]
public static DataSet GetLog(User u, LogTypes Type, DateTime SinceDate, int Limit)
{
try
{
return ConvertToDataSet(SqlHelper.ExecuteReader(
"select top (" + Limit +
") userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
SqlHelper.CreateParameter("@logHeader", Type.ToString()),
SqlHelper.CreateParameter("@user", u.Id),
SqlHelper.CreateParameter("@dateStamp", SinceDate)));
}
catch (Exception)
{
throw new Exception("The GetLog method is not compatible with the data layer.");
}
}
/// <summary>
/// Converts a records reader to a data set.
/// </summary>
/// <param name="recordsReader">The records reader.</param>
/// <returns>The data set</returns>
/// <remarks>Only works with DataLayer.SqlHelpers.SqlServer.SqlServerDataReader.</remarks>
/// <exception>When not an DataLayer.SqlHelpers.SqlServer.SqlServerDataReader.</exception>
[Obsolete("Temporary workaround for old GetLog methods.", false)]
private static DataSet ConvertToDataSet(IRecordsReader recordsReader)
{
// Get the internal RawDataReader (obsolete)
System.Data.SqlClient.SqlDataReader reader
= ((DataLayer.SqlHelpers.SqlServer.SqlServerDataReader)recordsReader).RawDataReader;
DataSet dataSet = new DataSet();
do
{
DataTable dataTable = new DataTable();
DataTable schemaTable = reader.GetSchemaTable();
if (schemaTable != null)
{
// A query returning records was executed
foreach (DataRow dataRow in schemaTable.Rows)
{
// Create a column name that is unique in the data table
string columnName = (string)dataRow["ColumnName"];
// Add the column definition to the data table
DataColumn column = new DataColumn(columnName, (Type)dataRow["DataType"]);
dataTable.Columns.Add(column);
}
dataSet.Tables.Add(dataTable);
// Fill the data table we just created
while (reader.Read())
{
DataRow dataRow = dataTable.NewRow();
for (int i = 0; i < reader.FieldCount; i++)
dataRow[i] = reader.GetValue(i);
dataTable.Rows.Add(dataRow);
}
}
else
{
// No records were returned, return number of rows affected
dataTable.Columns.Add(new DataColumn("RowsAffected"));
dataSet.Tables.Add(dataTable);
DataRow rowsAffectedRow = dataTable.NewRow();
rowsAffectedRow[0] = reader.RecordsAffected;
dataTable.Rows.Add(rowsAffectedRow);
}
}
// Go trough all result sets
while (reader.NextResult());
// Close the data reader so the underlying connection is closed
recordsReader.Close();
return dataSet;
}
#pragma warning restore 618
#endregion
public static void CleanLogs(int maximumAgeOfLogsInMinutes)
{
try
{
DateTime oldestPermittedLogEntry = DateTime.Now.Subtract(new TimeSpan(0, maximumAgeOfLogsInMinutes, 0));
SqlHelper.ExecuteNonQuery("delete from umbracoLog where datestamp < @oldestPermittedLogEntry and logHeader in ('open','system')",
SqlHelper.CreateParameter("@oldestPermittedLogEntry", oldestPermittedLogEntry));
Add(LogTypes.System, -1, "Log scrubbed. Removed all items older than " + oldestPermittedLogEntry);
}
catch (Exception e)
{
Debug.WriteLine(e.ToString(), "Error");
Trace.WriteLine(e.ToString());
}
}
#endregion
}
/// <summary>
/// The collection of available log types.
/// </summary>
public enum LogTypes
{
public enum LogTypes
{
/// <summary>
/// Used when new nodes are added
/// </summary>
New,
[AuditTrailLogItem]
New,
/// <summary>
/// Used when nodes are saved
/// </summary>
Save,
[AuditTrailLogItem]
Save,
/// <summary>
/// Used when nodes are opened
/// </summary>
Open,
[AuditTrailLogItem]
Open,
/// <summary>
/// Used when nodes are deleted
/// </summary>
Delete,
[AuditTrailLogItem]
Delete,
/// <summary>
/// Used when nodes are published
/// </summary>
Publish,
[AuditTrailLogItem]
Publish,
/// <summary>
/// Used when nodes are send to publishing
/// </summary>
SendToPublish,
[AuditTrailLogItem]
SendToPublish,
/// <summary>
/// Used when nodes are unpublished
/// </summary>
UnPublish,
[AuditTrailLogItem]
UnPublish,
/// <summary>
/// Used when nodes are moved
/// </summary>
Move,
[AuditTrailLogItem]
Move,
/// <summary>
/// Used when nodes are copied
/// </summary>
Copy,
[AuditTrailLogItem]
Copy,
/// <summary>
/// Used when nodes are assígned a domain
/// </summary>
AssignDomain,
[AuditTrailLogItem]
AssignDomain,
/// <summary>
/// Used when public access are changed for a node
/// </summary>
PublicAccess,
[AuditTrailLogItem]
PublicAccess,
/// <summary>
/// Used when nodes are sorted
/// </summary>
Sort,
[AuditTrailLogItem]
Sort,
/// <summary>
/// Used when a notification are send to a user
/// </summary>
Notify,
[AuditTrailLogItem]
Notify,
/// <summary>
/// Used when a user logs into the umbraco back-end
/// </summary>
Login,
Login,
/// <summary>
/// Used when a user logs out of the umbraco back-end
/// </summary>
Logout,
Logout,
/// <summary>
/// Used when a user login fails
/// </summary>
LoginFailure,
LoginFailure,
/// <summary>
/// General system notification
/// </summary>
System,
[AuditTrailLogItem]
System,
/// <summary>
/// System debugging notification
/// </summary>
Debug,
Debug,
/// <summary>
/// System error notification
/// </summary>
Error,
Error,
/// <summary>
/// Notfound error notification
/// </summary>
NotFound,
NotFound,
/// <summary>
/// Used when a node's content is rolled back to a previous version
/// </summary>
RollBack,
[AuditTrailLogItem]
RollBack,
/// <summary>
/// Used when a package is installed
/// </summary>
PackagerInstall,
[AuditTrailLogItem]
PackagerInstall,
/// <summary>
/// Used when a package is uninstalled
/// </summary>
PackagerUninstall,
[AuditTrailLogItem]
PackagerUninstall,
/// <summary>
/// Used when a ping is send to/from the system
/// </summary>
Ping,
Ping,
/// <summary>
/// Used when a node is send to translation
/// </summary>
SendToTranslate,
[AuditTrailLogItem]
SendToTranslate,
/// <summary>
/// Notification from a Scheduled task.
/// </summary>
ScheduledTask,
ScheduledTask,
/// <summary>
/// Use this log action for custom log messages that should be shown in the audit trail
/// </summary>
[AuditTrailLogItem]
Custom
}
}
public class LogItem
{
public int UserId { get; set; }
public int NodeId { get; set; }
public DateTime Timestamp { get; set; }
public LogTypes LogType { get; set; }
public string Comment { get; set; }
public LogItem()
{
}
public LogItem(int userId, int nodeId, DateTime timestamp, LogTypes logType, string comment)
{
UserId = userId;
NodeId = nodeId;
Timestamp = timestamp;
LogType = logType;
Comment = comment;
}
public static List<LogItem> ConvertIRecordsReader(IRecordsReader reader)
{
List<LogItem> items = new List<LogItem>();
while (reader.Read())
{
items.Add(new LogItem(
reader.GetInt("userId"),
reader.GetInt("nodeId"),
reader.GetDateTime("DateStamp"),
convertLogHeader(reader.GetString("logHeader")),
reader.GetString("logComment")));
}
return items;
}
private static LogTypes convertLogHeader(string logHeader)
{
try
{
return (LogTypes)Enum.Parse(typeof(LogTypes), logHeader, true);
}
catch
{
return LogTypes.Custom;
}
}
}
public class AuditTrailLogItem : Attribute
{
public AuditTrailLogItem()
{
}
}
}

View File

@@ -146,6 +146,56 @@ namespace umbraco
}
}
/// <summary>
/// Gets the assembly of an external logger that can be used to store log items in 3rd party systems
/// </summary>
public static string ExternalLoggerAssembly
{
get
{
XmlNode value = GetKeyAsNode("/settings/logging/externalLogger");
if (value != null)
{
return value.Attributes["assembly"].Value;
}
return "";
}
}
/// <summary>
/// Gets the type of an external logger that can be used to store log items in 3rd party systems
/// </summary>
public static string ExternalLoggerType
{
get
{
XmlNode value = GetKeyAsNode("/settings/logging/externalLogger");
if (value != null)
{
return value.Attributes["type"].Value;
}
return "";
}
}
/// <summary>
/// Long Audit Trail to external log too
/// </summary>
public static bool ExternalLoggerLogAuditTrail
{
get
{
XmlNode value = GetKeyAsNode("/settings/logging/externalLogger");
if (value != null)
{
string logAuditTrail = value.Attributes["logAuditTrail"].Value;
bool result;
if (!string.IsNullOrEmpty(logAuditTrail) && bool.TryParse(logAuditTrail, out result))
return result;
}
return false;
}
}
/// <summary>
/// Gets a value indicating whether the logs will be auto cleaned
/// </summary>

View File

@@ -0,0 +1,45 @@
using System;
namespace umbraco.BusinessLogic.Utils
{
/// <summary>
///
/// Threadsafe Singleton best practice design pattern template
///
/// Sample:
///
/// public class Demo
/// {
/// public static Form1 instance1
/// {
/// get
/// {
/// return Singleton<Form1>.Instance;
/// }
/// }
/// }
/// </summary>
/// <typeparam name="T">Any class that implements default constructor</typeparam>
public sealed class Singleton<T> where T : new()
{
private Singleton()
{
}
public static T Instance
{
get { return Nested.instance; }
}
private class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested()
{
}
internal static readonly T instance = new T();
}
}
}

View File

@@ -153,6 +153,7 @@
<Compile Include="IconI.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Interfaces\ILog.cs" />
<Compile Include="IO\IOHelper.cs" />
<Compile Include="IO\SystemDirectories.cs" />
<Compile Include="IO\SystemFiles.cs" />
@@ -181,6 +182,7 @@
<Compile Include="Utils\fileHelper.cs" />
<Compile Include="Utils\JSONSerializer.cs" />
<Compile Include="Utils\SerializableData.cs" />
<Compile Include="Utils\Singleton.cs" />
<Compile Include="Utils\TypeFinder.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -14,6 +14,7 @@ using umbraco.cms.businesslogic.cache;
using umbraco.cms.businesslogic.web;
using umbraco.DataLayer;
using umbraco.IO;
using umbraco.BusinessLogic.Utils;
namespace umbraco
{

View File

@@ -374,7 +374,6 @@
<Compile Include="showField.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Singleton.cs" />
<Compile Include="template.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -15,17 +15,18 @@
<asp:Content ContentPlaceHolderID="body" runat="server">
<cc1:Pane runat="server">
<div id="auditTrailList">
<asp:DataGrid ID="auditLog" runat="server" BorderStyle="None" HeaderStyle-CssClass="gridHeader" ItemStyle-CssClass="gridItem" GridLines="Horizontal" HeaderStyle-Font-Bold="True" AutoGenerateColumns="False"
width="100%">
<Columns>
<asp:TemplateColumn>
<HeaderTemplate>
<b>
<%=umbraco.ui.Text("action")%>
<%=umbraco.ui.Text("action")%>&nbsp;&nbsp;
</b>
</HeaderTemplate>
<ItemTemplate>
<%# FormatAction(DataBinder.Eval(Container.DataItem, "Action", "{0}")) %>
<%# FormatAction(DataBinder.Eval(Container.DataItem, "LogType", "{0}")) %>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn>
@@ -35,7 +36,7 @@
</b>
</HeaderTemplate>
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "User", "{0}") %>
<%# umbraco.BusinessLogic.User.GetUser(int.Parse(DataBinder.Eval(Container.DataItem, "UserId", "{0}"))).Name%>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn>
@@ -45,7 +46,7 @@
</b>
</HeaderTemplate>
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "Date", "{0:D} {0:T}") %>
<%# DataBinder.Eval(Container.DataItem, "Timestamp", "{0:D} {0:T}") %>
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn>
@@ -60,6 +61,7 @@
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
</div>
</cc1:Pane>
</asp:Content>

View File

@@ -21,7 +21,7 @@ namespace umbraco.presentation.umbraco.dialogs
{
// Put user code to initialize the page here
//nodeName.Text = new cms.businesslogic.CMSNode(int.Parse(helper.Request("nodeID"))).Text;
auditLog.DataSource = BusinessLogic.Log.GetAuditLogReader(int.Parse(helper.Request("nodeID")));
auditLog.DataSource = BusinessLogic.Log.Instance.GetAuditLogItems(int.Parse(UmbracoContext.Current.Request["nodeID"]));
auditLog.DataBind();
auditLog.BorderWidth = 0;
auditLog.BorderStyle = BorderStyle.None;
@@ -37,9 +37,9 @@ namespace umbraco.presentation.umbraco.dialogs
{
if (string.Compare(a.Alias, action, true) == 0) {
if(a.Icon.StartsWith("."))
return "<div class=\"menuSpr " + a.Icon.Trim('.') + "\"></div>";
return "<div class=\"menuSpr " + a.Icon.Trim('.') + "\"><span>" + ui.Text(action) + "</span></div>";
else
return "<img alt=\"" + ui.Text(a.Alias) + "\" src=\"../images/" + a.Icon + " width=\"16\" height=\"16\"/>";
return "<img alt=\"" + ui.Text(a.Alias) + "\" src=\"../images/" + a.Icon + " width=\"16\" height=\"16\"/> " + ui.Text(action);
}
}
return action;

View File

@@ -1,10 +1,9 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.3082
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

View File

@@ -530,7 +530,10 @@ guiEditor {
padding-left:25px;
}
#auditTrailList span
{
margin-left: 22px;
}
.umbNitroList{}
.umbNitroList input{float: left; display: block;}