Hopefully a simple question - is there any kind of ready-made audit log built into Sitecore so I can see who edited content when? I know without versioning the content, the last updated date/user would likely keep overwriting itself, but even knowing who was the last to do something with an item would be useful data. The History table might give some useful info perhaps but I’m not sure. Thanks.
4 Answers
Audit information is available in the logs, and I thought there was a way to isolate them in a separate log file by changing log4net settings. But you could also use the Audit Trail module from the marketplace: https://marketplace.sitecore.net/Modules/S/Sitecore_Audit_Trail.aspx
Helps you to answer following questions:
- Who did change?
- When it happened?
- What all actions happened on aparticular day?
- ...
The log file does contain audit entries, they are a bit hard to see by looking at the log files directly. You can use the Sitecore Log Analyzer from the Sitecore Market place to make it easier to see the audit logs. Once you load in your log folder there is a tab that displays all audit entries:
That will give you some information, although its still not easy to find everything.
If you are looking for something better, I highly recomend Sitecore Sidekick. This module comes with an audit logger that has a lot more features than the standard Sitecore logs.
Also it has a very nice user interface to view the contents of the audit log from within the Sitecore dashboard, so you don't have to download the log files use RDP to access them. Have a look here for a deeper guide on using it: https://jeffdarchuk.com/2016/10/17/sitecore-sidekick-audit-logger/
Just in case anyone lands here and needs to know of the non-out of the box options available to you here is a bit of a run down of ones I'm aware of/have used:
1) Sitecore Audit Trail
This module has been around for a while and I've used it once before, It worked well. The Marketplace module suggests it only works up to 7.5 but I've used it on 8.1 (I may have had to put some updates in to get it work play nice though), the github page suggests it works with 8.x too so it may have been updated since.
Features:
- Who did change on particular item?
- When it happened?
What all actions happened on particular day?
Does all tracking in back end - No effect on performance! [Uses power of log4net Appenders]
- Shows actions at Item Level and Site Level
- You can do search, pagination, and sorting!
- Fully Configurable
- No code changes required to do audit tracking
- Security has been applied -- User needs to be logged in to access it.
- Accessible from Context Menu of an Item And Review Tab
http://klpatil.github.io/Sitecore-Audit-Trail/ https://marketplace.sitecore.net/Modules/S/Sitecore_Audit_Trail.aspx https://github.com/klpatil/Sitecore-Audit-Trail
https://jeffdarchuk.com/2016/10/17/sitecore-sidekick-audit-logger/
For some reason Jeffs Sidekick module does not seem to be that well known but it has an awesome content sync app which I've blogged about a few times and also an Audit Logger app which I have found works really nicely. It traces events, gathers information about those events and stores them in a special search index.
Sidekick and audit logger can be installed from NuGet or The Marketplace and the github page is here: https://github.com/JeffDarchuk/SitecoreSidekick.
3) Use SPE
https://www.sitecoregabe.com/2018/08/basic-sitecore-audit-trail-with.html
Creates a Powershell report that consumes the accessible Sitecore log files which already contain the data needed. This might be the simplest approach but relies on you having the relevant logs.
function Get-Audit () {
# UPDATE: We'll use $SitecoreLogFolder instead. SPE creates a variable $SitecoreLogFolder and resolves the path for you.
# Identify the Sitecore log folder
# $logsFolder = [Sitecore.Configuration.Settings]::LogFolder
# Resolve the log folder's path
# $resolvedPath = Resolve-Path -Path $logsFolder
# Get all log files, then filter out everything that doesn't matter. Sort by LastWriteTime descending.
$files = Get-ChildItem $SitecoreLogFolder | Where-Object { $_.Name -notmatch "Fxm" -and $_.Name -NotMatch "Search" -and $_.Name -NotMatch "WebDAV" -and $_.Name -NotMatch "client" -and $_.Name -NotMatch "Crawling" -and $_.Name -NotMatch "Publishing" -and $_.Name -NotMatch "spe" -and $_.Name -NotMatch "custom" } | Sort-Object LastWriteTime -Descending
# Confirm the user has provided start and end dates.
if ($selectedEndDate -ne "01/01/0001 00:00:00" -and $selectedStartDate.Year -ne "01/01/0001 00:00:00") {
# Filter the log files further to only those within range.
$filteredFiles = $files | Where-Object {$_.LastWriteTime -ge $selectedEndDate -and $_.LastWriteTime -le $selectedStartDate }
}
else {
# If a user chose to not select a date range, use the original file list, but limit the process to the most recent 25 files.
$filteredFiles = $files | Select-Object -First 5
}
# Define a variable used to match the term 'Audit' when processing each line.
$regex = " audit "
# Define an array to house matching line objects.
$finalItems = @()
# Begin a loop based on the number of files to process.
for ($i = 0; $i -lt $filteredFiles.Count; $i++) {
# Get the content of the file.
$fileContent = Get-Content $filteredFiles[$i].FullName
# Set the current file
$file = $filteredFiles[$i]
# Create a date string based on the LastAccessTime.
$formattedFileDate = "$($file.LastAccessTime.Date.Month)/$($file.LastAccessTime.Date.Day)/$($file.LastAccessTime.Date.Year)"
# Loop through each line in the file.
foreach ($line in $fileContent) {
# Check of the line matches the 'AUDIT' regular expression.
if ($line -match $regex) {
# Concatenate the date and the rest of the line to a single variable.
$logLine = "$formattedFileDate $line"
# Remove double spaces from the line.
$saitizedLogLine = $logLine.Replace(" ", " ")
# In some cases, the audit line will contain ManagedPoolThread #XX instead of an ID. This accounts for this scenario
$saitizedLogLine = $saitizedLogLine -Replace "(((ManagedPoolThread)\s\#[^\s]+)\s)", "0 "
# Split the line by spaces and create new objects for each property.
$date, $apid, $time, $loglevel, $logcode, $username, $action = $saitizedLogLine.split(" ")
# Sanitize the username object (removing '{', '}', and ":" characters).
$username = $username -Replace "[#?\{\[\(\)\]\}\:]", ""
# Concatenate the date and time objects to a single string.
$dateTime = "$date $time"
# Convert the concatenated dateTime string to a System.DateTime.
$dateObj = [datetime]($dateTime)
# Define a new line object with each object.
$lineObj = [pscustomobject]@{date = $dateTime; pid = $apid; time = $time; loglevel = $loglevel; logcode = $logcode; username = $username; action = $action; logLine = $logLine; dateObj = $dateObj; }
# Add the line object to the finalItems array.
$finalItems += $lineObj
}
}
}
# Return the finalItems array sorted by date/time descending.
$finalItems | Sort-Object { $_.dateObj -as [datetime]} -Descending
}
# Define the dialog properties. We'll need a start date and end date input from the user.
$dialogProps = @{
Parameters = @(
@{Name = "selectedStartDate"; Title = "Closest Date"; Editor = "date time"; Tooltip = "(How recent?)"},
@{Name = "selectedEndDate"; Title = "Furthest Date"; Editor = "date time"; Tooltip = "(How far back?)"}
)
Title = "Date Filter"
Description = "Select a date range to filter the audit."
ShowHints = $true
}
# Invoke the dialog and set the Read-Variable to determine if the user selects 'cancel'.
$datemodal = Read-Variable @dialogProps
# Check if the user clicked 'cancel.
if ($datemodal -ne "cancel") {
# Define the ListView properties.
$tableProps = @{
InfoTitle = "Audit Trail Report"
InfoDescription = "Audit user logins, logouts, workflow executions, and publishing operations within a specified date range."
PageSize = 100
}
# Get and display the report in a ListView.
Get-Audit | Show-ListView @tableProps -Property @{ Label = "Date"; Expression = { $_.date } },
@{ Label = "ID"; Expression = { $_.pid } },
@{ Label = "Level"; Expression = { $_.loglevel } },
@{ Label = "Code"; Expression = { $_.logcode } },
@{ Label = "User"; Expression = { $_.username } },
@{ Label = "Action"; Expression = { $_.action } }
Close-Window
}
Some further options for consideration:
https://www.seanholmesby.com/sitecore-auditing-with-the-advanced-system-reporter/
There is none, if you configured none.
By that I mean, Sitecore does not keep an audit trail for item changes. There's a few bits of information you can scrape together, but you've already listed those.
If you want a full audit trail, you will have to write some code that hooks into item:saved
on the ContentDatabase and log it to disk. That will not help you retroactively however.
-
All right, thank you Mark, it's what I needed to know, and this case is rare enough that at this point we won't create custom code. Commented Feb 2, 2018 at 20:20
-
Or use workflow and enforce that new item versions are created (assuming fields are Versioned).– jammykamCommented Feb 2, 2018 at 20:29