Skip to content

Commit

Permalink
FO 3.1.13
Browse files Browse the repository at this point in the history
FO 3.1.13
  • Loading branch information
GitTorre authored Jun 14, 2021
2 parents 8bfd6d3 + c88cc2f commit a027835
Show file tree
Hide file tree
Showing 20 changed files with 308 additions and 291 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,4 @@ ASALocalRun/
**/PublishProfiles/Cloud.xml
/FabricObserver/observer_logs
/FabricObserver/PackageRoot/Data/Plugins/SampleNewObserver.dll
/nuget.exe
8 changes: 4 additions & 4 deletions Build-SFPkgs.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ function Build-SFPkg {
try {
Push-Location $scriptPath

Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Linux.SelfContained.3.1.12" "$scriptPath\bin\release\FabricObserver\linux-x64\self-contained\FabricObserverType"
Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Linux.FrameworkDependent.3.1.12" "$scriptPath\bin\release\FabricObserver\linux-x64\framework-dependent\FabricObserverType"
Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Linux.SelfContained.3.1.13" "$scriptPath\bin\release\FabricObserver\linux-x64\self-contained\FabricObserverType"
Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Linux.FrameworkDependent.3.1.13" "$scriptPath\bin\release\FabricObserver\linux-x64\framework-dependent\FabricObserverType"

Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Windows.SelfContained.3.1.12" "$scriptPath\bin\release\FabricObserver\win-x64\self-contained\FabricObserverType"
Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Windows.FrameworkDependent.3.1.12" "$scriptPath\bin\release\FabricObserver\win-x64\framework-dependent\FabricObserverType"
Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Windows.SelfContained.3.1.13" "$scriptPath\bin\release\FabricObserver\win-x64\self-contained\FabricObserverType"
Build-SFPkg "Microsoft.ServiceFabricApps.FabricObserver.Windows.FrameworkDependent.3.1.13" "$scriptPath\bin\release\FabricObserver\win-x64\framework-dependent\FabricObserverType"
}
finally {
Pop-Location
Expand Down
246 changes: 89 additions & 157 deletions Documentation/Observers.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Documentation/Using.md
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ $appParams = @{ "FabricSystemObserverEnabled" = "true"; "FabricSystemObserverMem
Then execute the application upgrade with

```Powershell
Start-ServiceFabricApplicationUpgrade -ApplicationName fabric:/FabricObserver -ApplicationTypeVersion 3.1.12 -ApplicationParameter $appParams -Monitored -FailureAction rollback
Start-ServiceFabricApplicationUpgrade -ApplicationName fabric:/FabricObserver -ApplicationTypeVersion 3.1.13 -ApplicationParameter $appParams -Monitored -FailureAction rollback
```

Note: On *Linux*, this will restart FO processes (one at a time, UD Walk with safety checks) due to the way Linux Capabilites work. In a nutshell, for any kind of application upgrade, we have to re-run the FO setup script to get the Capabilities in place. For Windows, FO processes will NOT be restarted.
7 changes: 3 additions & 4 deletions FabricObserver.Extensibility/Utilities/DataTableFileLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ public void ConfigureLogger(string filename)

var csvPath = Path.Combine(logFullPath, filename + ".csv");

// Clean out old files if written as MultipleFilesNoArchives.
if (MaxArchiveCsvFileLifetimeDays > 0 && FileWriteFormat == CsvFileWriteFormat.MultipleFilesNoArchives)
// Clean out old files.
if (MaxArchiveCsvFileLifetimeDays > 0)
{
TryCleanLogFolder(logFullPath, TimeSpan.FromDays(MaxArchiveCsvFileLifetimeDays));
}
Expand Down Expand Up @@ -162,8 +162,7 @@ public static void Flush()

private static void TryCleanLogFolder(string folderPath, TimeSpan maxAge)
{
if (!Directory.Exists(folderPath) ||
DateTime.UtcNow.Subtract(Directory.GetLastWriteTimeUtc(folderPath)) < maxAge)
if (!Directory.Exists(folderPath))
{
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public IList<T> Data
private bool isInWarningState;

/// <summary>
/// Gets count of warnings per observer instance across iterations for the lifetime of the Observer.
/// Gets count of total warnings for the lifetime of this instance.
/// </summary>
public int LifetimeWarningCount
{
Expand Down Expand Up @@ -144,8 +144,8 @@ public double AverageDataValue
}

/// <summary>
/// Gets or sets a value indicating whether there is an active warning state on this instance.
/// Set to false when warning state changes to Ok.
/// Gets or sets a value indicating whether there is an active Error or Warning health state on this instance.
/// Set to false when health state changes to Ok.
/// </summary>
public bool ActiveErrorOrWarning
{
Expand Down Expand Up @@ -192,13 +192,13 @@ public bool IsUnhealthy<TU>(TU threshold)
public T StandardDeviation => Data?.Count > 0 ? Statistics.StandardDeviation(Data) : default;

/// <summary>
/// Gets SlidingWindow Max: A sorted list of sliding window maximums.
/// Gets SlidingWindow Max: A sorted list of sliding window maximums. This is only availabe when Data is CircularBufferCollection.
/// </summary>
public IList<T> SlidingWindowMax => Data?.Count > 0 ? Statistics.SlidingWindow(Data, 3, WindowType.Max) : new List<T>(1);
public IList<T> SlidingWindowMax => Data?.Count >= 3 ? Statistics.SlidingWindow(Data, 3, WindowType.Max) : null;

/// <summary>
/// Gets SlidingWindow Min: A sorted list of sliding window minimums.
/// Gets SlidingWindow Min: A sorted list of sliding window minimums. This is only availabe when Data is CircularBufferCollection.
/// </summary>
public IList<T> SlidingWindowMin => Data?.Count > 0 ? Statistics.SlidingWindow(Data, 3, WindowType.Min) : new List<T>(1);
public IList<T> SlidingWindowMin => Data?.Count >= 3 ? Statistics.SlidingWindow(Data, 3, WindowType.Min) : null;
}
}
88 changes: 67 additions & 21 deletions FabricObserver.Extensibility/Utilities/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
// ------------------------------------------------------------

using System;
using System.Diagnostics.Tracing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using FabricObserver.Observers.Interfaces;
using FabricObserver.Observers.Utilities.Telemetry;
using Newtonsoft.Json;
using NLog;
using NLog.Config;
using NLog.Targets;
Expand All @@ -24,7 +25,7 @@ public sealed class Logger : IObserverLogger<ILogger>
private const int Retries = 5;

// This needs to be static to prevent internal EventSource instantiation errors.
private static EventSource etwLogger;
//private static EventSource etwLogger;

private readonly string loggerName;

Expand All @@ -44,19 +45,6 @@ private string Filename
get;
}

private EventSource EtwLogger
{
get
{
if (EnableETWLogging && etwLogger == null)
{
etwLogger = new EventSource(ObserverConstants.EventSourceProviderName);
}

return etwLogger;
}
}

public bool EnableETWLogging
{
get; set;
Expand Down Expand Up @@ -143,9 +131,37 @@ public void LogWarning(string format, params object[] parameters)
OLogger.Warn(format, parameters);
}

/// <summary>
/// Logs EventSource events and automatically determines Level based on object (T data) content inspection.
/// </summary>
/// <typeparam name="T">Anonymous/generic type.</typeparam>
/// <param name="eventName">Name of the event.</param>
/// <param name="data">Anonymous object instance.</param>
public void LogEtw<T>(string eventName, T data)
{
EtwLogger?.Write(eventName, data);
if (!EnableETWLogging)
{
return;
}

// All FO ETW events are written as anonymous .NET types (anonymous object intances with fields/properties)
// housed in FabricObserverDataEvent events of FabricObserverETWProvider EventSource provider. This means they
// are JSON serializable for use in content inspection.
string s = JsonConvert.SerializeObject(data);

if (!string.IsNullOrWhiteSpace(s) && s.Contains("Warning"))
{
ServiceEventSource.Current.DataTypeWriteWarning(eventName, data);
return;
}

if (!string.IsNullOrWhiteSpace(s) && s.Contains("Error"))
{
ServiceEventSource.Current.DataTypeWriteError(eventName, data);
return;
}

ServiceEventSource.Current.DataTypeWriteInfo(eventName, data);
}

public bool TryWriteLogFile(string path, string content)
Expand All @@ -172,11 +188,9 @@ public bool TryWriteLogFile(string path, string content)
File.WriteAllText(path, content);
return true;
}
catch (IOException)
{
}
catch (UnauthorizedAccessException)
catch (Exception e) when (e is ArgumentException || e is IOException || e is UnauthorizedAccessException)
{

}

Thread.Sleep(1000);
Expand Down Expand Up @@ -254,14 +268,21 @@ private void InitializeLoggers()
LogFolderBasePath = logFolderBase;
string file = Path.Combine(logFolderBase, "fabric_observer.log");

if (!string.IsNullOrEmpty(FolderName) && !string.IsNullOrEmpty(Filename))
if (!string.IsNullOrWhiteSpace(FolderName) && !string.IsNullOrWhiteSpace(Filename))
{
string folderPath = Path.Combine(logFolderBase, FolderName);
file = Path.Combine(folderPath, Filename);
}

FilePath = file;

// Clean out old log files. This is to ensure the supplied policy is enforced if FO is restarted before the MaxArchiveFileLifetimeDays has been reached.
// This is because Logger FileTarget settings are not preserved across FO deployments.
if (MaxArchiveFileLifetimeDays > 0)
{
TryCleanLogFolder(Path.Combine(logFolderBase, FolderName), TimeSpan.FromDays(MaxArchiveFileLifetimeDays));
}

var targetName = loggerName + "LogFile";

if (LogManager.Configuration == null)
Expand Down Expand Up @@ -297,5 +318,30 @@ private void InitializeLoggers()
TimeSource.Current = new AccurateUtcTimeSource();
OLogger = LogManager.GetLogger(loggerName);
}

private static void TryCleanLogFolder(string folderPath, TimeSpan maxAge)
{
if (!Directory.Exists(folderPath))
{
return;
}

string[] files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);

foreach (string file in files)
{
try
{
if (DateTime.UtcNow.Subtract(File.GetCreationTime(file)) >= maxAge)
{
File.Delete(file);
}
}
catch (Exception e) when (e is ArgumentException || e is IOException || e is UnauthorizedAccessException)
{

}
}
}
}
}
65 changes: 30 additions & 35 deletions FabricObserver.Extensibility/Utilities/NetworkUsage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,51 +23,45 @@ public static (int LowPort, int HighPort) TupleGetFabricApplicationPortRangeForN
return (-1, -1);
}

StringReader sreader = null;
XmlReader xreader = null;

try
{
// Safe XML pattern - *Do not use LoadXml*.
var xdoc = new XmlDocument { XmlResolver = null };
sreader = new StringReader(clusterManifestXml);
xreader = XmlReader.Create(sreader, new XmlReaderSettings { XmlResolver = null });
xdoc.Load(xreader);
using (var sreader = new StringReader(clusterManifestXml))
{
using (var xreader = XmlReader.Create(sreader, new XmlReaderSettings { XmlResolver = null }))
{
// Safe XML pattern - *Do not use LoadXml*.
var xdoc = new XmlDocument { XmlResolver = null };
xdoc.Load(xreader);

// Cluster Information.
var nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("sf", "http://schemas.microsoft.com/2011/01/fabric");
// Cluster Information.
var nsmgr = new XmlNamespaceManager(xdoc.NameTable);
nsmgr.AddNamespace("sf", "http://schemas.microsoft.com/2011/01/fabric");

// SF Application Port Range.
var applicationEndpointsNode = xdoc.SelectSingleNode($"//sf:NodeTypes//sf:NodeType[@Name='{nodeType}']//sf:ApplicationEndpoints", nsmgr);
// SF Application Port Range.
var applicationEndpointsNode = xdoc.SelectSingleNode($"//sf:NodeTypes//sf:NodeType[@Name='{nodeType}']//sf:ApplicationEndpoints", nsmgr);

if (applicationEndpointsNode == null)
{
return (-1, -1);
}
if (applicationEndpointsNode == null)
{
return (-1, -1);
}

var ret = (int.Parse(applicationEndpointsNode.Attributes?.Item(0)?.Value ?? "-1"),
int.Parse(applicationEndpointsNode.Attributes?.Item(1)?.Value ?? "-1"));
var ret = (int.Parse(applicationEndpointsNode.Attributes?.Item(0)?.Value ?? "-1"),
int.Parse(applicationEndpointsNode.Attributes?.Item(1)?.Value ?? "-1"));

return ret;
return ret;
}
}
}
catch (Exception e) when (e is ArgumentException || e is NullReferenceException || e is XmlException)
{
// continue
}
finally
{
sreader?.Dispose();
xreader?.Dispose();
}

return (-1, -1);
}

public static int GetActiveFirewallRulesCount()
{
ManagementObjectCollection results = null;
ManagementObjectSearcher searcher = null;
int count = -1;

// This method is not implemented for Linux yet.
Expand All @@ -80,17 +74,18 @@ public static int GetActiveFirewallRulesCount()
{
var scope = new ManagementScope("\\\\.\\ROOT\\StandardCimv2");
var q = new ObjectQuery("SELECT * FROM MSFT_NetFirewallRule WHERE Enabled=1");
searcher = new ManagementObjectSearcher(scope, q);
results = searcher.Get();
count = results.Count;

using (var searcher = new ManagementObjectSearcher(scope, q))
{
using (var results = searcher.Get())
{
count = results.Count;
}
}
}
catch (ManagementException)
{
}
finally
{
results?.Dispose();
searcher?.Dispose();

}

return count;
Expand Down
Loading

0 comments on commit a027835

Please sign in to comment.