Updated logging plus more resilient coding to allow better run experience
This commit is contained in:
@@ -9,12 +9,32 @@ using Microsoft.BizTalk.ExplorerOM;
|
||||
|
||||
namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
{
|
||||
/// <summary>
|
||||
/// Discovers monitorable endpoints from the BizTalk management catalog.
|
||||
/// </summary>
|
||||
public sealed class BizTalkCatalogDiscoveryService
|
||||
{
|
||||
/// <summary>
|
||||
/// BizTalk discovery options.
|
||||
/// </summary>
|
||||
private readonly BizTalkOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Output defaults used while normalizing endpoints.
|
||||
/// </summary>
|
||||
private readonly OutputOptions _outputOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Logger used for discovery decisions.
|
||||
/// </summary>
|
||||
private readonly GeneratorFileLogger _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new BizTalk catalog discovery service.
|
||||
/// </summary>
|
||||
/// <param name="options">BizTalk discovery options.</param>
|
||||
/// <param name="outputOptions">Output defaults for generated targets.</param>
|
||||
/// <param name="logger">Discovery logger.</param>
|
||||
public BizTalkCatalogDiscoveryService(BizTalkOptions options, OutputOptions outputOptions, GeneratorFileLogger logger)
|
||||
{
|
||||
_options = options ?? new BizTalkOptions();
|
||||
@@ -22,10 +42,17 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers all configured BizTalk artifact endpoints and returns monitor-compatible endpoints.
|
||||
/// </summary>
|
||||
/// <returns>The discovered endpoints sorted by application, target name and endpoint.</returns>
|
||||
public IReadOnlyCollection<DiscoveredEndpoint> Discover()
|
||||
{
|
||||
var discovered = new List<DiscoveredEndpoint>();
|
||||
var inspectedApplications = 0;
|
||||
var skippedApplications = 0;
|
||||
|
||||
_logger.Info("BizTalk-Katalog wird geöffnet. IncludeSendPorts=" + _options.IncludeSendPorts + ", IncludeReceiveLocations=" + _options.IncludeReceiveLocations + ".");
|
||||
var catalog = new BtsCatalogExplorer();
|
||||
catalog.ConnectionString = _options.ConnectionString;
|
||||
|
||||
@@ -38,10 +65,14 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
|
||||
if (ShouldSkipApplication(application))
|
||||
{
|
||||
skippedApplications++;
|
||||
_logger.Info("BizTalk-Anwendung übersprungen: " + application.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
inspectedApplications++;
|
||||
_logger.Info("BizTalk-Anwendung wird analysiert: " + application.Name);
|
||||
|
||||
if (_options.IncludeSendPorts)
|
||||
{
|
||||
DiscoverSendPorts(application, discovered);
|
||||
@@ -53,6 +84,8 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("BizTalk-Discovery beendet. AnalysierteAnwendungen=" + inspectedApplications + ", UebersprungeneAnwendungen=" + skippedApplications + ", UnterstuetzteTargets=" + discovered.Count + ".");
|
||||
|
||||
return discovered
|
||||
.OrderBy(x => x.MappedApplicationName, StringComparer.OrdinalIgnoreCase)
|
||||
.ThenBy(x => x.TargetName, StringComparer.OrdinalIgnoreCase)
|
||||
@@ -60,6 +93,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers send port transports from one BizTalk application.
|
||||
/// </summary>
|
||||
/// <param name="application">The BizTalk application to inspect.</param>
|
||||
/// <param name="discovered">The target collection receiving supported endpoints.</param>
|
||||
private void DiscoverSendPorts(Application application, List<DiscoveredEndpoint> discovered)
|
||||
{
|
||||
foreach (SendPort sendPort in application.SendPorts)
|
||||
@@ -90,6 +128,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discovers receive locations from one BizTalk application.
|
||||
/// </summary>
|
||||
/// <param name="application">The BizTalk application to inspect.</param>
|
||||
/// <param name="discovered">The target collection receiving supported endpoints.</param>
|
||||
private void DiscoverReceiveLocations(Application application, List<DiscoveredEndpoint> discovered)
|
||||
{
|
||||
foreach (ReceivePort receivePort in application.ReceivePorts)
|
||||
@@ -131,6 +174,16 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a send port transport when it exists and can be normalized.
|
||||
/// </summary>
|
||||
/// <param name="discovered">The target collection receiving supported endpoints.</param>
|
||||
/// <param name="bizTalkApplicationName">The source BizTalk application name.</param>
|
||||
/// <param name="artifactType">The artifact type label.</param>
|
||||
/// <param name="targetNameBase">The base name for the generated target.</param>
|
||||
/// <param name="artifactName">The source artifact name.</param>
|
||||
/// <param name="transport">The BizTalk transport information.</param>
|
||||
/// <param name="isSecondary">True when the transport is a secondary send port transport.</param>
|
||||
private void AddTransportIfSupported(List<DiscoveredEndpoint> discovered, string bizTalkApplicationName, string artifactType, string targetNameBase, string artifactName, TransportInfo transport, bool isSecondary)
|
||||
{
|
||||
if (transport == null)
|
||||
@@ -150,6 +203,17 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
isSecondary);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a discovered endpoint when artifact filters and endpoint normalization allow it.
|
||||
/// </summary>
|
||||
/// <param name="discovered">The target collection receiving supported endpoints.</param>
|
||||
/// <param name="bizTalkApplicationName">The source BizTalk application name.</param>
|
||||
/// <param name="artifactType">The artifact type label.</param>
|
||||
/// <param name="targetNameBase">The base name for the generated target.</param>
|
||||
/// <param name="artifactName">The source artifact name.</param>
|
||||
/// <param name="adapterName">The BizTalk adapter name.</param>
|
||||
/// <param name="sourceAddress">The raw address read from BizTalk.</param>
|
||||
/// <param name="isSecondary">True when the endpoint is from a secondary transport.</param>
|
||||
private void AddEndpointIfSupported(List<DiscoveredEndpoint> discovered, string bizTalkApplicationName, string artifactType, string targetNameBase, string artifactName, string adapterName, string sourceAddress, bool isSecondary)
|
||||
{
|
||||
if (ShouldSkipArtifact(artifactName))
|
||||
@@ -190,6 +254,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
_logger.Discovery("ADD", artifactType, bizTalkApplicationName, artifactName, adapterName, sourceAddress, normalizedEndpoint, "Zuordnung zu ApplicationName='" + mappedApplication + "'.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a BizTalk application should be skipped.
|
||||
/// </summary>
|
||||
/// <param name="application">The BizTalk application to inspect.</param>
|
||||
/// <returns>True when the application should be skipped.</returns>
|
||||
private bool ShouldSkipApplication(Application application)
|
||||
{
|
||||
if (application == null)
|
||||
@@ -205,6 +274,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return _options.IgnoreApplications.Any(pattern => WildcardMatch(application.Name, pattern));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a BizTalk artifact name matches a configured ignore pattern.
|
||||
/// </summary>
|
||||
/// <param name="artifactName">The artifact name to inspect.</param>
|
||||
/// <returns>True when the artifact should be skipped.</returns>
|
||||
private bool ShouldSkipArtifact(string artifactName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(artifactName))
|
||||
@@ -215,6 +289,13 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return _options.IgnoreArtifactNamePatterns.Any(pattern => WildcardMatch(artifactName, pattern));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the generated monitor application name for a BizTalk artifact.
|
||||
/// </summary>
|
||||
/// <param name="bizTalkApplicationName">The source BizTalk application name.</param>
|
||||
/// <param name="artifactType">The source artifact type.</param>
|
||||
/// <param name="artifactName">The source artifact name.</param>
|
||||
/// <returns>The generated monitor application name.</returns>
|
||||
private string ResolveMappedApplicationName(string bizTalkApplicationName, string artifactType, string artifactName)
|
||||
{
|
||||
foreach (var rule in _options.ArtifactMappings.Where(r => r != null && !string.IsNullOrWhiteSpace(r.ApplicationName)))
|
||||
@@ -241,6 +322,14 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return string.IsNullOrWhiteSpace(bizTalkApplicationName) ? "Unassigned Application" : bizTalkApplicationName.Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a generated monitor target name from BizTalk artifact metadata.
|
||||
/// </summary>
|
||||
/// <param name="artifactType">The source artifact type.</param>
|
||||
/// <param name="baseName">The base artifact display name.</param>
|
||||
/// <param name="adapterName">The BizTalk adapter name.</param>
|
||||
/// <param name="isSecondary">True when the endpoint is from a secondary transport.</param>
|
||||
/// <returns>The generated target name.</returns>
|
||||
private string BuildTargetName(string artifactType, string baseName, string adapterName, bool isSecondary)
|
||||
{
|
||||
var prefix = string.Equals(artifactType, "ReceiveLocation", StringComparison.OrdinalIgnoreCase)
|
||||
@@ -261,6 +350,16 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalizes a BizTalk adapter address into a monitor-compatible endpoint.
|
||||
/// </summary>
|
||||
/// <param name="sourceAddress">The raw address read from BizTalk.</param>
|
||||
/// <param name="adapterName">The BizTalk adapter name.</param>
|
||||
/// <param name="normalizedEndpoint">The normalized monitor endpoint when successful.</param>
|
||||
/// <param name="port">The resolved explicit port when available.</param>
|
||||
/// <param name="httpMethod">The generated HTTP method when applicable.</param>
|
||||
/// <param name="reason">The skip reason when normalization fails.</param>
|
||||
/// <returns>True when the address can be monitored; otherwise false.</returns>
|
||||
private bool TryNormalizeEndpoint(string sourceAddress, string adapterName, out string normalizedEndpoint, out int? port, out string httpMethod, out string reason)
|
||||
{
|
||||
normalizedEndpoint = string.Empty;
|
||||
@@ -386,6 +485,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely resolves the adapter name from a BizTalk transport.
|
||||
/// </summary>
|
||||
/// <param name="transport">The BizTalk transport information.</param>
|
||||
/// <returns>The adapter name or an empty string.</returns>
|
||||
private static string ResolveAdapterName(TransportInfo transport)
|
||||
{
|
||||
try
|
||||
@@ -398,6 +502,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely resolves the adapter name from a BizTalk protocol type.
|
||||
/// </summary>
|
||||
/// <param name="transportType">The BizTalk protocol type.</param>
|
||||
/// <returns>The adapter name or an empty string.</returns>
|
||||
private static string ResolveAdapterName(ProtocolType transportType)
|
||||
{
|
||||
try
|
||||
@@ -410,6 +519,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely reads the address from a BizTalk transport.
|
||||
/// </summary>
|
||||
/// <param name="transport">The BizTalk transport information.</param>
|
||||
/// <returns>The transport address or an empty string.</returns>
|
||||
private static string SafeAddress(TransportInfo transport)
|
||||
{
|
||||
try
|
||||
@@ -422,12 +536,23 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether an adapter name contains a fragment.
|
||||
/// </summary>
|
||||
/// <param name="adapterName">The adapter name to inspect.</param>
|
||||
/// <param name="fragment">The fragment to search for.</param>
|
||||
/// <returns>True when the adapter name contains the fragment.</returns>
|
||||
private static bool AdapterContains(string adapterName, string fragment)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(adapterName)
|
||||
&& adapterName.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detects semicolon-separated email recipient lists that are not monitorable endpoints.
|
||||
/// </summary>
|
||||
/// <param name="value">The address value to inspect.</param>
|
||||
/// <returns>True when the value looks like an email address list.</returns>
|
||||
private static bool LooksLikeEmailAddressList(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
@@ -475,6 +600,12 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies simple wildcard matching with asterisks and question marks.
|
||||
/// </summary>
|
||||
/// <param name="input">The input value.</param>
|
||||
/// <param name="pattern">The wildcard pattern.</param>
|
||||
/// <returns>True when the input matches the pattern.</returns>
|
||||
private static bool WildcardMatch(string input, string pattern)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(pattern))
|
||||
@@ -487,6 +618,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return Regex.IsMatch(input, regex, RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether a value looks like a host:port endpoint.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to inspect.</param>
|
||||
/// <returns>True when the value contains a host and numeric port.</returns>
|
||||
private static bool LooksLikeHostPort(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
@@ -497,6 +633,11 @@ namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
return Regex.IsMatch(value.Trim(), @"^[a-zA-Z0-9._-]+:\d{1,5}($|/.*$)");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a port from a host:port value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value containing a port.</param>
|
||||
/// <returns>The parsed port, or null when no port is found.</returns>
|
||||
private static int? ParsePort(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
|
||||
@@ -1,18 +1,68 @@
|
||||
namespace BizTalkMonitorConfigGenerator.BizTalk
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents one BizTalk artifact endpoint that can be written as a monitor target.
|
||||
/// </summary>
|
||||
public sealed class DiscoveredEndpoint
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the BizTalk artifact type.
|
||||
/// </summary>
|
||||
public string ArtifactType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source BizTalk application name.
|
||||
/// </summary>
|
||||
public string BizTalkApplicationName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the generated monitor application name.
|
||||
/// </summary>
|
||||
public string MappedApplicationName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the source BizTalk artifact name.
|
||||
/// </summary>
|
||||
public string ArtifactName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the BizTalk adapter name.
|
||||
/// </summary>
|
||||
public string AdapterName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the raw address read from BizTalk.
|
||||
/// </summary>
|
||||
public string SourceAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the monitor-compatible endpoint.
|
||||
/// </summary>
|
||||
public string NormalizedEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the generated monitor target name.
|
||||
/// </summary>
|
||||
public string TargetName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the HTTP method for generated HTTP targets.
|
||||
/// </summary>
|
||||
public string HttpMethod { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the explicit target port, when resolved.
|
||||
/// </summary>
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets an optional UNC path validation override.
|
||||
/// </summary>
|
||||
public bool? ValidateUncPathAccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets discovery detail text for diagnostics.
|
||||
/// </summary>
|
||||
public string Detail { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user