Skip to content

Commit fbce162

Browse files
committed
add detailed logging
1 parent 428629a commit fbce162

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The anonymization/deanonymization process will _only_ run if there are two appli
3636

3737
Add these keys to your `web.config` with the desired salt, and upon the next application start, the database will be anonymized. A new settings key (installed automatically) named "XperienceCommunityDatabaseAnonymized" tracks the current state of the database, so it is safe to leave these keys in the `web.config`- the process will only run once.
3838

39-
The anonymization process runs in the background on application start. To monitor its progress, check the __Event log__ for "ANONYMIZE_START" and "ANONYMIZE_END" events (or, the equivalent "DEANONYMIZE" events). To restore the database to its original state, set the "XperienceCommunityEnableAnonymization" key to false. If you are shipping the entire project (not just the sanitized database), be sure to remove the salt from the `web.config`!
39+
The anonymization process runs in the background on application start. To monitor its progress, check the __Event log__ for "ANONYMIZE_START" and "ANONYMIZE_END" events (or, the equivalent "DEANONYMIZE" events). The "END" event will contain a detailed description of the process and modified records. To restore the database to its original state, set the "XperienceCommunityEnableAnonymization" key to false. If you are shipping the entire project (not just the sanitized database), be sure to remove the salt from the `web.config`!
4040

4141
## Full Instructions
4242

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System.Text;
2+
3+
using CMS;
4+
using CMS.Helpers;
5+
6+
using XperienceCommunity.DatabaseAnonymizer.Services;
7+
8+
[assembly: RegisterImplementation(typeof(IAnonymizationLogger), typeof(AnonymizationLogger))]
9+
namespace XperienceCommunity.DatabaseAnonymizer.Services
10+
{
11+
public class AnonymizationLogger : IAnonymizationLogger
12+
{
13+
private DateTime? mEnd;
14+
private DateTime? mStart;
15+
private readonly Dictionary<string, int> mModifications = [];
16+
17+
18+
public void LogEnd() => mEnd = DateTime.Now;
19+
20+
21+
public void LogModification(string table, int rowsModified)
22+
{
23+
if (rowsModified <= 0)
24+
{
25+
return;
26+
}
27+
28+
if (!mModifications.ContainsKey(table))
29+
{
30+
mModifications.Add(table, rowsModified);
31+
32+
return;
33+
}
34+
35+
int modifications = mModifications[table];
36+
mModifications[table] = modifications + rowsModified;
37+
}
38+
39+
40+
public void LogStart() => mStart = DateTime.Now;
41+
42+
43+
public string GetLog()
44+
{
45+
var msgBuilder = new StringBuilder();
46+
foreach (string table in mModifications.Keys)
47+
{
48+
msgBuilder
49+
.Append("- [")
50+
.Append(table)
51+
.Append("] updated ")
52+
.Append(mModifications[table])
53+
.AppendLine(" rows");
54+
}
55+
56+
return $"Process finished in {GetMinutes()} minutes:{Environment.NewLine}{msgBuilder}";
57+
}
58+
59+
60+
private int GetMinutes()
61+
{
62+
if (mStart is null || mEnd is null)
63+
{
64+
return 0;
65+
}
66+
67+
double seconds = (mEnd - mStart).Value.TotalSeconds;
68+
69+
return ValidationHelper.GetInteger(Math.Ceiling(seconds / 60), 0);
70+
}
71+
}
72+
}

src/Services/AnonymizerService.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace XperienceCommunity.DatabaseAnonymizer.Services
1515
public class AnonymizerService(
1616
IEventLogService eventLogService,
1717
IAnonymizationTableProvider anonymizationTableProvider,
18-
IAppSettingsService appSettingsService) : IAnonymizerService
18+
IAppSettingsService appSettingsService,
19+
IAnonymizationLogger anonmyzationLogger) : IAnonymizerService
1920
{
2021
private byte[]? mKey;
2122
private string? mSalt;
@@ -26,6 +27,7 @@ public class AnonymizerService(
2627
private const string ANONYMIZE_ENABLED_KEYNAME = "XperienceCommunityEnableAnonymization";
2728
private readonly IEventLogService eventLogService = eventLogService;
2829
private readonly IAppSettingsService appSettingsService = appSettingsService;
30+
private readonly IAnonymizationLogger anonymizationLogger = anonmyzationLogger;
2931
private readonly IAnonymizationTableProvider anonymizationTableProvider = anonymizationTableProvider;
3032

3133
/// <summary>
@@ -118,7 +120,8 @@ private void ModifyTable(string table, bool anonymize)
118120
if (updateStatements.Any())
119121
{
120122
string query = string.Join(Environment.NewLine, updateStatements);
121-
ConnectionHelper.ExecuteNonQuery(query, null, QueryTypeEnum.SQLQuery);
123+
int rowsModified = ConnectionHelper.ExecuteNonQuery(query, null, QueryTypeEnum.SQLQuery);
124+
anonymizationLogger.LogModification(table, rowsModified);
122125
}
123126

124127
currentPage++;
@@ -217,13 +220,17 @@ private string GetUpdateRowStatement(
217220
}
218221

219222

220-
private void SetProcessStarted(bool isAnonymized) =>
223+
private void SetProcessStarted(bool isAnonymized)
224+
{
225+
anonymizationLogger.LogStart();
221226
eventLogService.LogInformation(nameof(AnonymizerService), isAnonymized ? "ANONYMIZE_START" : "DEANONYMIZE_START");
227+
}
222228

223229

224230
private void SetProcessFinished(bool isAnonymized)
225231
{
226-
eventLogService.LogInformation(nameof(AnonymizerService), isAnonymized ? "ANONYMIZE_END" : "DEANONYMIZE_END");
232+
anonymizationLogger.LogEnd();
233+
eventLogService.LogInformation(nameof(AnonymizerService), isAnonymized ? "ANONYMIZE_END" : "DEANONYMIZE_END", anonymizationLogger.GetLog());
227234
SettingsKeyInfoProvider.SetGlobalValue(ISANONYMIZED_SETTINGNAME, isAnonymized);
228235
}
229236

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace XperienceCommunity.DatabaseAnonymizer.Services
2+
{
3+
/// <summary>
4+
/// Contains methods for recording anonymization operations.
5+
/// </summary>
6+
public interface IAnonymizationLogger
7+
{
8+
/// <summary>
9+
/// Logs the start time of the anonymization process.
10+
/// </summary>
11+
void LogStart();
12+
13+
14+
/// <summary>
15+
/// Updates the number of rows modified for a table.
16+
/// </summary>
17+
/// <param name="table">The database table.</param>
18+
/// <param name="rowsModified">The number of rows modified.</param>
19+
void LogModification(string table, int rowsModified);
20+
21+
22+
/// <summary>
23+
/// Logs the end time of the anonymization process.
24+
/// </summary>
25+
void LogEnd();
26+
27+
28+
/// <summary>
29+
/// Gets a string summarizing the anonymization process suitable for the Event log.
30+
/// </summary>
31+
string GetLog();
32+
}
33+
}

0 commit comments

Comments
 (0)