Skip to content

Commit

Permalink
Address #138 & #139 (#150)
Browse files Browse the repository at this point in the history
* Introduce the algorithm for rotating health report file

* Add configuration support for csv health report boundary

- SingleLogFileMaximumSizeInMBytes
- RententionLogsInDays

* Implement date window for csv health report

* Remove 'current' suffix for logs for compatbility

* Handle log folder no permission issue

* Add new tests for CsvHealthReporter

* Refactor rotate logfile to add testability

* Add testability to log retention

* Fix the .NET Core Console Consumer App

* Update README.md

* Get a better name of logRentensionInDays to replace RetensionLogsInDays

It is log retention than logs for retention.

* Rewords description for logRetentionInDays in README

* Revert the change to IRequireActivation

* Refactor the code for better testability

* Reword a code comment

* Bump up version number for EF.Core
  • Loading branch information
xiaomi7732 authored Nov 16, 2017
1 parent 85926c7 commit 4fb15f8
Show file tree
Hide file tree
Showing 17 changed files with 597 additions and 232 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,9 @@ This health reporter writes all errors, warnings, and informational traces gener
"logFileFolder": ".",
"logFilePrefix": "HealthReport",
"minReportLevel": "Warning",
"throttlingPeriodMsec": "1000"
"throttlingPeriodMsec": "1000",
"singleLogFileMaximumSizeInMBytes": "8192",
"logRetentionInDays": "30"
}
```
| Field | Values/Types | Required | Description |
Expand All @@ -858,8 +860,11 @@ This health reporter writes all errors, warnings, and informational traces gener
| `logFilePrefix` | file path | No | Specifies a prefix used for the CSV log file. CsvHealthReporter creates the log file name by combining this prefix with the date of when the file is generated. If the prefix is omitted, then a default prefix of "HealthReport" is used. |
| `minReportLevel` | Error, Warning, Message | No | Specifies the collection report level. Report traces with equal or higher severity than specified are collected. For example, if Warning is specified, then Error, and Warning traces are collected. Default is Error. |
| `throttlingPeriodMsec` | number of milliseconds | No | Specifies the throttling time period. This setting protects the health reporter from being overwhelmed, which can happen if a message is repeatedly generated due to an error in the pipeline. Default is 0, for no throttling. |
| `singleLogFileMaximumSizeInMBytes` | File size in MB/number | No | Specifies the size of the log file in MB before rotating happens. The default value is 8192 MB (8 GB). Once the size of log file exceeds the value, it will be renamed from fileName.csv to fileName_last.csv. Then logs will be written to a new fileName.csv. This setting prevents a single log file become too big. |
| `logRetentionInDays` | number of days for the logs files retain | No | Specifies how long log files will be retained. The default value is 30 days. Any log files created earlier than the specified number of days ago will be removed automatically. This prevents continuous generation of logs that might lead to storage exhaustion. |

CsvHealthReporter will try to open the log file for writing during initialization. If it can't, it is considered a fatal error and will cause the whole EventFlow pipeline to fail. This can happen especially if a value for the log file path is not provided (default is used, which is application executables folder) and the application executables are residing on a read-only file system. Docker tools for Visual Studio use this configuration during debugging, so for containerized services the recommended practice is to specify the log file path explicitly.

CsvHealthReporter will try to open the log file for writing during initialization. If it can't, a debug message will be output to the debugger viewer like Visual Studio Output window, etc. This can happen especially if a value for the log file path is not provided (default is used, which is application executables folder) and the application executables are residing on a read-only file system. Docker tools for Visual Studio use this configuration during debugging, so for containerized services the recommended practice is to specify the log file path explicitly.

### Pipeline Settings
The EventFlow configuration has settings allowing the application to adjust certain behaviors of the pipeline. These range from how many events the pipeline buffer, to the timeout the pipeline should use when waiting for an operation. If this section is omitted, the pipeline will use default settings.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,10 @@
<ProjectReference Include="..\Microsoft.Diagnostics.EventFlow.Outputs.StdOutput\Microsoft.Diagnostics.EventFlow.Outputs.StdOutput.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="config.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,25 @@
// ------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Diagnostics.EventFlow.HealthReporters;
using Microsoft.Diagnostics.EventFlow.Inputs;
using Microsoft.Diagnostics.EventFlow.Outputs;
using System.Threading;

namespace Microsoft.Diagnostics.EventFlow.Consumers.ConsoleAppCore
{
public class Program
{
public static void Main(string[] args)
{
// HealthReporter
var configBuilder = new ConfigurationBuilder();
configBuilder.AddJsonFile("config.json");
var configuration = configBuilder.Build();

using (IHealthReporter reporter = new CsvHealthReporter("FileReportConfig.json"))
using (var pipeline = DiagnosticPipelineFactory.CreatePipeline("config.json"))
{
// Listeners
List<IObservable<EventData>> inputs = new List<IObservable<EventData>>();
inputs.Add((new TraceInputFactory()).CreateItem(configuration, reporter));

// Senders
var outputs = new List<IOutput>();
outputs.Add(new StdOutput(reporter));

DiagnosticPipeline pipeline = new DiagnosticPipeline(
reporter,
inputs,
null,
new EventSink[] { new EventSink(new StdOutput(reporter), null) });

// Build up the pipeline
Console.WriteLine("Pipeline is created.");

// Send a trace to the pipeline
Trace.TraceInformation("This is a message from trace . . .");
Trace.TraceWarning("This is a warning from trace . . .");


// Check the result
Console.WriteLine("Press any key to continue . . .");
Console.ReadKey(true);
for (int i = 0; i < 200000; i++)
{
// You shall not need to call this unless you really want to diagnose EventHub issue.
pipeline.HealthReporter.ReportHealthy("Some health report content. . .");
Thread.Sleep(1);
}
Trace.TraceWarning("EventFlow is working!");
Console.ReadLine();
}
}
}
Expand Down
135 changes: 12 additions & 123 deletions src/Microsoft.Diagnostics.EventFlow.Consumers.ConsoleAppCore/config.json
Original file line number Diff line number Diff line change
@@ -1,136 +1,25 @@
{
"inputs": [
{
"type": "EventSource",
"sources": [
{ "providerName": "Microsoft-ServiceFabric-Services" },
{ "providerName": "MyCompany-AirTrafficControlApplication-Frontend" }
]
},
{
"type": "PerformanceCounter",
"counters": [
{
"counterCategory": "Process",
"counterName": "% Processor Time"
},
{
"counterCategory": "Process",
"counterName": "Private Bytes"
},
{
"counterCategory": ".NET CLR Memory",
"counterName": "% Time in GC"
},
{
"counterCategory": "Process",
"counterName": "# of Exceps Thrown / sec"
}
]
},
{
"type": "Trace",
"traceLevel": "Warning"
}
],

"filters": [
{
"type": "drop",
"include": "Level == Verbose"
}
],

"outputs": [
{
"type": "ApplicationInsights",

// Should be a secret, eventually
"InstrumentationKey": "***REMOVED***",

"filters": [
// EventSource-based metrics
{
"type": "metadata",
"metadata": "metric",
"include": "ProviderName == Microsoft-ServiceFabric-Services && EventName == StatefulRunAsyncFailure",
"metricName": "StatefulRunAsyncFailure",
"metricValue": "1.0"
},
{
"type": "metadata",
"metadata": "metric",
"include": "ProviderName == Microsoft-ServiceFabric-Services && EventName == StatefulRunAsyncInvocation",
"metricName": "StatefulRunAsyncInvocation",
"metricValue": "1.0"
},
{
"type": "metadata",
"metadata": "metric",
"include": "ProviderName == MyCompany-AirTrafficControlApplication-Frontend && EventName == RestApiOperationStop",
"metricName": "FrontendOperationDurationMsec",
"metricValueProperty": "durationMsec"
},

// EventSource-based request
{
"type": "metadata",
"metadata": "request",
"include": "ProviderName == MyCompany-AirTrafficControlApplication-Frontend && EventName == RestApiOperationStop",
"requestNameProperty": "operationName",
"durationProperty": "durationMsec",
"isSuccessProperty": "isSuccess"
},

// Performance counter-based metrics
{
"type": "metadata",
"metadata": "metric",
"include": "CounterName == \"% Processor Time\"",
"metricName": "FrontendServiceProcessorTimePercent"
},
{
"type": "metadata",
"metadata": "metric",
"include": "CounterName == \"% Time in GC\"",
"metricName": "FrontendServiceProcessorTimePercent"
},
{
"type": "metadata",
"metadata": "metric",
"include": "CounterName == \"# of Exceps Thrown / sec\"",
"metricName": "FrontendServiceExceptionsThrownPerSecond"
},
{
"type": "metadata",
"metadata": "metric",
"include": "CounterName == \"PrivateBytes\"",
"metricName": "FrontendServiceProcessPrivateBytes"
}
]
},
{
"type": "oms",
"filters": [
{
"type": "metadata",
"metadata": "request",
"include": "ProviderName == MyCompany-AirTrafficControlApplication-Frontend && EventName == RestApiOperationStop",
"requestNameProperty": "operationName",
"durationProperty": "durationMsec",
"returnCode": "httpCode"
}
]
"type": "StdOutput"
}
],

"schema-version": "2016-08-11",

"extensions": [
{
"name": "myFilter",
"type": "filter",
"factory": "MyApplication.Diagnostics.MyFilterFactory, MyApplication.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
}
]
"healthReporter": {
"type": "CsvHealthReporter",
"logFileFolder": ".",
"logFilePrefix": "HealthReportAAABB",
"minReportLevel": "Message",
"throttlingPeriodMsec": "1000",
"singleLogFileMaximumSizeInMBytes": 1,
"logRetentionInDays": 1,
"isDebugMode": false
},
"schema-version": "2016-08-11"
}
Loading

0 comments on commit 4fb15f8

Please sign in to comment.