Skip to content

Commit 105bbca

Browse files
authored
Refactor read trace invocation to avoid duplicate calls to post import script and to exclude log_NNN.trc files (#471)
* #470 allow for a seprate line for pssdiag trace files to show up in SQL Nexus * #470 refactor code so that we can control which post execution scripts is run and make sure the appropriate script is run for .TRC/XEL files and not every time * #470 don't log that script is skipped * #470 exclude the processing of default trace files (log_*.trc) - refactor code
1 parent 1337e47 commit 105bbca

File tree

2 files changed

+127
-56
lines changed

2 files changed

+127
-56
lines changed

ReadTraceNexusImporter/ReadTraceNexusImporter.cs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using System.Xml;
1616
using System.Reflection;
1717
using System.Windows.Forms;
18+
using System.Linq;
1819

1920

2021
namespace ReadTrace
@@ -284,14 +285,19 @@ private decimal GetLocalServerTimeOffset()
284285

285286

286287

287-
private bool SkipFile(string FullFileName)
288+
private bool SkipFile(string fullFileName)
288289
{
289-
bool ret = false;
290-
if (FullFileName.ToLower().EndsWith("_blk.trc"))
291-
ret = true;
290+
string name = Path.GetFileName(fullFileName);
291+
if (name == null)
292+
return false;
292293

293-
return ret;
294+
if (name.EndsWith("_blk.trc", StringComparison.OrdinalIgnoreCase))
295+
return true;
296+
297+
if (System.Text.RegularExpressions.Regex.IsMatch(name, @"^log_\d+\.trc$", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
298+
return true;
294299

300+
return false;
295301
}
296302
/// <summary>Find the first trace file</summary>
297303
/// <remarks>If a trace file without a rollover number exists (e.g. "ABC_sp_trace.trc"), prefer it.
@@ -310,8 +316,6 @@ private string FindFirstTraceFile(string[] files)
310316
Array.Sort(files);
311317
foreach (string f in files)
312318
{
313-
if (SkipFile(f))
314-
continue;
315319

316320
string trcFileNoExt = Path.GetFileNameWithoutExtension(f);
317321
if ((trcFileNoExt.LastIndexOf('_') > -1) // find the last underscore in the filename
@@ -394,16 +398,27 @@ public bool DoImport()
394398
string timeAdjForLocalTimeMinutes = "";
395399
decimal UtcToLocalOffsetHours = 99;
396400
Util.Logger.LogMessage("ReadTraceNexusImporter - Starting import...");
397-
string[] files = Directory.GetFiles(Path.GetDirectoryName(this.traceFileSpec), Path.GetFileName(this.traceFileSpec));
401+
402+
string[] allFiles = Directory.GetFiles(Path.GetDirectoryName(this.traceFileSpec), Path.GetFileName(this.traceFileSpec));
403+
string[] filteredFiles = allFiles.Where(f => !SkipFile(f)).ToArray();
404+
int excludedCount = allFiles.Length - filteredFiles.Length;
405+
406+
if (excludedCount > 0)
407+
Util.Logger.LogMessage($"ReadTraceNexusImporter: Excluded {excludedCount} trace file(s) (log_NNN.trc / *_blk.trc).");
398408

399409
if (null == this.readTracePath)
400410
throw new Exception("Cannot locate ReadTrace.exe. This import requires ReadTrace version 9.0.9.0 or later.");
401-
if (0 == files.Length)
411+
412+
if (filteredFiles.Length == 0)
402413
{
414+
Util.Logger.LogMessage("ReadTraceNexusImporter: No eligible trace files after exclusions.");
403415
State = ImportState.NoFiles;
404416
return false;
405417
}
406418

419+
// Use filtered array
420+
string[] files = filteredFiles;
421+
407422
State = ImportState.Importing;
408423

409424
// Find the first trace file.
@@ -620,7 +635,7 @@ public void OnStatusChanged(EventArgs e)
620635
/// <summary>Filemask (e.g. "*.trc") used to advertise the set of files that a given importer knows how to process</summary>
621636
public string[] SupportedMasks
622637
{
623-
get { return new string[] { "*.TRC", "*pssdiag*.xel", "*LogScout*.xel" }; }
638+
get { return new string[] { "*.trc", "*pssdiag*.xel", "*LogScout*.xel"}; }
624639
}
625640

626641
/// <summary>Number of rows/lines/events processed from source file. Used to communicate progress back to host.</summary>

sqlnexus/fmImport.cs

Lines changed: 102 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.ComponentModel;
4-
using System.Data;
4+
using System.Linq;
55
using System.Drawing;
66
using System.Text;
77
using System.IO;
@@ -95,26 +95,68 @@ private bool BlockFile(string FileName)
9595
return ToBlock;
9696

9797
}
98+
99+
//exclusion for trace files
100+
private static bool IsExcludedTraceFile(string fullPath)
101+
{
102+
string name = Path.GetFileName(fullPath);
103+
if (name == null) return false;
104+
105+
// Existing exclusion
106+
if (name.EndsWith("_blk.trc", StringComparison.OrdinalIgnoreCase))
107+
return true;
108+
109+
// New exclusion: log_NNN.trc pattern
110+
if (System.Text.RegularExpressions.Regex.IsMatch(name, @"^log_\d+\.trc$", RegexOptions.IgnoreCase))
111+
return true;
112+
113+
return false;
114+
}
115+
98116
private void AddFiles(string Mask, INexusImporter Importer)
99117
{
100-
string[] files2 = Directory.GetFiles(cbPath.Text.Trim().Replace("\"", ""), Mask);
118+
string basePath = cbPath.Text.Trim().Replace("\"", "");
119+
string[] allMatches = Directory.GetFiles(basePath, Mask);
120+
101121

102122
//if no file found for this mask, just return
103-
if (files2.Length <= 0)
104-
{
123+
if (allMatches.Length <= 0)
105124
return;
125+
126+
// If this is a trace mask (*.trc) for ReadTrace, filter out excluded files
127+
bool isReadTrace = Importer != null &&
128+
Importer.Name.IndexOf("ReadTrace", StringComparison.OrdinalIgnoreCase) >= 0 &&
129+
Mask.Equals("*.trc", StringComparison.OrdinalIgnoreCase);
130+
131+
//apply exclusion for trace files
132+
string[] includedFiles = allMatches;
133+
if (isReadTrace)
134+
{
135+
includedFiles = allMatches
136+
.Where(f => !IsExcludedTraceFile(f))
137+
.ToArray();
138+
139+
int excludedCount = allMatches.Length - includedFiles.Length;
140+
if (excludedCount > 0)
141+
{
142+
MainForm.LogMessage($"Excluded {excludedCount} trace file(s) from import based on exclusion criteria (log_NNN.trc / *_blk.trc).", MessageOptions.Silent);
143+
}
106144
}
107-
int i = tlpFiles.RowCount - 1;
145+
146+
// If after filtering there are NO included files, do NOT add any UI row.
147+
if (includedFiles.Length == 0)
148+
return;
149+
150+
int rowIndex = tlpFiles.RowCount - 1;
108151

109152

110153
if (Importer is INexusFileImporter)
111154
{
112-
string[] files = Directory.GetFiles(cbPath.Text.Trim().Replace("\"", ""), Mask);
155+
113156
int blockedCounter = 0;
114-
foreach (string f in files)
157+
foreach (string f in includedFiles)
115158
{
116159

117-
118160
//handle multiple instances
119161
//block all text files that are from excluded instances
120162
if (BlockFile(f) || instances.Block(f))
@@ -123,40 +165,33 @@ private void AddFiles(string Mask, INexusImporter Importer)
123165
continue;
124166
}
125167

126-
AddFileRow(i, Path.GetFileName(f), Importer, "");
127-
i++;
168+
AddFileRow(rowIndex, Path.GetFileName(f), Importer, "");
169+
rowIndex++;
128170

129171
}
130172
MainForm.LogMessage("Number of files blocked for import (due to multiple instance or unrelated files such as sqldump*: " + blockedCounter, MessageOptions.Silent);
131173
}
132174
else
133175
{
134-
if (0 != Directory.GetFiles(cbPath.Text.Trim().Replace("\"", ""), Mask).Length) //Only add the mask if matching files are found
176+
if (includedFiles.Length > 0) //Only add the mask if matching files are found
135177
{
136178
//need special handling read trace for multiple instances
137179
//when multiple instances files are caputred, only provide the one instnance selected.
138-
if (Importer.Name.ToUpper().IndexOf("READTRACE") >= 0 && instances.Count > 1)
180+
if (isReadTrace && instances.Count > 1)
139181
{
140182
if (Mask.ToUpper().Contains("XEL"))
141-
{
142-
AddFileRow(i, instances.SelectedXEventFileMask, Importer, "");
143-
}
183+
AddFileRow(rowIndex, instances.SelectedXEventFileMask, Importer, "");
144184
else
145-
{
146-
AddFileRow(i, instances.SelectedTraceFileMask, Importer, "");
147-
}
148-
149-
150-
185+
AddFileRow(rowIndex, instances.SelectedTraceFileMask, Importer, "");
151186
}
152187
else
153188
{
154-
AddFileRow(i, Mask, Importer, "");
189+
AddFileRow(rowIndex, Mask, Importer, "");
155190
}
156191

157192
}
158193
}
159-
}
194+
}//end of AddFiles
160195

161196
private void AddFileRow(int row, string labelText, INexusImporter Importer, string RowType)
162197
{
@@ -888,13 +923,13 @@ private void DoImport()
888923
MainForm);
889924

890925
//Run pre-scripts and cache post scripts for later use
891-
if (!PostScripts.ContainsKey(ri.GetType().Name))
926+
if (!PostScripts.ContainsKey(ri.Name))
892927
{
893-
PostScripts.Add(ri.GetType().Name, ri.PostScripts);
894-
foreach (string s in ri.PreScripts)
928+
PostScripts.Add(ri.Name, ri.PostScripts);
929+
foreach (string pre_script in ri.PreScripts)
895930
{
896-
MainForm.LogMessage("Executing pre-script: " + s);
897-
RunScript(s);
931+
MainForm.LogMessage("Executing pre-script: " + pre_script);
932+
RunScript(pre_script);
898933
}
899934
}
900935

@@ -908,10 +943,8 @@ private void DoImport()
908943

909944

910945

911-
if (ri.Name.ToLower().Contains("rowset"))
912-
{
913-
RunPostScripts();
914-
}
946+
RunPostScripts(ri.Name);
947+
915948
Globals.IsNexusCoreImporterSuccessful = true;
916949
//ll.LinkBehavior = LinkBehavior.HoverUnderline;
917950
}
@@ -1282,30 +1315,53 @@ select count (distinct runtime) 'NumberOfRuntimes' from tbl_PERF_STATS_SCRIPT_RU
12821315
return retString;
12831316
}
12841317

1285-
private void RunPostScripts()
1318+
private void RunPostScripts(string importerName)
12861319
{
1287-
MainForm.LogMessage("Executing post-mortem analysis scripts...");
1288-
//RunScript(Application.StartupPath + @"\TraceAnalysis.sql");
1320+
if (string.IsNullOrEmpty(importerName))
1321+
return;
1322+
1323+
// Only execute ReadTracePostProcessing.sql when the current importer is the ReadTrace importer.
1324+
bool isReadTraceImporter = importerName.Equals("ReadTrace (SQL XEL/TRC files)", StringComparison.OrdinalIgnoreCase);
12891325

1290-
//nothing to run
1291-
if (null == PostScripts || PostScripts.Count <= 0)
1326+
// If nothing to run, skip executing the post scripts.
1327+
if (!PostScripts.TryGetValue(importerName, out var scripts) || scripts == null || scripts.Length == 0)
12921328
return;
12931329

1294-
foreach (string[] scripts in PostScripts.Values)
1330+
MainForm.LogMessage($"Executing post-mortem analysis scripts for importer '{importerName}'...");
1331+
1332+
//RunScript(Application.StartupPath + @"\TraceAnalysis.sql");
1333+
1334+
// Execute each post script from the list.
1335+
foreach (string script in scripts)
12951336
{
1296-
if (scripts == null || scripts.Length <= 0)
1337+
if (string.IsNullOrWhiteSpace(script))
12971338
continue;
1298-
foreach (string script in scripts)
1299-
{
1300-
if (string.IsNullOrEmpty(script))
1301-
continue; //nothign to run
13021339

1303-
MainForm.LogMessage("Executing post-script: " + script);
1304-
RunScript(script);
1340+
// run ReadTracePostProcessing.sql only for the ReadTrace importer
1341+
if (script.Equals("ReadTracePostProcessing.sql", StringComparison.OrdinalIgnoreCase))
1342+
{
1343+
if (!isReadTraceImporter)
1344+
{
1345+
// Skip this script if the current importer is not ReadTrace.
1346+
continue;
1347+
}
13051348
}
1349+
1350+
// in the future we can add more special cases here for other importers if needed (else if ...)
1351+
//else if (script.Equals("AnotherPostProcessing.sql", StringComparison.OrdinalIgnoreCase))
1352+
//{
1353+
// if (!isAnotherImporter)
1354+
// {
1355+
// MainForm.LogMessage($"Skipping '{script}' (only runs for Another importer).", MessageOptions.Silent);
1356+
// continue;
1357+
// }
1358+
//}
1359+
1360+
MainForm.LogMessage("Executing post-script: " + script);
1361+
RunScript(script);
13061362
}
13071363

1308-
MainForm.LogMessage("Execution of post-mortem analysis scripts complete.");
1364+
MainForm.LogMessage($"Execution of post-mortem analysis scripts complete for importer '{importerName}'.");
13091365
}
13101366

13111367
private void RunScript(string scriptname)

0 commit comments

Comments
 (0)