Skip to content

Commit a1eaeca

Browse files
authored
sync: improve logging (#3774)
1 parent 56d979a commit a1eaeca

4 files changed

Lines changed: 92 additions & 43 deletions

File tree

src/SIL.XForge.Scripture/Services/HgWrapper.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ public static string[] Pull(string repository, byte[] bundle)
3838
public void BackupRepository(string repository, string backupFile) =>
3939
RunCommand(repository, $"bundle -a --type v2 \"{backupFile}\"");
4040

41+
/// <summary>
42+
/// Returns a graph of recent commits in the repository.
43+
/// </summary>
44+
public string RecentLogGraph(string repositoryPath)
45+
{
46+
// Include commits that will help when investigating sync problems. Ideally this would include the commit before
47+
// this S/R, any local commits made at the beginning of S/R, and the current tip commit. And without flooding
48+
// the logs. "date(-1)" means within 1 day from today (`hg help dates`). "merge()" means merge commits.
49+
string output = RunCommand(
50+
repositoryPath,
51+
"""log --template "{node} {date|isodate} {phase}\n" --graph --rev "date(-1) or merge() or tip" --limit 5 """
52+
);
53+
// Use a backslash that does not need escaped.
54+
string graph = output.Replace("\\", "\u29F5");
55+
return graph;
56+
}
57+
4158
/// <summary>
4259
/// Get the most recent revision id of the commit from the last push or pull with the PT send/receive server.
4360
/// </summary>

src/SIL.XForge.Scripture/Services/IHgWrapper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public interface IHgWrapper
1313
string GetLastPublicRevision(string repository);
1414
string GetRepoRevision(string repositoryPath);
1515
void MarkSharedChangeSetsPublic(string repository);
16+
string RecentLogGraph(string repositoryPath);
1617
string[] GetDraftRevisions(string repositoryPath);
1718
}

src/SIL.XForge.Scripture/Services/ParatextService.cs

Lines changed: 57 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,10 @@ SyncMetrics syncMetrics
208208
throw new ArgumentNullException();
209209
}
210210

211-
void traceListener(string message) => syncMetrics.Log.Add($"{DateTime.UtcNow:u} Trace: {message}");
212-
void alertListener(string message) => syncMetrics.Log.Add($"{DateTime.UtcNow:u} {message}");
211+
// Note that SyncMetricsLog does not call _logger.Log, to not recurse into the trace listener.
212+
void SyncMetricsLog(string message) => syncMetrics?.Log.Add($"{DateTime.UtcNow:u} SR: {message}");
213+
void traceListener(string message) => SyncMetricsLog($"Trace {message}");
214+
void alertListener(string message) => SyncMetricsLog($"Alert {message}");
213215
LambdaTraceListener listener = new LambdaTraceListener(traceListener);
214216
try
215217
{
@@ -259,7 +261,9 @@ SyncMetrics syncMetrics
259261
if (TryGetProject(userSecret, sendReceiveRepository, projectsMetadata, out ParatextProject ptProject))
260262
{
261263
if (!projectGuids.Contains(paratextId))
262-
_logger.LogWarning($"The project with PT ID {paratextId} did not have a full name available.");
264+
{
265+
SyncMetricsLog($"The project with PT ID {paratextId} did not have a full name available.");
266+
}
263267
}
264268
else
265269
{
@@ -340,28 +344,37 @@ SyncMetrics syncMetrics
340344
throw new InvalidOperationException("User does not have permission to share changes.");
341345
}
342346

343-
// TODO report results
347+
void SyncMetricsLogCommitGraph()
348+
{
349+
string graph = _hgHelper.RecentLogGraph(scrText.Directory);
350+
SyncMetricsLog($"Commit graph:");
351+
Linq.Enumerable.ForEach(Extensions.StringExtensions.SplitLines(graph), SyncMetricsLog);
352+
}
353+
344354
List<SharedProject> sharedPtProjectsToSr = [sharedProj];
345355
List<SendReceiveResult> results = Enumerable.Empty<SendReceiveResult>().ToList();
346356
bool success = false;
347-
bool noErrors = SharingLogicWrapper.HandleErrors(() =>
348-
success = SharingLogicWrapper.ShareChanges(
349-
sharedPtProjectsToSr,
350-
source.AsInternetSharedRepositorySource(),
351-
out results,
352-
sharedPtProjectsToSr
353-
)
354-
);
355-
if (results == null)
357+
bool noErrors = false;
358+
try
356359
{
357-
_logger.LogWarning($"SendReceive results are unexpectedly null.");
360+
noErrors = SharingLogicWrapper.HandleErrors(() =>
361+
success = SharingLogicWrapper.ShareChanges(
362+
sharedPtProjectsToSr,
363+
source.AsInternetSharedRepositorySource(),
364+
out results,
365+
sharedPtProjectsToSr
366+
)
367+
);
358368
}
359-
if (results != null && results.Any(r => r == null))
369+
catch
360370
{
361-
_logger.LogWarning($"SendReceive results unexpectedly contained a null result.");
371+
SyncMetricsLogCommitGraph();
372+
throw;
362373
}
374+
363375
string srResultDescriptions = ExplainSRResults(results);
364-
_logger.LogInformation($"SendReceive results: {srResultDescriptions}");
376+
SyncMetricsLog(srResultDescriptions);
377+
SyncMetricsLogCommitGraph();
365378
if (
366379
!noErrors
367380
|| !success
@@ -650,17 +663,33 @@ public async Task<string> GetResourcePermissionAsync(string paratextId, string s
650663

651664
private static string ExplainSRResults(IEnumerable<SendReceiveResult>? srResults)
652665
{
653-
return string.Join(
654-
";",
655-
srResults?.Select(
656-
(SendReceiveResult r) =>
657-
$"SR result: {r.Result}, "
658-
+ $"Revisions sent: {string.Join(",", r.RevisionsSent ?? Enumerable.Empty<string>())}, "
659-
+ $"Revisions received: {string.Join(",", r.RevisionsReceived ?? Enumerable.Empty<string>())}, "
660-
+ $"Failure message: {r.FailureMessage}."
661-
)
662-
?? []
663-
);
666+
if (srResults == null)
667+
{
668+
return $"SendReceive results are unexpectedly null.";
669+
}
670+
671+
return $"SendReceive results ({srResults.Count()}):\n"
672+
+ string.Join("\n", srResults.Select(ExplainOneSRResult));
673+
}
674+
675+
private static string ExplainOneSRResult(SendReceiveResult? srResult)
676+
{
677+
if (srResult == null)
678+
{
679+
return $"SendReceive result is null.";
680+
}
681+
string revisionsSent =
682+
srResult.RevisionsSent == null
683+
? "(null)"
684+
: $"({srResult.RevisionsSent.Length}) " + string.Join(", ", srResult.RevisionsSent);
685+
string revisionsReceived =
686+
srResult.RevisionsReceived == null
687+
? "(null)"
688+
: $"({srResult.RevisionsReceived.Length}) " + string.Join(", ", srResult.RevisionsReceived);
689+
return $"SR Result: {srResult.Result}\n"
690+
+ $" Revisions sent: {revisionsSent}\n"
691+
+ $" Revisions received: {revisionsReceived}\n"
692+
+ $" Failure message: {srResult.FailureMessage ?? "(null)"}";
664693
}
665694

666695
/// <summary>

src/SIL.XForge.Scripture/Services/ParatextSyncRunner.cs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,13 @@ CancellationToken token
171171
_syncMetrics.RepositoryBackupCreated = canRollbackParatext;
172172
if (canRollbackParatext)
173173
{
174-
Log($"RunAsync: There wasn't already a local PT repo backup, so we made one.");
174+
LogMetric($"RunAsync: There wasn't already a local PT repo backup, so we made one.");
175175
}
176176
else
177177
{
178-
Log($"RunAsync: There wasn't already a local PT repo backup, so we tried to make one but failed.");
178+
LogMetric(
179+
$"RunAsync: There wasn't already a local PT repo backup, so we tried to make one but failed."
180+
);
179181
}
180182
}
181183

@@ -184,17 +186,17 @@ CancellationToken token
184186

185187
if (_paratextService.IsResource(targetParatextId))
186188
{
187-
Log($"This is a resource, so not considering hg repo revisions.");
189+
LogMetric($"This is a resource, so not considering hg repo revisions.");
188190
}
189191
else if (_projectDoc.Data.Sync.SyncedToRepositoryVersion == null)
190192
{
191-
Log(
193+
LogMetric(
192194
$"The SF DB SyncedToRepositoryVersion is null. Maybe this project is being Connected, or has not synced successfully since we started tracking this information."
193195
);
194196
}
195197
else
196198
{
197-
Log(
199+
LogMetric(
198200
$"Setting hg repo to last imported hg repo rev of {_projectDoc.Data.Sync.SyncedToRepositoryVersion}."
199201
);
200202
_paratextService.SetRepoToRevision(
@@ -295,7 +297,7 @@ await GetAndUpdateParatextBooksAndNotes(
295297
// delete all data for removed books
296298
if (targetBooksToDelete.Count > 0)
297299
{
298-
Log(
300+
LogMetric(
299301
$"RunAsync: Going to delete texts and questions,comments,answers for {targetBooksToDelete.Count} books."
300302
);
301303
// delete target books
@@ -889,7 +891,7 @@ private async Task PreflightAuthenticationReportAsync()
889891
{
890892
bool canAuthToRegistry = await _paratextService.CanUserAuthenticateToPTRegistryAsync(_userSecret);
891893
bool canAuthToArchives = await _paratextService.CanUserAuthenticateToPTArchivesAsync(_userSecret.Id);
892-
Log($"User can authenticate to PT Registry: {canAuthToRegistry}, to PT Archives: {canAuthToArchives}.");
894+
LogMetric($"User can authenticate to PT Registry: {canAuthToRegistry}, to PT Archives: {canAuthToArchives}.");
893895
}
894896

895897
private async Task UpdateDocsAsync(
@@ -1688,11 +1690,11 @@ private async Task CompleteSync(bool successful, bool canRollbackParatext, Cance
16881690
await NotifySyncProgress(SyncPhase.Phase9, 60.0);
16891691
if (token.IsCancellationRequested)
16901692
{
1691-
Log($"CompleteSync: There was a cancellation request.");
1693+
LogMetric($"CompleteSync: There was a cancellation request.");
16921694
}
16931695
if (_projectDoc == null || _projectSecret == null)
16941696
{
1695-
Log("CompleteSync: _projectDoc or _projectSecret are null. Rolling back SF DB transaction.");
1697+
LogMetric("CompleteSync: _projectDoc or _projectSecret are null. Rolling back SF DB transaction.");
16961698
_conn.RollbackTransaction();
16971699
return;
16981700
}
@@ -1738,7 +1740,7 @@ private async Task CompleteSync(bool successful, bool canRollbackParatext, Cance
17381740
_syncMetrics.RepositoryRestoredFromBackup = restoreSucceeded;
17391741
}
17401742
}
1741-
Log(
1743+
LogMetric(
17421744
$"CompleteSync: Sync was not successful. {(restoreSucceeded ? "Rolled back" : "Failed to roll back")} local PT repo."
17431745
);
17441746
if (!restoreSucceeded)
@@ -1757,15 +1759,15 @@ await _projectDoc.SubmitJson0OpAsync(op =>
17571759

17581760
if (successful)
17591761
{
1760-
Log($"CompleteSync: Successfully synchronized to PT repo commit id '{repoVersion}'.");
1762+
LogMetric($"CompleteSync: Successfully synchronized to PT repo commit id '{repoVersion}'.");
17611763
op.Set(pd => pd.Sync.DateLastSuccessfulSync, DateTime.UtcNow);
17621764
op.Set(pd => pd.Sync.SyncedToRepositoryVersion, repoVersion);
17631765
// If the sync was successful, then the last sync error code should be cleared
17641766
op.Unset(pd => pd.Sync.LastSyncErrorCode);
17651767
}
17661768
else
17671769
{
1768-
Log(
1770+
LogMetric(
17691771
$"CompleteSync: Failed to synchronize. PT repo latest shared version is '{repoVersion}'. SF DB project SyncedToRepositoryVersion is '{_projectDoc.Data.Sync.SyncedToRepositoryVersion}'."
17701772
);
17711773
}
@@ -2061,7 +2063,7 @@ private void ReportRepoRevs(string prefix = "")
20612063
$"DB Sync.SyncedToRepositoryVersion: {_projectDoc.Data.Sync.SyncedToRepositoryVersion}, DB Sync.DataInSync: {_projectDoc.Data.Sync.DataInSync}.";
20622064
if (_paratextService.IsResource(projectPTId))
20632065
{
2064-
Log($"{prefix}In-sync info: Is resource. {dbInfo}");
2066+
LogMetric($"{prefix}In-sync info: Is resource. {dbInfo}");
20652067
}
20662068
else if (!_paratextService.LocalProjectDirExists(projectPTId))
20672069
{
@@ -2071,7 +2073,7 @@ private void ReportRepoRevs(string prefix = "")
20712073
{
20722074
string repoRev = _paratextService.GetRepoRevision(_userSecret, projectPTId);
20732075
string sharedRev = _paratextService.GetLatestSharedVersion(_userSecret, projectPTId);
2074-
Log(
2076+
LogMetric(
20752077
$"{prefix}In-sync info: Local hg repo current rev: {repoRev}, Latest shared rev: {sharedRev}, {dbInfo}"
20762078
);
20772079
}
@@ -2197,5 +2199,5 @@ private void Log(string message, string? projectSFId = null, string? userId = nu
21972199
_syncMetrics?.Log.Add($"{DateTime.UtcNow:u} {message}");
21982200
}
21992201

2200-
private void LogMetric(string message) => Log(message);
2202+
private void LogMetric(string message) => _syncMetrics?.Log.Add($"{DateTime.UtcNow:u} {message}");
22012203
}

0 commit comments

Comments
 (0)