From facecd5ed7e5938bc2828bfd6283dc2c04185721 Mon Sep 17 00:00:00 2001 From: Andrey Shabarshov Date: Tue, 25 Jul 2023 17:21:06 +0100 Subject: [PATCH] DEEP-14 Interval import implemented. Training dialog added. Logging added --- DeepTrace/Controls/Dialog.razor | 22 +++- DeepTrace/Controls/TrainingDialog.razor | 51 ++++++++ DeepTrace/Data/IntervalDefinition.cs | 2 +- DeepTrace/Data/MLModel1.mbconfig | 73 +++++------ DeepTrace/Data/MLModel1.training.cs | 4 +- DeepTrace/Data/TrainedModelDefinition.cs | 4 +- DeepTrace/DeepTrace.csproj | 2 + DeepTrace/ML/IMLProcessor.cs | 2 +- DeepTrace/ML/MLProcessor.cs | 20 ++- DeepTrace/ML/MedianHelper.cs | 6 +- DeepTrace/Pages/DataSources.razor | 9 +- DeepTrace/Pages/Training.razor | 156 ++++++++++++++++++----- DeepTrace/Program.cs | 10 ++ DeepTrace/appsettings.Development.json | 4 +- DeepTrace/appsettings.json | 6 +- DeepTrace/log4net.config | 63 +++++++++ 16 files changed, 340 insertions(+), 94 deletions(-) create mode 100644 DeepTrace/Controls/TrainingDialog.razor create mode 100644 DeepTrace/log4net.config diff --git a/DeepTrace/Controls/Dialog.razor b/DeepTrace/Controls/Dialog.razor index a8be1ec..fb44cc7 100644 --- a/DeepTrace/Controls/Dialog.razor +++ b/DeepTrace/Controls/Dialog.razor @@ -3,18 +3,32 @@ @Text - @if (AllowCancel) + @if( IsYesNoCancel ) { + Yes + No Cancel } - Ok + else + { + if (AllowCancel) + { + Cancel + } + Ok + } @code { [CascadingParameter] MudDialogInstance? MudDialog { get; set; } - [Parameter] public bool AllowCancel { get; set; } - [Parameter] public string Text { get; set; } = ""; + [Parameter] public bool AllowCancel { get; set; } + [Parameter] public string Text { get; set; } = ""; + [Parameter] public bool IsYesNoCancel { get; set; } = false; void Submit() => MudDialog?.Close(DialogResult.Ok(true)); + void Cancel() => MudDialog?.Cancel(); + + void Yes() => MudDialog?.Close(DialogResult.Ok(true)); + void No() => MudDialog?.Close(DialogResult.Ok(false)); } \ No newline at end of file diff --git a/DeepTrace/Controls/TrainingDialog.razor b/DeepTrace/Controls/TrainingDialog.razor new file mode 100644 index 0000000..e967c91 --- /dev/null +++ b/DeepTrace/Controls/TrainingDialog.razor @@ -0,0 +1,51 @@ +@using DeepTrace.Data; +@using DeepTrace.ML; + + + + + + +

@Text

+ + + +
+ + Ok + +
+@code { + [CascadingParameter] MudDialogInstance? MudDialog { get; set; } + [Parameter] public MLProcessor? Processor { get; set; } + [Parameter] public ModelDefinition? Model { get; set; } + [Parameter] public string Text { get; set; } = ""; + + private string _progressText = ""; + private bool _isTraining = true; + + void Submit() => MudDialog?.Close(DialogResult.Ok(true)); + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (!firstRender || Processor==null || Model==null) + { + return; + } + + await Processor.Train(Model, UpdateProgress); + _isTraining = false; + await InvokeAsync(StateHasChanged); + } + + private async void UpdateProgress(string message) + { + _progressText = message; + await InvokeAsync(StateHasChanged); + } +} \ No newline at end of file diff --git a/DeepTrace/Data/IntervalDefinition.cs b/DeepTrace/Data/IntervalDefinition.cs index f13788b..d6194be 100644 --- a/DeepTrace/Data/IntervalDefinition.cs +++ b/DeepTrace/Data/IntervalDefinition.cs @@ -16,7 +16,7 @@ public string Name { get; set; } = string.Empty; - public List Data { get; set; } + public List Data { get; set; } = new(); } } diff --git a/DeepTrace/Data/MLModel1.mbconfig b/DeepTrace/Data/MLModel1.mbconfig index e226ced..ed29167 100644 --- a/DeepTrace/Data/MLModel1.mbconfig +++ b/DeepTrace/Data/MLModel1.mbconfig @@ -191,50 +191,50 @@ "Version": 0, "Type": "Trial", "TrainerName": "SdcaMaximumEntropyMulti", - "Score": 0.87460317460317472, - "RuntimeInSeconds": 5.47599983215332 - }, - { - "Version": 0, - "Type": "Trial", - "TrainerName": "FastForestOva", - "Score": 0.91460317460317475, - "RuntimeInSeconds": 3.6610000133514404 + "Score": 0.57954545454545447, + "RuntimeInSeconds": 5.3579998016357422 }, { "Version": 0, "Type": "Trial", "TrainerName": "FastTreeOva", - "Score": 0.91460317460317475, - "RuntimeInSeconds": 3.2239999771118164 + "Score": 0.91090909090909089, + "RuntimeInSeconds": 3.3050000667572021 }, { "Version": 0, "Type": "Trial", - "TrainerName": "LbfgsLogisticRegressionOva", - "Score": 0.96035353535353529, - "RuntimeInSeconds": 2.812000036239624 - }, - { - "Version": 0, - "Type": "Trial", - "TrainerName": "SdcaLogisticRegressionOva", - "Score": 0.87460317460317472, - "RuntimeInSeconds": 7.8530001640319824 + "TrainerName": "FastTreeOva", + "Score": 0.96460317460317468, + "RuntimeInSeconds": 3.1909999847412109 }, { "Version": 0, "Type": "Trial", "TrainerName": "LbfgsMaximumEntropyMulti", - "Score": 0.96035353535353529, - "RuntimeInSeconds": 2.3250000476837158 + "Score": 0.95031746031746034, + "RuntimeInSeconds": 2.2969999313354492 }, { "Version": 0, "Type": "Trial", - "TrainerName": "LightGbmMulti", - "Score": 0.91460317460317475, - "RuntimeInSeconds": 2.875 + "TrainerName": "FastForestOva", + "Score": 0.91090909090909089, + "RuntimeInSeconds": 3.9630000591278076 + }, + { + "Version": 0, + "Type": "Trial", + "TrainerName": "SdcaLogisticRegressionOva", + "Score": 0.57954545454545447, + "RuntimeInSeconds": 7.7239999771118164 + }, + { + "Version": 0, + "Type": "Trial", + "TrainerName": "LbfgsLogisticRegressionOva", + "Score": 0.95031746031746034, + "RuntimeInSeconds": 3.937000036239624 } ], "Pipeline": { @@ -311,20 +311,16 @@ "OutputColumnName": "Q1mean" }, "20": { - "OutputColumnNames": [ - "Features" - ], - "InputColumnNames": [ - "Features" - ] - }, - "21": { - "L1Regularization": 1.0, - "L2Regularization": 1.0, + "NumberOfLeaves": 33, + "MinimumExampleCountPerLeaf": 14, + "NumberOfTrees": 4, + "MaximumBinCountPerFeature": 1022, + "FeatureFraction": 0.99999999, + "LearningRate": 0.75792684413443268, "LabelColumnName": "Name", "FeatureColumnName": "Features" }, - "22": { + "21": { "OutputColumnName": "PredictedLabel", "InputColumnName": "PredictedLabel" }, @@ -378,8 +374,7 @@ "FeaturizeText", "Concatenate", "MapValueToKey", - "NormalizeMinMax", - "LbfgsLogisticRegressionOva", + "FastTreeOva", "MapKeyToValue" ] }, diff --git a/DeepTrace/Data/MLModel1.training.cs b/DeepTrace/Data/MLModel1.training.cs index a2ddc91..415036a 100644 --- a/DeepTrace/Data/MLModel1.training.cs +++ b/DeepTrace/Data/MLModel1.training.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.ML.Data; +using Microsoft.ML.Trainers.FastTree; using Microsoft.ML.Trainers; using Microsoft.ML; @@ -54,8 +55,7 @@ namespace DeepTrace .Append(mlContext.Transforms.Text.FeaturizeText(inputColumnName:@"Q5mean",outputColumnName:@"Q5mean")) .Append(mlContext.Transforms.Concatenate(@"Features", new []{@"Q1max",@"Q1avg",@"Q1mean",@"Q2min",@"Q2max",@"Q2avg",@"Q2mean",@"Q3min",@"Q3max",@"Q3avg",@"Q3mean",@"Q4max",@"Q4avg",@"Q4mean",@"Q5min",@"Q5max",@"Q5avg",@"Q5mean"})) .Append(mlContext.Transforms.Conversion.MapValueToKey(outputColumnName:@"Name",inputColumnName:@"Name")) - .Append(mlContext.Transforms.NormalizeMinMax(@"Features", @"Features")) - .Append(mlContext.MulticlassClassification.Trainers.OneVersusAll(binaryEstimator: mlContext.BinaryClassification.Trainers.LbfgsLogisticRegression(new LbfgsLogisticRegressionBinaryTrainer.Options(){L1Regularization=1F,L2Regularization=1F,LabelColumnName=@"Name",FeatureColumnName=@"Features"}), labelColumnName:@"Name")) + .Append(mlContext.MulticlassClassification.Trainers.OneVersusAll(binaryEstimator:mlContext.BinaryClassification.Trainers.FastTree(new FastTreeBinaryTrainer.Options(){NumberOfLeaves=33,MinimumExampleCountPerLeaf=14,NumberOfTrees=4,MaximumBinCountPerFeature=1022,FeatureFraction=0.99999999,LearningRate=0.757926844134433,LabelColumnName=@"Name",FeatureColumnName=@"Features"}),labelColumnName: @"Name")) .Append(mlContext.Transforms.Conversion.MapKeyToValue(outputColumnName:@"PredictedLabel",inputColumnName:@"PredictedLabel")); return pipeline; diff --git a/DeepTrace/Data/TrainedModelDefinition.cs b/DeepTrace/Data/TrainedModelDefinition.cs index 8dde9cb..7ca81b0 100644 --- a/DeepTrace/Data/TrainedModelDefinition.cs +++ b/DeepTrace/Data/TrainedModelDefinition.cs @@ -7,7 +7,7 @@ namespace DeepTrace.Data { [BsonId] public ObjectId? Id { get; set; } - public string Name { get; set; } - public byte[] Value { get; set; } //base64 + public string Name { get; set; } = string.Empty; + public byte[] Value { get; set; } = Array.Empty(); //base64 } } diff --git a/DeepTrace/DeepTrace.csproj b/DeepTrace/DeepTrace.csproj index ac1b184..1636219 100644 --- a/DeepTrace/DeepTrace.csproj +++ b/DeepTrace/DeepTrace.csproj @@ -6,6 +6,8 @@ + + diff --git a/DeepTrace/ML/IMLProcessor.cs b/DeepTrace/ML/IMLProcessor.cs index d96d1f9..37e7acb 100644 --- a/DeepTrace/ML/IMLProcessor.cs +++ b/DeepTrace/ML/IMLProcessor.cs @@ -5,7 +5,7 @@ namespace DeepTrace.ML; public interface IMLProcessor { - Task Train(ModelDefinition modelDef); + Task Train(ModelDefinition modelDef, Action log); byte[] Export(); void Import(byte[] data); string Predict(DataSourceDefinition dataSource); diff --git a/DeepTrace/ML/MLProcessor.cs b/DeepTrace/ML/MLProcessor.cs index 48bea6a..e779253 100644 --- a/DeepTrace/ML/MLProcessor.cs +++ b/DeepTrace/ML/MLProcessor.cs @@ -12,13 +12,21 @@ namespace DeepTrace.ML private EstimatorBuilder _estimatorBuilder = new EstimatorBuilder(); private DataViewSchema? _schema; private ITransformer? _transformer; + private static string _signature = "DeepTrace-Model-v1-" + typeof(MLProcessor).Name; + private readonly ILogger _logger; + + public MLProcessor(ILogger logger) + { + _logger = logger; + } private string Name { get; set; } = "TestModel"; - public async Task Train(ModelDefinition modelDef) + public async Task Train(ModelDefinition modelDef, Action log) { var pipeline = _estimatorBuilder.BuildPipeline(_mlContext, modelDef); var (data, filename) = await MLHelpers.Convert(_mlContext, modelDef); + _mlContext.Log += (_,e) => LogEvents(log, e); try { _schema = data.Schema; @@ -31,7 +39,15 @@ namespace DeepTrace.ML } - private static string _signature = "DeepTrace-Model-v1-"+typeof(MLProcessor).Name; + private void LogEvents(Action log, LoggingEventArgs e) + { + if(e.Kind.ToString() != "Trace") + { + _logger.LogDebug(e.Message); + log(e.Message); + } + + } public byte[] Export() { diff --git a/DeepTrace/ML/MedianHelper.cs b/DeepTrace/ML/MedianHelper.cs index 939b240..b00299d 100644 --- a/DeepTrace/ML/MedianHelper.cs +++ b/DeepTrace/ML/MedianHelper.cs @@ -13,7 +13,7 @@ public static class MedianHelper /// Pivot is selected ranodmly if random number generator is supplied else its selected as last element in the list. /// Reference: Introduction to Algorithms 3rd Edition, Corman et al, pp 171 /// - private static int Partition(this IList list, int start, int end, Random rnd = null) where T : IComparable + private static int Partition(this IList list, int start, int end, Random? rnd = null) where T : IComparable { if (rnd != null) list.Swap(end, rnd.Next(start, end + 1)); @@ -34,11 +34,11 @@ public static class MedianHelper /// Note: specified list would be mutated in the process. /// Reference: Introduction to Algorithms 3rd Edition, Corman et al, pp 216 /// - public static T NthOrderStatistic(this IList list, int n, Random rnd = null) where T : IComparable + public static T NthOrderStatistic(this IList list, int n, Random? rnd = null) where T : IComparable { return NthOrderStatistic(list, n, 0, list.Count - 1, rnd); } - private static T NthOrderStatistic(this IList list, int n, int start, int end, Random rnd) where T : IComparable + private static T NthOrderStatistic(this IList list, int n, int start, int end, Random? rnd) where T : IComparable { while (true) { diff --git a/DeepTrace/Pages/DataSources.razor b/DeepTrace/Pages/DataSources.razor index f30cebe..d5c2db8 100644 --- a/DeepTrace/Pages/DataSources.razor +++ b/DeepTrace/Pages/DataSources.razor @@ -372,6 +372,9 @@ private void HandleTrain() { + if ( DisplayData == null ) + return; + var mlContext = new MLContext(); var dataView = mlContext.Data.LoadFromEnumerable(DisplayData.Series[0].Data.Select(x => new MyTimeSeries(Time: x.TimeStamp, Value: x.Value))); @@ -476,7 +479,7 @@ // -------- Spike detection tutorial --------- - private static void DetectSpike(MLContext mLContext, IDataView dataView, TimeSeries[]? data) + private static void DetectSpike(MLContext mLContext, IDataView dataView, TimeSeries[] data) { string outputColumnName = nameof(IidSpikePrediction.Prediction); string inputColumnName = nameof(TimeSeriesDataTutorial.Value); @@ -521,7 +524,7 @@ class TimeSeriesDataTutorial { public float Value; - + public TimeSeriesDataTutorial(float value) { Value = value; @@ -531,7 +534,7 @@ class IidSpikePrediction { [VectorType(3)] - public double[] Prediction { get; set; } + public double[] Prediction { get; set; } = Array.Empty(); } } diff --git a/DeepTrace/Pages/Training.razor b/DeepTrace/Pages/Training.razor index 25276f7..fffceec 100644 --- a/DeepTrace/Pages/Training.razor +++ b/DeepTrace/Pages/Training.razor @@ -1,4 +1,5 @@ @page "/training" +@using CsvHelper; @using DeepTrace.Data; @using DeepTrace.ML; @using DeepTrace.Services; @@ -7,6 +8,7 @@ @using Microsoft.ML; @using PrometheusAPI; @using System.Text; +@using System.Globalization; @inject PrometheusClient Prometheus @inject IDialogService DialogService @@ -16,6 +18,7 @@ @inject IEstimatorBuilder EstimatorBuilder @inject NavigationManager NavManager @inject IJSRuntime Js +@inject ILogger MLProcessorLogger Training @@ -202,14 +205,14 @@ } } - private ModelForm? _modelForm; - private TimeSeriesData? DisplayData { get; set; } + private ModelForm? _modelForm; private List _dataSources = new(); - private List _modelDefinitions = new() {new()}; + private List _modelDefinitions = new() {new()}; + private DateTime? _minDate; + private DateTime? _maxDate; - private DateTime? _minDate; - private DateTime? _maxDate; - private bool IsAddDisabled => DisplayData==null; + private TimeSeriesData? DisplayData { get; set; } + private bool IsAddDisabled => DisplayData == null; private DateTime? MinDate { @@ -245,9 +248,9 @@ base.OnInitialized(); - var sources = await StorageService.Load(); - var models = await ModelService.Load(); - var trainedModels = await TrainedModelService.Load(); + var sources = await StorageService.Load(); + var models = await ModelService.Load(); + var trainedModels = await TrainedModelService.Load(); IList files = new List(); if (sources.Count > 0) @@ -256,8 +259,8 @@ _modelDefinitions = models; _modelForm.CurrentModel = _modelDefinitions[0]; - var source = _dataSources.FirstOrDefault(x => x.Name == _modelDefinitions[0].DataSource.Name); - _modelForm.DataSource = source ?? _dataSources[0]; + var source = _dataSources.FirstOrDefault(x => x.Name == _modelDefinitions[0].DataSource.Name); + _modelForm.DataSource = source ?? _dataSources[0]; } @@ -293,7 +296,7 @@ } catch (Exception e) { - ShowError(e.Message); + await ShowError(e.Message); return; } @@ -303,20 +306,20 @@ { if (res.Status != StatusType.Success) { - ShowError(res.Error ?? "Error"); + await ShowError(res.Error ?? "Error"); return; } if (res.ResultType != ResultTypeType.Matrix) { - ShowError($"Got {res.ResultType}, but Matrix expected for {def.Query}"); + await ShowError($"Got {res.ResultType}, but Matrix expected for {def.Query}"); return; } var m = res.AsMatrix().Result; if (m == null || m.Length != 1) { - ShowError($"No data returned for {def.Query}"); + await ShowError($"No data returned for {def.Query}"); return; } @@ -335,12 +338,15 @@ private void HandleAddModel() { + if (_modelForm == null) + return; + _modelDefinitions.Add(new()); _modelForm.CurrentModel = _modelDefinitions[^1]; StateHasChanged(); } - private void HandleDeleteModel() + private async Task HandleDeleteModel() { if (_modelDefinitions.Count < 2) { @@ -350,7 +356,7 @@ var pos = _modelDefinitions.IndexOf(_modelForm!.CurrentModel); if (pos < 0) { - ShowError("Not found"); + await ShowError("Not found"); return; } @@ -360,10 +366,10 @@ if (toDelete.Id != null) { - ModelService.Delete(toDelete); + await ModelService.Delete(toDelete); } - StateHasChanged(); + await InvokeAsync(StateHasChanged); } private async Task HandleAddTableContent() @@ -399,11 +405,14 @@ private void ItemHasBeenCommitted(object element) { - Task.Run(async ()=>ModelService.Store(_modelForm!.CurrentModel)); + Task.Run(() => ModelService.Store(_modelForm!.CurrentModel)); } private async Task HandleRefresh() { + if (DisplayData == null) + return; + var previousIntervals = _modelForm!.CurrentModel.IntervalDefinitionList; foreach(var currentInterval in previousIntervals) @@ -415,20 +424,72 @@ // await InvokeAsync(StateHasChanged); } - //Doesn't work + private class ImportedCsv + { + public DateTime Start { get; set; } + public DateTime End { get; set; } + public string Label { get; set; } = ""; + } + private async Task HandleImport(IBrowserFile file) { - var result = new StringBuilder(); - var reader = new StreamReader(file.OpenReadStream(file.Size)); + try + { + await HandleImportInternal(file); + } + catch (Exception e) + { + await ShowError($"Can't import: {e.Message}"); + } + } - while (reader.Peek() >= 0) - result.AppendLine(await reader.ReadLineAsync()); - - result.ToString(); + private async Task HandleImportInternal(IBrowserFile file) + { + if ( _modelForm == null ) + return; + + using var mem = new MemoryStream(); + // https://stackoverflow.com/questions/67066860/blazorinputfile-synchronous-reads-are-not-supported + await file.OpenReadStream(file.Size).CopyToAsync(mem); + mem.Position = 0; + + // var text = Encoding.UTF8.GetString(mem.ToArray()); + + using (var reader = new StreamReader(mem)) + using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) + { + var records = csv.GetRecords(); + + var yes = await YesNo("If you want to replace all intervals click Yes. Click No to append."); + if (yes == null) + return; + + if (yes == true) + _modelForm.CurrentModel.IntervalDefinitionList.Clear(); + + var normalWorkStart = DateTime.MinValue; + foreach( var rec in records) + { + if(normalWorkStart != DateTime.MinValue) + { + var normalWorkEnd = rec.Start - TimeSpan.FromSeconds(1); + if(normalWorkStart("Error", parameters, options); + var d = DialogService.Show("Error", parameters, options); + await d.Result; + } + + private async Task YesNo(string text) + { + var options = new DialogOptions + { + CloseOnEscapeKey = true + }; + var parameters = new DialogParameters(); + parameters.Add(nameof(Controls.Dialog.Text), text); + parameters.Add(nameof(Controls.Dialog.IsYesNoCancel), true); + + var d = DialogService.Show("Query", parameters, options); + var res = await d.Result; + return res?.Data as bool?; } private async Task HandleTrain() { - var mlProcessor = new MLProcessor(); - await mlProcessor.Train(_modelForm!.CurrentModel); + var mlProcessor = new MLProcessor(MLProcessorLogger); + MLProcessorLogger.LogInformation("Training started"); + + var options = new DialogOptions + { + CloseOnEscapeKey = true + }; + var parameters = new DialogParameters(); + parameters.Add(nameof(Controls.TrainingDialog.Text), _modelForm!.CurrentModel.Name); + parameters.Add(nameof(Controls.TrainingDialog.Processor), mlProcessor); + parameters.Add(nameof(Controls.TrainingDialog.Model), _modelForm.CurrentModel); + + var d = DialogService.Show("Training", parameters, options); + var res = await d.Result; + + MLProcessorLogger.LogInformation("Training finished"); var bytes = mlProcessor.Export(); //save to Mongo var trainedModel = new TrainedModelDefinition { - Name = "TrainedModel", + Id = _modelForm!.CurrentModel.Id, + Name = _modelForm!.CurrentModel.Name, Value = bytes }; await TrainedModelService.Store(trainedModel); diff --git a/DeepTrace/Program.cs b/DeepTrace/Program.cs index 20031db..ab23244 100644 --- a/DeepTrace/Program.cs +++ b/DeepTrace/Program.cs @@ -3,9 +3,19 @@ using PrometheusAPI; using MongoDB.Driver; using DeepTrace.Services; using DeepTrace.ML; +using ApexCharts; +using log4net; var builder = WebApplication.CreateBuilder(args); +builder.Services.AddLogging(logging => +{ + logging.ClearProviders(); + GlobalContext.Properties["LOGS_ROOT"] = Environment.GetEnvironmentVariable("LOGS_ROOT") ?? ""; + System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); + logging.AddLog4Net("log4net.config"); +}); + // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); diff --git a/DeepTrace/appsettings.Development.json b/DeepTrace/appsettings.Development.json index 770d3e9..eb962da 100644 --- a/DeepTrace/appsettings.Development.json +++ b/DeepTrace/appsettings.Development.json @@ -2,8 +2,8 @@ "DetailedErrors": true, "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Default": "Trace", + "Microsoft.AspNetCore": "Information" } } } diff --git a/DeepTrace/appsettings.json b/DeepTrace/appsettings.json index 6b73d63..7a0c40d 100644 --- a/DeepTrace/appsettings.json +++ b/DeepTrace/appsettings.json @@ -1,12 +1,12 @@ { "Logging": { "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" + "Default": "Trace", + "Microsoft.AspNetCore": "Information" } }, "AllowedHosts": "*", - + "Connections": { "Prometheus": "http://localhost:9090", "MongoDb": "mongodb://localhost:27017" diff --git a/DeepTrace/log4net.config b/DeepTrace/log4net.config new file mode 100644 index 0000000..b4010c2 --- /dev/null +++ b/DeepTrace/log4net.config @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +