From 5eb6f7bb2db96c8ee11a005a7fb0c2420555a1d7 Mon Sep 17 00:00:00 2001 From: Rafael Lillo Date: Fri, 15 May 2020 09:08:54 +0100 Subject: [PATCH 01/19] Add ravendb store --- MiniProfiler.sln | 1 + docker-compose.yml | 18 ++ .../JsonFormatter.cs | 80 ------ .../MiniProfiler.Providers.RavenDB.csproj | 3 +- .../MiniProfilerIndex.cs | 37 +++ .../MiniProfilerWrapper.cs | 119 +++++++++ .../RavenDbStorage.cs | 249 ++++++++++++++++++ .../RavenMiniProfiler.cs | 97 ------- .../MiniProfiler.Tests/Helpers/TestConfig.cs | 2 + .../MiniProfiler.Tests.csproj | 1 + .../Storage/RavenDbStoreTest.cs | 71 +++++ 11 files changed, 500 insertions(+), 178 deletions(-) create mode 100644 docker-compose.yml delete mode 100644 src/MiniProfiler.Providers.RavenDB/JsonFormatter.cs create mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs create mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs create mode 100644 src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs create mode 100644 tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs diff --git a/MiniProfiler.sln b/MiniProfiler.sln index fea48d739..c0deacc7e 100644 --- a/MiniProfiler.sln +++ b/MiniProfiler.sln @@ -15,6 +15,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{CC4009 nuget.config = nuget.config Readme.md = Readme.md version.json = version.json + docker-compose.yml = docker-compose.yml EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniProfiler", "src\MiniProfiler\MiniProfiler.csproj", "{386222BD-6B6E-480F-A342-8DE1AB516E2C}" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..36e56ecf1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3" +services: + postgres: + image: postgres:alpine + container_name: postgres + ports: + - 5432:5432 + environment: + POSTGRES_PASSWORD: "postgres" + raven: + image: ravendb/ravendb + container_name: raven-db + ports: + - 8080:8080 + environment: + RAVEN_ARGS: '--Setup.Mode=None' + RAVEN_License_Eula_Accepted: 'true' + RAVEN_Security_UnsecuredAccessAllowed: 'PrivateNetwork' \ No newline at end of file diff --git a/src/MiniProfiler.Providers.RavenDB/JsonFormatter.cs b/src/MiniProfiler.Providers.RavenDB/JsonFormatter.cs deleted file mode 100644 index f7794612c..000000000 --- a/src/MiniProfiler.Providers.RavenDB/JsonFormatter.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using Raven.Client.Connection.Profiling; -using Raven.Imports.Newtonsoft.Json; -using Raven.Imports.Newtonsoft.Json.Linq; -using Raven.Json.Linq; - -namespace StackExchange.Profiling.RavenDb -{ - internal static class JsonFormatter - { - public static RequestResultArgs FormatRequest(RequestResultArgs input) - { - return new RequestResultArgs - { - DurationMilliseconds = input.DurationMilliseconds, - At = input.At, - HttpResult = input.HttpResult, - Method = input.Method, - Status = input.Status, - Url = input.Url, - PostedData = FilterData(input.PostedData), - Result = FilterData(input.Result) - }; - } - - private static string FilterData(string result) - { - RavenJToken token; - - try - { - token = RavenJToken.Parse(result); - } - catch (Exception) - { - return result; - } - - Visit(token); - - return token.ToString(Formatting.Indented); - } - - private static void Visit(RavenJToken token) - { - switch (token.Type) - { - case JTokenType.Object: - foreach (var item in (RavenJObject)token) - Visit(item.Value); - - break; - - case JTokenType.Array: - foreach (var items in (RavenJArray)token) - Visit(items); - - break; - - case JTokenType.Constructor: - case JTokenType.Property: - case JTokenType.Comment: - case JTokenType.None: - case JTokenType.Integer: - case JTokenType.Float: - case JTokenType.String: - case JTokenType.Boolean: - case JTokenType.Null: - case JTokenType.Undefined: - case JTokenType.Date: - case JTokenType.Raw: - case JTokenType.Bytes: - break; - - default: - throw new ArgumentOutOfRangeException(token.Type.ToString()); - } - } - } -} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj b/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj index 0948a1036..b8466f70f 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj @@ -10,6 +10,7 @@ - + + \ No newline at end of file diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs new file mode 100644 index 000000000..b06c07432 --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs @@ -0,0 +1,37 @@ +using System.Linq; +using Raven.Client.Documents.Indexes; + +namespace StackExchange.Profiling +{ + /// + /// The MiniProfiler index + /// + public class MiniProfilerIndex : AbstractIndexCreationTask + { + /// + /// + /// + public MiniProfilerIndex() + { + this.Indexes.Add(x => x.User, FieldIndexing.Search); + this.Indexes.Add(x => x.HasUserViewed, FieldIndexing.Search); + this.Indexes.Add(x => x.Started, FieldIndexing.Search); + + Map = docs => from profiler in docs + select new MiniProfiler + { + Id = profiler.ProfileId, + Name = profiler.Name, + Started = profiler.Started, + DurationMilliseconds = profiler.DurationMilliseconds, + MachineName = profiler.MachineName, + CustomLinks = profiler.CustomLinks, + CustomLinksJson = profiler.CustomLinksJson, + Root = profiler.Root, + ClientTimings = profiler.ClientTimings, + User = profiler.User, + HasUserViewed = profiler.HasUserViewed + }; + } + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs new file mode 100644 index 000000000..67ec7869a --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using StackExchange.Profiling.Internal; + +namespace StackExchange.Profiling +{ + public class MiniProfilerWrapper + { + public MiniProfilerWrapper() + { + + } + + public MiniProfilerWrapper(MiniProfiler profiler) + { + ProfileId = profiler.Id; + Name = profiler.Name; + Started = profiler.Started; + DurationMilliseconds = profiler.DurationMilliseconds; + MachineName = profiler.MachineName; + CustomLinks = profiler.CustomLinks; + CustomLinksJson = profiler.CustomLinksJson; + Root = profiler.Root; + ClientTimings = profiler.ClientTimings; + User = profiler.User; + HasUserViewed = profiler.HasUserViewed; + } + + public string Id { get; set; } + + /// + /// Gets or sets the profiler id. + /// Identifies this Profiler so it may be stored/cached. + /// + public Guid ProfileId { get; set; } + + /// + /// Gets or sets a display name for this profiling session. + /// + public string Name { get; set; } + + /// + /// Gets or sets when this profiler was instantiated, in UTC time. + /// + public DateTime Started { get; set; } + + /// + /// Gets the milliseconds, to one decimal place, that this MiniProfiler ran. + /// + public decimal DurationMilliseconds { get; set; } + + /// + /// Gets or sets where this profiler was run. + /// + public string MachineName { get; set; } + + /// + /// Keys are names, values are URLs, allowing additional links to be added to a profiler result, e.g. perhaps a deeper + /// diagnostic page for the current request. + /// + /// + /// Use to easily add a name/url pair to this dictionary. + /// + public Dictionary CustomLinks { get; set; } + + /// + /// JSON used to store Custom Links. Do not touch. + /// + public string CustomLinksJson { get; set; } + + /// + /// Gets or sets the root timing. + /// The first that is created and started when this profiler is instantiated. + /// All other s will be children of this one. + /// + public Timing Root { get; set; } + + /// + /// Gets or sets timings collected from the client + /// + public ClientTimings ClientTimings { get; set; } + + /// + /// Gets or sets a string identifying the user/client that is profiling this request. + /// + /// + /// If this is not set manually at some point, the UserIdProvider implementation will be used; + /// by default, this will be the current request's IP address. + /// + public string User { get; set; } + + /// + /// Returns true when this MiniProfiler has been viewed by the that recorded it. + /// + /// + /// Allows POSTs that result in a redirect to be profiled. implementation + /// will keep a list of all profilers that haven't been fetched down. + /// + public bool HasUserViewed { get; set; } + + public MiniProfiler ToMiniProfiler() + { + return new MiniProfiler + { + Id = ProfileId, + Name = Name, + Started = Started, + DurationMilliseconds = DurationMilliseconds, + MachineName = MachineName, + CustomLinks = CustomLinks, + CustomLinksJson = CustomLinksJson, + Root = Root, + ClientTimings = ClientTimings, + User = User, + HasUserViewed = HasUserViewed + }; + } + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs new file mode 100644 index 000000000..eeb0ebebf --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Raven.Client.Documents; +using Raven.Client.Documents.Conventions; +using Raven.Client.Documents.Linq; +using StackExchange.Profiling.Storage; + +namespace StackExchange.Profiling +{ + /// + /// Understands how to store a to a RavenDb database. + /// + public class RavenDbStorage : IAsyncStorage + { + private readonly IDocumentStore _store; + + /// + /// Returns a new . + /// + /// The . + public RavenDbStorage(IDocumentStore store) + { + _store = store; + store.Conventions.FindCollectionName = type => + { + if (type == typeof(MiniProfilerWrapper)) + { + return nameof(MiniProfiler); + } + + return DocumentConventions.DefaultGetCollectionName(type); + }; + } + + /// + /// Creates indexes for faster querying. + /// + public RavenDbStorage WithIndexCreation() + { + new MiniProfilerIndex() + .Execute(_store); + return this; + } + + /// + /// List the MiniProfiler Ids for the given search criteria. + /// + /// The max number of results + /// Search window start + /// Search window end + /// Result order + /// The list of GUID keys + public IEnumerable List(int maxResults, DateTime? start = null, DateTime? finish = null, + ListResultsOrder orderBy = ListResultsOrder.Descending) + { + using var session = _store.OpenSession(); + + var query = session.Query(); + + if (start.HasValue) + { + query = query.Where(x => x.Started >= start.Value); + } + + if (finish.HasValue) + { + query = query.Where(x => x.Started <= start.Value); + } + + query.Take(maxResults); + + query = orderBy == ListResultsOrder.Descending + ? query.OrderByDescending(x => x.Started) + : query.OrderBy(x => x.Started); + + + return query.Select(x => x.Id).ToList(); + } + + /// + /// Stores to profilers under its ; + /// + /// The to save. + public void Save(MiniProfiler profiler) + { + using var session = _store.OpenSession(); + session.Store(new MiniProfilerWrapper(profiler) ); + session.SaveChanges(); + } + + /// + /// Loads the MiniProfiler identified by 'id' from the database. + /// + /// The profiler ID to load. + /// The loaded . + public MiniProfiler Load(Guid id) + { + using var session = _store.OpenSession(); + return session.Query().FirstOrDefault(x => x.Id == id); + } + + /// + /// Sets a particular profiler session so it is considered "unviewed" + /// + /// The user to set this profiler ID as unviewed for. + /// The profiler ID to set unviewed. + public void SetUnviewed(string user, Guid id) + { + using var session = _store.OpenSession(); + var profile = session.Query().First(x => x.ProfileId == id); + profile.HasUserViewed = false; + session.SaveChanges(); + } + + /// + /// Sets a particular profiler session to "viewed" + /// + /// The user to set this profiler ID as viewed for. + /// The profiler ID to set viewed. + public void SetViewed(string user, Guid id) + { + using var session = _store.OpenSession(); + var profile = session.Query().First(x => x.Id == id); + profile.HasUserViewed = true; + session.SaveChanges(); + } + + /// + /// Returns a list of s that haven't been seen by . + /// + /// User identified by the current . + public List GetUnviewedIds(string user) + { + using var session = _store.OpenSession(); + return session.Query() + .Where(x => x.User == user && !x.HasUserViewed) + .Select(x => x.ProfileId) + .ToList(); + } + + /// + /// Asynchronously returns the MiniProfiler Ids for the given search criteria. + /// + /// The max number of results + /// Search window start + /// Search window end + /// Result order + /// The list of GUID keys + public async Task> ListAsync(int maxResults, DateTime? start = null, DateTime? finish = null, + ListResultsOrder orderBy = ListResultsOrder.Descending) + + { + using var session = _store.OpenAsyncSession(); + + var query = session.Query(); + + if (start.HasValue) + { + query = query.Where(x => x.Started >= start.Value); + } + + if (finish.HasValue) + { + query = query.Where(x => x.Started <= start.Value); + } + + query.Take(maxResults); + + query = orderBy == ListResultsOrder.Descending + ? query.OrderByDescending(x => x.Started) + : query.OrderBy(x => x.Started); + + + return await query.Select(x => x.ProfileId).ToListAsync().ConfigureAwait(false); + } + + /// + /// Asynchronously stores to profilers under its . + /// + /// The to save. + public async Task SaveAsync(MiniProfiler profiler) + { + using var session = _store.OpenAsyncSession(); + await session.StoreAsync(profiler).ConfigureAwait(false); + await session.SaveChangesAsync().ConfigureAwait(false); + } + + /// + /// Loads the MiniProfiler identified by 'id' from the database. + /// + /// The profiler ID to load. + /// The loaded . + public async Task LoadAsync(Guid id) + { + using var session = _store.OpenAsyncSession(); + return (await session.Query() + .FirstOrDefaultAsync(x => x.ProfileId == id) + .ConfigureAwait(false)).ToMiniProfiler(); + } + + /// + /// Asynchronously sets a particular profiler session so it is considered "unviewed" + /// + /// The user to set this profiler ID as unviewed for. + /// The profiler ID to set unviewed. + public async Task SetUnviewedAsync(string user, Guid id) + { + using var session = _store.OpenAsyncSession(); + var profile = await session.Query().FirstAsync(x => x.ProfileId == id).ConfigureAwait(false); + profile.HasUserViewed = false; + await session.SaveChangesAsync().ConfigureAwait(false); + } + + /// + /// Asynchronously sets a particular profiler session to "viewed" + /// + /// The user to set this profiler ID as viewed for. + /// The profiler ID to set viewed. + public async Task SetViewedAsync(string user, Guid id) + { + using var session = _store.OpenAsyncSession(); + var profile = await session.Query().FirstAsync(x => x.ProfileId == id).ConfigureAwait(false); + profile.HasUserViewed = true; + await session.SaveChangesAsync().ConfigureAwait(false); + } + + /// + /// Asynchronously returns a list of s that haven't been seen by . + /// + /// User identified by the current . + public async Task> GetUnviewedIdsAsync(string user) + { + using var session = _store.OpenAsyncSession(); + return await session.Query() + .Where(x => x.User == user && !x.HasUserViewed) + .Select(x => x.ProfileId) + .ToListAsync() + .ConfigureAwait(false); + } + + /// + /// Returns the . + /// + /// + public IDocumentStore GetDocumentStore() => _store; + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs b/src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs index 86d858d39..e69de29bb 100644 --- a/src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs +++ b/src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs @@ -1,97 +0,0 @@ -using System; -using System.Text; -using System.Text.RegularExpressions; - -using Raven.Client; -using Raven.Client.Connection.Profiling; -using StackExchange.Profiling.Internal; - -namespace StackExchange.Profiling.RavenDb -{ - /// - /// MiniProfiler RavenDB support - /// - public static class MiniProfilerRaven - { - private static readonly Regex IndexQueryPattern = new Regex("/indexes/([A-Za-z/]+)"); - - /// - /// Initialize MiniProfilerRaven for the given DocumentStore (only call once!) - /// - /// The to attach to - public static IDocumentStore AddMiniProfiler(this IDocumentStore store) - { - if (store?.HasJsonRequestFactory ?? false) - { - // TODO: MiniProfiler 4.1 release - // Note: this is a terrible approach - it logs the endpoint in relation to - // the tree position as-of the end of the request. This may be incorrect, and the - // start position is at best calculated. We'll need to research if there's a better way - // to hook into profiling here. The built-in profiling is all-or-nothing session based - // but may still be the best (or only) available (correct) option. - store.JsonRequestFactory.LogRequest += (sender, args) => - { - var profiler = MiniProfiler.Current; - var head = profiler?.Head; - if (head != null) - { - var formattedRequest = JsonFormatter.FormatRequest(args); - var duration = (decimal)formattedRequest.DurationMilliseconds; - - head.AddCustomTiming("raven", new CustomTiming(profiler, BuildCommandString(formattedRequest)) - { - Id = Guid.NewGuid(), - StartMilliseconds = Math.Max(head.StartMilliseconds - duration, 0), - DurationMilliseconds = duration, - FirstFetchDurationMilliseconds = duration, - ExecuteType = formattedRequest.Status.ToString() - }); - } - }; - } - - return store; - } - - private static string BuildCommandString(RequestResultArgs request) - { - var uri = new Uri(request.Url); - - var sb = new StringBuilder(); - // Basic request information - // HTTP GET - 200 (Cached) - sb.AppendFormat("HTTP {0} - {1} ({2})\n", - request.Method, - request.HttpResult, - request.Status); - - // Request URL - sb.AppendFormat("{0}://{1}{2}\n\n", uri.Scheme, uri.Authority, uri.AbsolutePath); - // Append query - if (uri.Query.HasValue()) - { - var match = IndexQueryPattern.Match(uri.AbsolutePath); - if (match.Success) - { - string index = match.Groups[1].Value; - if (index.HasValue()) - sb.Append("index=").AppendLine(index); - } - if (uri.Query.Length > 1) - { - var qsValues = Uri.UnescapeDataString(uri.Query.Substring(1).Replace("&", "\n").Trim()); - sb.AppendLine(qsValues); - } - } - - // Append POSTed data, if any (multi-get, PATCH, etc.) - if (request.PostedData.HasValue()) - { - sb.Append(request.PostedData); - } - - // Set the command string to a formatted string - return sb.ToString(); - } - } -} diff --git a/tests/MiniProfiler.Tests/Helpers/TestConfig.cs b/tests/MiniProfiler.Tests/Helpers/TestConfig.cs index 7fffbd7a3..32bb650a2 100644 --- a/tests/MiniProfiler.Tests/Helpers/TestConfig.cs +++ b/tests/MiniProfiler.Tests/Helpers/TestConfig.cs @@ -38,6 +38,8 @@ public class Config public string MySQLConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(MySQLConnectionString)) ?? "server=localhost;uid=root;pwd=root;database=test;Allow User Variables=true;SslMode=none"; public string PostgreSqlConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(PostgreSqlConnectionString)) ?? "Server=localhost;Port=5432;Database=test;User Id=postgres;Password=postgres;"; public string MongoDbConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(MongoDbConnectionString)) ?? "mongodb://localhost:27017/test"; + public string RavenDbUrls { get; set; } = Environment.GetEnvironmentVariable(nameof(RavenDbUrls)) ?? "http://localhost:8080"; + public string RavenDatabase { get; set; } = Environment.GetEnvironmentVariable(nameof(RavenDatabase)) ?? "test"; } } } diff --git a/tests/MiniProfiler.Tests/MiniProfiler.Tests.csproj b/tests/MiniProfiler.Tests/MiniProfiler.Tests.csproj index 3a2500296..5dab6fdef 100644 --- a/tests/MiniProfiler.Tests/MiniProfiler.Tests.csproj +++ b/tests/MiniProfiler.Tests/MiniProfiler.Tests.csproj @@ -8,6 +8,7 @@ + diff --git a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs new file mode 100644 index 000000000..abda40d76 --- /dev/null +++ b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs @@ -0,0 +1,71 @@ +using System; +using Raven.Client.Documents; +using Raven.Client.Documents.Operations; +using Raven.Client.Exceptions; +using Raven.Client.Exceptions.Database; +using Raven.Client.ServerWide; +using Raven.Client.ServerWide.Operations; +using Xunit; +using Xunit.Abstractions; + +namespace StackExchange.Profiling.Tests.Storage +{ + public class RavenDbStoreTest : StorageBaseTest, IClassFixture + { + public RavenDbStoreTest(RavenDbStoreFixture fixture, ITestOutputHelper output) + : base(fixture, output) + { + } + } + + public class RavenDbStoreFixture : StorageFixtureBase, IDisposable + { + public RavenDbStoreFixture() + { + Skip.IfNoConfig(nameof(TestConfig.Current.RavenDbUrls), TestConfig.Current.RavenDbUrls); + Skip.IfNoConfig(nameof(TestConfig.Current.RavenDatabase), TestConfig.Current.RavenDatabase); + + try + { + var store = new DocumentStore + { + Urls = TestConfig.Current.RavenDbUrls.Split(';'), Database = TestConfig.Current.RavenDatabase + }; + + Storage = new RavenDbStorage(store);//.WithIndexCreation(); + + store.Initialize(); + + try + { + store.Maintenance.ForDatabase(TestConfig.Current.RavenDatabase).Send(new GetStatisticsOperation()); + } + catch (DatabaseDoesNotExistException) + { + try + { + store.Maintenance.Server.Send(new CreateDatabaseOperation(new DatabaseRecord(TestConfig.Current.RavenDatabase))); + } + catch (ConcurrencyException) + { + // The database was already created before calling CreateDatabaseOperation + } + } + + Storage.GetUnviewedIds(""); + } + catch (Exception e) + { + e.MaybeLog(TestConfig.Current.RavenDbUrls); + e.MaybeLog(TestConfig.Current.RavenDatabase); + ShouldSkip = true; + SkipReason = e.Message; + } + } + + + public void Dispose() + { + } + } +} From e3f8e77652ae9432e0e07d9d55af0873012ec7a6 Mon Sep 17 00:00:00 2001 From: Rafael Lillo Date: Fri, 15 May 2020 20:36:35 +0100 Subject: [PATCH 02/19] Fixes error to execute test --- .../MiniProfilerIdIndex.cs | 27 +++++ .../MiniProfilerIndex.cs | 37 ------ .../MiniProfilerWrapper.cs | 2 +- .../RavenDbStorage.cs | 110 ++++++++++++++---- .../Storage/RavenDbStoreTest.cs | 29 ++++- 5 files changed, 142 insertions(+), 63 deletions(-) create mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs delete mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs new file mode 100644 index 000000000..7b1310808 --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs @@ -0,0 +1,27 @@ +using System.Linq; +using Raven.Client.Documents.Indexes; + +namespace StackExchange.Profiling +{ + /// + /// The MiniProfiler index + /// + public class MiniProfilerIdIndex : AbstractIndexCreationTask + { + /// + /// + /// + public MiniProfilerIdIndex() + { + this.Indexes.Add(x => x.User, FieldIndexing.Search); + this.Indexes.Add(x => x.HasUserViewed, FieldIndexing.Search); + this.Indexes.Add(x => x.Started, FieldIndexing.Search); + + Map = docs => from profiler in docs + select new + { + profiler.ProfileId, + }; + } + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs deleted file mode 100644 index b06c07432..000000000 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerIndex.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Linq; -using Raven.Client.Documents.Indexes; - -namespace StackExchange.Profiling -{ - /// - /// The MiniProfiler index - /// - public class MiniProfilerIndex : AbstractIndexCreationTask - { - /// - /// - /// - public MiniProfilerIndex() - { - this.Indexes.Add(x => x.User, FieldIndexing.Search); - this.Indexes.Add(x => x.HasUserViewed, FieldIndexing.Search); - this.Indexes.Add(x => x.Started, FieldIndexing.Search); - - Map = docs => from profiler in docs - select new MiniProfiler - { - Id = profiler.ProfileId, - Name = profiler.Name, - Started = profiler.Started, - DurationMilliseconds = profiler.DurationMilliseconds, - MachineName = profiler.MachineName, - CustomLinks = profiler.CustomLinks, - CustomLinksJson = profiler.CustomLinksJson, - Root = profiler.Root, - ClientTimings = profiler.ClientTimings, - User = profiler.User, - HasUserViewed = profiler.HasUserViewed - }; - } - } -} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs index 67ec7869a..aa4f5c8a8 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs @@ -4,7 +4,7 @@ namespace StackExchange.Profiling { - public class MiniProfilerWrapper + public class MiniProfilerWrapper { public MiniProfilerWrapper() { diff --git a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs index eeb0ebebf..c54725dbb 100644 --- a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs +++ b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Raven.Client.Documents; using Raven.Client.Documents.Conventions; using Raven.Client.Documents.Linq; +using Raven.Client.Documents.Session; using StackExchange.Profiling.Storage; namespace StackExchange.Profiling @@ -15,15 +17,31 @@ namespace StackExchange.Profiling public class RavenDbStorage : IAsyncStorage { private readonly IDocumentStore _store; + private readonly bool _waitForReplication; + private readonly bool _waitForIndexes; /// /// Returns a new . /// - /// The . - public RavenDbStorage(IDocumentStore store) + /// The ravenDb Urls + /// The ravenDb Database + /// The identifier for store + /// The client certificate to use for authentication + /// If it should wait for Indexes after Save changes + /// If it should wait for replication after Save changes + public RavenDbStorage(string[] urls, string database, string identifier = "mini-profiler", + X509Certificate2 certificate = null, bool waitForIndexes = false, bool waitForReplication = false) { - _store = store; - store.Conventions.FindCollectionName = type => + _waitForReplication = waitForReplication; + _waitForIndexes = waitForIndexes; + _store = new DocumentStore + { + Urls = urls, + Database = database, + Identifier = identifier, + Certificate = certificate + }; + _store.Conventions.FindCollectionName = type => { if (type == typeof(MiniProfilerWrapper)) { @@ -32,14 +50,16 @@ public RavenDbStorage(IDocumentStore store) return DocumentConventions.DefaultGetCollectionName(type); }; + _store.Initialize(); } + /// /// Creates indexes for faster querying. /// public RavenDbStorage WithIndexCreation() { - new MiniProfilerIndex() + new MiniProfilerIdIndex() .Execute(_store); return this; } @@ -55,9 +75,12 @@ public RavenDbStorage WithIndexCreation() public IEnumerable List(int maxResults, DateTime? start = null, DateTime? finish = null, ListResultsOrder orderBy = ListResultsOrder.Descending) { - using var session = _store.OpenSession(); + using var session = _store.OpenSession(new SessionOptions + { + NoTracking = true + }); - var query = session.Query(); + var query = session.Query(); if (start.HasValue) { @@ -76,9 +99,35 @@ public IEnumerable List(int maxResults, DateTime? start = null, DateTime? : query.OrderBy(x => x.Started); - return query.Select(x => x.Id).ToList(); + return query.Select(x => x.ProfileId).ToList(); + } + + private void ConfigureWait(IDocumentSession session) + { + if (_waitForIndexes) + { + session.Advanced.WaitForIndexesAfterSaveChanges(throwOnTimeout: false); + } + + if (_waitForReplication) + { + session.Advanced.WaitForReplicationAfterSaveChanges(throwOnTimeout: false); + } } + + private void ConfigureWait(IAsyncDocumentSession session) + { + if (_waitForIndexes) + { + session.Advanced.WaitForIndexesAfterSaveChanges(throwOnTimeout: false); + } + if (_waitForReplication) + { + session.Advanced.WaitForReplicationAfterSaveChanges(throwOnTimeout: false); + } + } + /// /// Stores to profilers under its ; /// @@ -86,7 +135,8 @@ public IEnumerable List(int maxResults, DateTime? start = null, DateTime? public void Save(MiniProfiler profiler) { using var session = _store.OpenSession(); - session.Store(new MiniProfilerWrapper(profiler) ); + ConfigureWait(session); + session.Store(new MiniProfilerWrapper(profiler)); session.SaveChanges(); } @@ -97,8 +147,11 @@ public void Save(MiniProfiler profiler) /// The loaded . public MiniProfiler Load(Guid id) { - using var session = _store.OpenSession(); - return session.Query().FirstOrDefault(x => x.Id == id); + using var session = _store.OpenSession(new SessionOptions + { + NoTracking = true + }); + return session.Query().FirstOrDefault(x => x.ProfileId == id)?.ToMiniProfiler(); } /// @@ -109,6 +162,8 @@ public MiniProfiler Load(Guid id) public void SetUnviewed(string user, Guid id) { using var session = _store.OpenSession(); + ConfigureWait(session); + var profile = session.Query().First(x => x.ProfileId == id); profile.HasUserViewed = false; session.SaveChanges(); @@ -122,7 +177,8 @@ public void SetUnviewed(string user, Guid id) public void SetViewed(string user, Guid id) { using var session = _store.OpenSession(); - var profile = session.Query().First(x => x.Id == id); + ConfigureWait(session); + var profile = session.Query().First(x => x.ProfileId == id); profile.HasUserViewed = true; session.SaveChanges(); } @@ -133,7 +189,10 @@ public void SetViewed(string user, Guid id) /// User identified by the current . public List GetUnviewedIds(string user) { - using var session = _store.OpenSession(); + using var session = _store.OpenSession(new SessionOptions + { + NoTracking = true + }); return session.Query() .Where(x => x.User == user && !x.HasUserViewed) .Select(x => x.ProfileId) @@ -148,11 +207,12 @@ public List GetUnviewedIds(string user) /// Search window end /// Result order /// The list of GUID keys - public async Task> ListAsync(int maxResults, DateTime? start = null, DateTime? finish = null, - ListResultsOrder orderBy = ListResultsOrder.Descending) - + public async Task> ListAsync(int maxResults, DateTime? start = null, DateTime? finish = null, ListResultsOrder orderBy = ListResultsOrder.Descending) { - using var session = _store.OpenAsyncSession(); + using var session = _store.OpenAsyncSession(new SessionOptions + { + NoTracking = true + }); var query = session.Query(); @@ -183,7 +243,8 @@ public async Task> ListAsync(int maxResults, DateTime? start = public async Task SaveAsync(MiniProfiler profiler) { using var session = _store.OpenAsyncSession(); - await session.StoreAsync(profiler).ConfigureAwait(false); + ConfigureWait(session); + await session.StoreAsync(new MiniProfilerWrapper(profiler)).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); } @@ -194,7 +255,10 @@ public async Task SaveAsync(MiniProfiler profiler) /// The loaded . public async Task LoadAsync(Guid id) { - using var session = _store.OpenAsyncSession(); + using var session = _store.OpenAsyncSession(new SessionOptions + { + NoTracking = true + }); return (await session.Query() .FirstOrDefaultAsync(x => x.ProfileId == id) .ConfigureAwait(false)).ToMiniProfiler(); @@ -208,6 +272,7 @@ public async Task LoadAsync(Guid id) public async Task SetUnviewedAsync(string user, Guid id) { using var session = _store.OpenAsyncSession(); + ConfigureWait(session); var profile = await session.Query().FirstAsync(x => x.ProfileId == id).ConfigureAwait(false); profile.HasUserViewed = false; await session.SaveChangesAsync().ConfigureAwait(false); @@ -221,6 +286,7 @@ public async Task SetUnviewedAsync(string user, Guid id) public async Task SetViewedAsync(string user, Guid id) { using var session = _store.OpenAsyncSession(); + ConfigureWait(session); var profile = await session.Query().FirstAsync(x => x.ProfileId == id).ConfigureAwait(false); profile.HasUserViewed = true; await session.SaveChangesAsync().ConfigureAwait(false); @@ -232,7 +298,11 @@ public async Task SetViewedAsync(string user, Guid id) /// User identified by the current . public async Task> GetUnviewedIdsAsync(string user) { - using var session = _store.OpenAsyncSession(); + using var session = _store.OpenAsyncSession(new SessionOptions + { + NoTracking = true + }); + return await session.Query() .Where(x => x.User == user && !x.HasUserViewed) .Select(x => x.ProfileId) diff --git a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs index abda40d76..f2a96d578 100644 --- a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs +++ b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs @@ -31,11 +31,9 @@ public RavenDbStoreFixture() { Urls = TestConfig.Current.RavenDbUrls.Split(';'), Database = TestConfig.Current.RavenDatabase }; - - Storage = new RavenDbStorage(store);//.WithIndexCreation(); - - store.Initialize(); + store.Initialize(); + try { store.Maintenance.ForDatabase(TestConfig.Current.RavenDatabase).Send(new GetStatisticsOperation()); @@ -52,6 +50,11 @@ public RavenDbStoreFixture() } } + store.Dispose(); + store = null; + + Storage = new RavenDbStorage(TestConfig.Current.RavenDbUrls.Split(';'), TestConfig.Current.RavenDatabase, waitForIndexes: true); + Storage.WithIndexCreation(); Storage.GetUnviewedIds(""); } catch (Exception e) @@ -63,9 +66,25 @@ public RavenDbStoreFixture() } } - public void Dispose() { + if (!ShouldSkip) + { + Storage.DropDatabase(); + } + } + } + + public static class RavenDbDbStorageExtensions + { + /// + /// Drop database for RavenDB storage. + /// + /// The storage to drop schema for. + public static void DropDatabase(this RavenDbStorage storage) + { + var store = storage.GetDocumentStore(); + store.Maintenance.Server.Send(new DeleteDatabasesOperation(store.Database, true)); } } } From 8820be152ca688a1a1ee0cb6ef17118aa8df5e6c Mon Sep 17 00:00:00 2001 From: Rafael Lillo Date: Fri, 15 May 2020 22:28:15 +0100 Subject: [PATCH 03/19] Remove RavenMiniProfiler and README.md --- src/MiniProfiler.Providers.RavenDB/README.md | 18 ------------------ .../RavenMiniProfiler.cs | 0 2 files changed, 18 deletions(-) delete mode 100644 src/MiniProfiler.Providers.RavenDB/README.md delete mode 100644 src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs diff --git a/src/MiniProfiler.Providers.RavenDB/README.md b/src/MiniProfiler.Providers.RavenDB/README.md deleted file mode 100644 index 7baac028e..000000000 --- a/src/MiniProfiler.Providers.RavenDB/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# MiniProfiler for RavenDB - -This package allows you to profile your RavenDB requests using MiniProfiler. - -Simply call `MiniProfilerRaven.InitializeFor(store)` when you initialize -your Raven `DocumentStore` (please note that `EmbeddableDocumentStore` is not supported). - -```c# -var store = new DocumentStore(); -store.Initialize(); - -// Initialize MiniProfiler -MiniProfilerRaven.InitializeFor(store); -``` - -A new column will appear on MiniProfiler that provides detail on your Raven requests, including `POST`ed data. - -All of the existing settings and functionality of MiniProfiler can be taken advantage of. \ No newline at end of file diff --git a/src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs b/src/MiniProfiler.Providers.RavenDB/RavenMiniProfiler.cs deleted file mode 100644 index e69de29bb..000000000 From 855f33b310bec45548c7bed6dda7e387cc3731c5 Mon Sep 17 00:00:00 2001 From: Rafael Lillo Date: Sun, 17 May 2020 12:23:29 +0100 Subject: [PATCH 04/19] Use index and fixes query --- .../MiniProfilerIdIndex.cs | 27 ---------- ...iProfilerWrapper_ByHasUserViewedAndUser.cs | 24 +++++++++ .../MiniProfilerWrapper_ByProfileId.cs | 23 ++++++++ .../MiniProfilerWrapper_ByStarted.cs | 23 ++++++++ .../RavenDbStorage.cs | 54 +++++++++++++------ .../Storage/RavenDbStoreTest.cs | 1 - 6 files changed, 108 insertions(+), 44 deletions(-) delete mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs create mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs create mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs create mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs deleted file mode 100644 index 7b1310808..000000000 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerIdIndex.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Linq; -using Raven.Client.Documents.Indexes; - -namespace StackExchange.Profiling -{ - /// - /// The MiniProfiler index - /// - public class MiniProfilerIdIndex : AbstractIndexCreationTask - { - /// - /// - /// - public MiniProfilerIdIndex() - { - this.Indexes.Add(x => x.User, FieldIndexing.Search); - this.Indexes.Add(x => x.HasUserViewed, FieldIndexing.Search); - this.Indexes.Add(x => x.Started, FieldIndexing.Search); - - Map = docs => from profiler in docs - select new - { - profiler.ProfileId, - }; - } - } -} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs new file mode 100644 index 000000000..7e3f12a3d --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs @@ -0,0 +1,24 @@ +using System.Linq; +using Raven.Client.Documents.Indexes; + +namespace StackExchange.Profiling +{ + /// + /// The MiniProfiler index + /// + public class MiniProfilerWrapper_ByHasUserViewedAndUser : AbstractIndexCreationTask + { + /// + /// + /// + public MiniProfilerWrapper_ByHasUserViewedAndUser() + { + Map = docs => from profiler in docs + select new + { + profiler.HasUserViewed, + profiler.User + }; + } + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs new file mode 100644 index 000000000..58360b5ef --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs @@ -0,0 +1,23 @@ +using System.Linq; +using Raven.Client.Documents.Indexes; + +namespace StackExchange.Profiling +{ + /// + /// The MiniProfiler index + /// + public class MiniProfilerWrapper_ByProfileId : AbstractIndexCreationTask + { + /// + /// + /// + public MiniProfilerWrapper_ByProfileId() + { + Map = docs => from profiler in docs + select new + { + profiler.ProfileId + }; + } + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs new file mode 100644 index 000000000..1c558d72d --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs @@ -0,0 +1,23 @@ +using System.Linq; +using Raven.Client.Documents.Indexes; + +namespace StackExchange.Profiling +{ + /// + /// The MiniProfiler index + /// + public class MiniProfilerWrapper_ByStarted : AbstractIndexCreationTask + { + /// + /// + /// + public MiniProfilerWrapper_ByStarted() + { + Map = docs => from profiler in docs + select new + { + profiler.Started + }; + } + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs index c54725dbb..e50b05f66 100644 --- a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs +++ b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs @@ -51,6 +51,7 @@ public RavenDbStorage(string[] urls, string database, string identifier = "mini- return DocumentConventions.DefaultGetCollectionName(type); }; _store.Initialize(); + WithIndexCreation(); } @@ -59,8 +60,15 @@ public RavenDbStorage(string[] urls, string database, string identifier = "mini- /// public RavenDbStorage WithIndexCreation() { - new MiniProfilerIdIndex() + new MiniProfilerWrapper_ByProfileId() .Execute(_store); + + new MiniProfilerWrapper_ByHasUserViewedAndUser() + .Execute(_store); + + new MiniProfilerWrapper_ByStarted() + .Execute(_store); + return this; } @@ -80,7 +88,7 @@ public IEnumerable List(int maxResults, DateTime? start = null, DateTime? NoTracking = true }); - var query = session.Query(); + var query = session.Query(); if (start.HasValue) { @@ -89,7 +97,7 @@ public IEnumerable List(int maxResults, DateTime? start = null, DateTime? if (finish.HasValue) { - query = query.Where(x => x.Started <= start.Value); + query = query.Where(x => x.Started <= finish.Value); } query.Take(maxResults); @@ -151,7 +159,8 @@ public MiniProfiler Load(Guid id) { NoTracking = true }); - return session.Query().FirstOrDefault(x => x.ProfileId == id)?.ToMiniProfiler(); + return session.Query() + .FirstOrDefault(x => x.ProfileId == id)?.ToMiniProfiler(); } /// @@ -164,7 +173,8 @@ public void SetUnviewed(string user, Guid id) using var session = _store.OpenSession(); ConfigureWait(session); - var profile = session.Query().First(x => x.ProfileId == id); + var profile = session.Query() + .First(x => x.ProfileId == id); profile.HasUserViewed = false; session.SaveChanges(); } @@ -178,7 +188,8 @@ public void SetViewed(string user, Guid id) { using var session = _store.OpenSession(); ConfigureWait(session); - var profile = session.Query().First(x => x.ProfileId == id); + var profile = session.Query() + .First(x => x.ProfileId == id); profile.HasUserViewed = true; session.SaveChanges(); } @@ -193,8 +204,8 @@ public List GetUnviewedIds(string user) { NoTracking = true }); - return session.Query() - .Where(x => x.User == user && !x.HasUserViewed) + return session.Query() + .Where(x => !x.HasUserViewed && x.User == user) .Select(x => x.ProfileId) .ToList(); } @@ -214,7 +225,7 @@ public async Task> ListAsync(int maxResults, DateTime? start = NoTracking = true }); - var query = session.Query(); + var query = session.Query(); if (start.HasValue) { @@ -223,7 +234,7 @@ public async Task> ListAsync(int maxResults, DateTime? start = if (finish.HasValue) { - query = query.Where(x => x.Started <= start.Value); + query = query.Where(x => x.Started <= finish.Value); } query.Take(maxResults); @@ -233,7 +244,10 @@ public async Task> ListAsync(int maxResults, DateTime? start = : query.OrderBy(x => x.Started); - return await query.Select(x => x.ProfileId).ToListAsync().ConfigureAwait(false); + return await query + .Select(x => x.ProfileId) + .ToListAsync() + .ConfigureAwait(false); } /// @@ -259,7 +273,7 @@ public async Task LoadAsync(Guid id) { NoTracking = true }); - return (await session.Query() + return (await session.Query() .FirstOrDefaultAsync(x => x.ProfileId == id) .ConfigureAwait(false)).ToMiniProfiler(); } @@ -273,7 +287,11 @@ public async Task SetUnviewedAsync(string user, Guid id) { using var session = _store.OpenAsyncSession(); ConfigureWait(session); - var profile = await session.Query().FirstAsync(x => x.ProfileId == id).ConfigureAwait(false); + + var profile = await session.Query() + .FirstAsync(x => x.ProfileId == id) + .ConfigureAwait(false); + profile.HasUserViewed = false; await session.SaveChangesAsync().ConfigureAwait(false); } @@ -287,7 +305,11 @@ public async Task SetViewedAsync(string user, Guid id) { using var session = _store.OpenAsyncSession(); ConfigureWait(session); - var profile = await session.Query().FirstAsync(x => x.ProfileId == id).ConfigureAwait(false); + + var profile = await session.Query() + .FirstAsync(x => x.ProfileId == id) + .ConfigureAwait(false); + profile.HasUserViewed = true; await session.SaveChangesAsync().ConfigureAwait(false); } @@ -303,8 +325,8 @@ public async Task> GetUnviewedIdsAsync(string user) NoTracking = true }); - return await session.Query() - .Where(x => x.User == user && !x.HasUserViewed) + return await session.Query() + .Where(x => !x.HasUserViewed && x.User == user) .Select(x => x.ProfileId) .ToListAsync() .ConfigureAwait(false); diff --git a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs index f2a96d578..135dd764b 100644 --- a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs +++ b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs @@ -54,7 +54,6 @@ public RavenDbStoreFixture() store = null; Storage = new RavenDbStorage(TestConfig.Current.RavenDbUrls.Split(';'), TestConfig.Current.RavenDatabase, waitForIndexes: true); - Storage.WithIndexCreation(); Storage.GetUnviewedIds(""); } catch (Exception e) From b25a6b8de4fed68b338e4500f93ee5339332d372 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 20:38:14 -0400 Subject: [PATCH 05/19] Warning cleanup! --- .../MiniProfiler.Providers.RavenDB.csproj | 1 - .../MiniProfilerWrapper.cs | 40 +++++++++---------- ...iProfilerWrapper_ByHasUserViewedAndUser.cs | 4 +- .../MiniProfilerWrapper_ByProfileId.cs | 4 +- .../MiniProfilerWrapper_ByStarted.cs | 4 +- 5 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj b/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj index b8466f70f..a44f762eb 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfiler.Providers.RavenDB.csproj @@ -5,7 +5,6 @@ MiniProfiler: Profilers for RavenDB Marc Gravell, Jarrod Dixon, Yaakov Ellis, Nick Craver Raven;RavenDB;$(PackageBaseTags) - false net461;netstandard2.0 diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs index aa4f5c8a8..2b9a8fd77 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs @@ -1,15 +1,12 @@ -using System; +using System; using System.Collections.Generic; using StackExchange.Profiling.Internal; namespace StackExchange.Profiling { - public class MiniProfilerWrapper + internal class MiniProfilerWrapper { - public MiniProfilerWrapper() - { - - } + public MiniProfilerWrapper() { } public MiniProfilerWrapper(MiniProfiler profiler) { @@ -98,22 +95,21 @@ public MiniProfilerWrapper(MiniProfiler profiler) /// public bool HasUserViewed { get; set; } - public MiniProfiler ToMiniProfiler() +#pragma warning disable CS0618 // Type or member is obsolete + public MiniProfiler ToMiniProfiler() => new MiniProfiler { - return new MiniProfiler - { - Id = ProfileId, - Name = Name, - Started = Started, - DurationMilliseconds = DurationMilliseconds, - MachineName = MachineName, - CustomLinks = CustomLinks, - CustomLinksJson = CustomLinksJson, - Root = Root, - ClientTimings = ClientTimings, - User = User, - HasUserViewed = HasUserViewed - }; - } + Id = ProfileId, + Name = Name, + Started = Started, + DurationMilliseconds = DurationMilliseconds, + MachineName = MachineName, + CustomLinks = CustomLinks, + CustomLinksJson = CustomLinksJson, + Root = Root, + ClientTimings = ClientTimings, + User = User, + HasUserViewed = HasUserViewed + }; +#pragma warning restore CS0618 // Type or member is obsolete } } diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs index 7e3f12a3d..7fb3f1fac 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Raven.Client.Documents.Indexes; namespace StackExchange.Profiling @@ -6,7 +6,7 @@ namespace StackExchange.Profiling /// /// The MiniProfiler index /// - public class MiniProfilerWrapper_ByHasUserViewedAndUser : AbstractIndexCreationTask + internal class MiniProfilerWrapper_ByHasUserViewedAndUser : AbstractIndexCreationTask { /// /// diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs index 58360b5ef..6f6ebcd35 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Raven.Client.Documents.Indexes; namespace StackExchange.Profiling @@ -6,7 +6,7 @@ namespace StackExchange.Profiling /// /// The MiniProfiler index /// - public class MiniProfilerWrapper_ByProfileId : AbstractIndexCreationTask + internal class MiniProfilerWrapper_ByProfileId : AbstractIndexCreationTask { /// /// diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs index 1c558d72d..0044ec77e 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs +++ b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using Raven.Client.Documents.Indexes; namespace StackExchange.Profiling @@ -6,7 +6,7 @@ namespace StackExchange.Profiling /// /// The MiniProfiler index /// - public class MiniProfilerWrapper_ByStarted : AbstractIndexCreationTask + internal class MiniProfilerWrapper_ByStarted : AbstractIndexCreationTask { /// /// From 42a19e575a3affda7af8b207e520cbe0c22a7803 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 21:24:01 -0400 Subject: [PATCH 06/19] Consolidation and naming schemes More closely match the other libraries and namespaces :) --- .../Internal/Indexes.cs | 42 +++++++++++++ .../MiniProfilerDoc.cs} | 14 ++--- ...iProfilerWrapper_ByHasUserViewedAndUser.cs | 24 ------- .../MiniProfilerWrapper_ByProfileId.cs | 23 ------- .../MiniProfilerWrapper_ByStarted.cs | 23 ------- .../RavenDbStorage.cs | 63 +++++++++---------- .../Storage/RavenDbStoreTest.cs | 3 +- 7 files changed, 80 insertions(+), 112 deletions(-) create mode 100644 src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs rename src/MiniProfiler.Providers.RavenDB/{MiniProfilerWrapper.cs => Internal/MiniProfilerDoc.cs} (93%) delete mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs delete mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs delete mode 100644 src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs diff --git a/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs b/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs new file mode 100644 index 000000000..238f33e1e --- /dev/null +++ b/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs @@ -0,0 +1,42 @@ +using System.Linq; +using Raven.Client.Documents.Indexes; + +namespace StackExchange.Profiling.Storage.Internal +{ + /// + /// The MiniProfiler index by user for has viewed + /// + internal class Index_ByHasUserViewedAndUser : AbstractIndexCreationTask + { + public Index_ByHasUserViewedAndUser() => Map = docs => from profiler in docs + select new + { + profiler.HasUserViewed, + profiler.User + }; + } + + /// + /// The MiniProfiler index by profiler Id + /// + internal class Index_ByProfilerId : AbstractIndexCreationTask + { + public Index_ByProfilerId() => Map = docs => from profiler in docs + select new + { + profiler.ProfilerId + }; + } + + /// + /// The MiniProfiler index by start time + /// + internal class Index_ByStarted : AbstractIndexCreationTask + { + public Index_ByStarted() => Map = docs => from profiler in docs + select new + { + profiler.Started + }; + } +} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs b/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs similarity index 93% rename from src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs rename to src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs index 2b9a8fd77..ad70f9c82 100644 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper.cs +++ b/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs @@ -2,15 +2,15 @@ using System.Collections.Generic; using StackExchange.Profiling.Internal; -namespace StackExchange.Profiling +namespace StackExchange.Profiling.Storage.Internal { - internal class MiniProfilerWrapper + internal class MiniProfilerDoc { - public MiniProfilerWrapper() { } + public MiniProfilerDoc() { } - public MiniProfilerWrapper(MiniProfiler profiler) + public MiniProfilerDoc(MiniProfiler profiler) { - ProfileId = profiler.Id; + ProfilerId = profiler.Id; Name = profiler.Name; Started = profiler.Started; DurationMilliseconds = profiler.DurationMilliseconds; @@ -29,7 +29,7 @@ public MiniProfilerWrapper(MiniProfiler profiler) /// Gets or sets the profiler id. /// Identifies this Profiler so it may be stored/cached. /// - public Guid ProfileId { get; set; } + public Guid ProfilerId { get; set; } /// /// Gets or sets a display name for this profiling session. @@ -98,7 +98,7 @@ public MiniProfilerWrapper(MiniProfiler profiler) #pragma warning disable CS0618 // Type or member is obsolete public MiniProfiler ToMiniProfiler() => new MiniProfiler { - Id = ProfileId, + Id = ProfilerId, Name = Name, Started = Started, DurationMilliseconds = DurationMilliseconds, diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs deleted file mode 100644 index 7fb3f1fac..000000000 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByHasUserViewedAndUser.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Linq; -using Raven.Client.Documents.Indexes; - -namespace StackExchange.Profiling -{ - /// - /// The MiniProfiler index - /// - internal class MiniProfilerWrapper_ByHasUserViewedAndUser : AbstractIndexCreationTask - { - /// - /// - /// - public MiniProfilerWrapper_ByHasUserViewedAndUser() - { - Map = docs => from profiler in docs - select new - { - profiler.HasUserViewed, - profiler.User - }; - } - } -} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs deleted file mode 100644 index 6f6ebcd35..000000000 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByProfileId.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using Raven.Client.Documents.Indexes; - -namespace StackExchange.Profiling -{ - /// - /// The MiniProfiler index - /// - internal class MiniProfilerWrapper_ByProfileId : AbstractIndexCreationTask - { - /// - /// - /// - public MiniProfilerWrapper_ByProfileId() - { - Map = docs => from profiler in docs - select new - { - profiler.ProfileId - }; - } - } -} diff --git a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs b/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs deleted file mode 100644 index 0044ec77e..000000000 --- a/src/MiniProfiler.Providers.RavenDB/MiniProfilerWrapper_ByStarted.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using Raven.Client.Documents.Indexes; - -namespace StackExchange.Profiling -{ - /// - /// The MiniProfiler index - /// - internal class MiniProfilerWrapper_ByStarted : AbstractIndexCreationTask - { - /// - /// - /// - public MiniProfilerWrapper_ByStarted() - { - Map = docs => from profiler in docs - select new - { - profiler.Started - }; - } - } -} diff --git a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs index e50b05f66..65a75ffcb 100644 --- a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs +++ b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; @@ -7,9 +7,9 @@ using Raven.Client.Documents.Conventions; using Raven.Client.Documents.Linq; using Raven.Client.Documents.Session; -using StackExchange.Profiling.Storage; +using StackExchange.Profiling.Storage.Internal; -namespace StackExchange.Profiling +namespace StackExchange.Profiling.Storage { /// /// Understands how to store a to a RavenDb database. @@ -43,7 +43,7 @@ public RavenDbStorage(string[] urls, string database, string identifier = "mini- }; _store.Conventions.FindCollectionName = type => { - if (type == typeof(MiniProfilerWrapper)) + if (type == typeof(MiniProfilerDoc)) { return nameof(MiniProfiler); } @@ -60,14 +60,9 @@ public RavenDbStorage(string[] urls, string database, string identifier = "mini- /// public RavenDbStorage WithIndexCreation() { - new MiniProfilerWrapper_ByProfileId() - .Execute(_store); - - new MiniProfilerWrapper_ByHasUserViewedAndUser() - .Execute(_store); - - new MiniProfilerWrapper_ByStarted() - .Execute(_store); + new Index_ByProfilerId().Execute(_store); + new Index_ByHasUserViewedAndUser().Execute(_store); + new Index_ByStarted().Execute(_store); return this; } @@ -88,7 +83,7 @@ public IEnumerable List(int maxResults, DateTime? start = null, DateTime? NoTracking = true }); - var query = session.Query(); + var query = session.Query(); if (start.HasValue) { @@ -107,7 +102,7 @@ public IEnumerable List(int maxResults, DateTime? start = null, DateTime? : query.OrderBy(x => x.Started); - return query.Select(x => x.ProfileId).ToList(); + return query.Select(x => x.ProfilerId).ToList(); } private void ConfigureWait(IDocumentSession session) @@ -144,7 +139,7 @@ public void Save(MiniProfiler profiler) { using var session = _store.OpenSession(); ConfigureWait(session); - session.Store(new MiniProfilerWrapper(profiler)); + session.Store(new MiniProfilerDoc(profiler)); session.SaveChanges(); } @@ -159,8 +154,8 @@ public MiniProfiler Load(Guid id) { NoTracking = true }); - return session.Query() - .FirstOrDefault(x => x.ProfileId == id)?.ToMiniProfiler(); + return session.Query() + .FirstOrDefault(x => x.ProfilerId == id)?.ToMiniProfiler(); } /// @@ -173,8 +168,8 @@ public void SetUnviewed(string user, Guid id) using var session = _store.OpenSession(); ConfigureWait(session); - var profile = session.Query() - .First(x => x.ProfileId == id); + var profile = session.Query() + .First(x => x.ProfilerId == id); profile.HasUserViewed = false; session.SaveChanges(); } @@ -188,8 +183,8 @@ public void SetViewed(string user, Guid id) { using var session = _store.OpenSession(); ConfigureWait(session); - var profile = session.Query() - .First(x => x.ProfileId == id); + var profile = session.Query() + .First(x => x.ProfilerId == id); profile.HasUserViewed = true; session.SaveChanges(); } @@ -204,9 +199,9 @@ public List GetUnviewedIds(string user) { NoTracking = true }); - return session.Query() + return session.Query() .Where(x => !x.HasUserViewed && x.User == user) - .Select(x => x.ProfileId) + .Select(x => x.ProfilerId) .ToList(); } @@ -225,7 +220,7 @@ public async Task> ListAsync(int maxResults, DateTime? start = NoTracking = true }); - var query = session.Query(); + var query = session.Query(); if (start.HasValue) { @@ -245,7 +240,7 @@ public async Task> ListAsync(int maxResults, DateTime? start = return await query - .Select(x => x.ProfileId) + .Select(x => x.ProfilerId) .ToListAsync() .ConfigureAwait(false); } @@ -258,7 +253,7 @@ public async Task SaveAsync(MiniProfiler profiler) { using var session = _store.OpenAsyncSession(); ConfigureWait(session); - await session.StoreAsync(new MiniProfilerWrapper(profiler)).ConfigureAwait(false); + await session.StoreAsync(new MiniProfilerDoc(profiler)).ConfigureAwait(false); await session.SaveChangesAsync().ConfigureAwait(false); } @@ -273,8 +268,8 @@ public async Task LoadAsync(Guid id) { NoTracking = true }); - return (await session.Query() - .FirstOrDefaultAsync(x => x.ProfileId == id) + return (await session.Query() + .FirstOrDefaultAsync(x => x.ProfilerId == id) .ConfigureAwait(false)).ToMiniProfiler(); } @@ -288,8 +283,8 @@ public async Task SetUnviewedAsync(string user, Guid id) using var session = _store.OpenAsyncSession(); ConfigureWait(session); - var profile = await session.Query() - .FirstAsync(x => x.ProfileId == id) + var profile = await session.Query() + .FirstAsync(x => x.ProfilerId == id) .ConfigureAwait(false); profile.HasUserViewed = false; @@ -306,8 +301,8 @@ public async Task SetViewedAsync(string user, Guid id) using var session = _store.OpenAsyncSession(); ConfigureWait(session); - var profile = await session.Query() - .FirstAsync(x => x.ProfileId == id) + var profile = await session.Query() + .FirstAsync(x => x.ProfilerId == id) .ConfigureAwait(false); profile.HasUserViewed = true; @@ -325,9 +320,9 @@ public async Task> GetUnviewedIdsAsync(string user) NoTracking = true }); - return await session.Query() + return await session.Query() .Where(x => !x.HasUserViewed && x.User == user) - .Select(x => x.ProfileId) + .Select(x => x.ProfilerId) .ToListAsync() .ConfigureAwait(false); } diff --git a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs index 135dd764b..4e8a2074a 100644 --- a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs +++ b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs @@ -1,10 +1,11 @@ -using System; +using System; using Raven.Client.Documents; using Raven.Client.Documents.Operations; using Raven.Client.Exceptions; using Raven.Client.Exceptions.Database; using Raven.Client.ServerWide; using Raven.Client.ServerWide.Operations; +using StackExchange.Profiling.Storage; using Xunit; using Xunit.Abstractions; From cd3b6bf1dd54019d43f9cbc61bf408373d128288 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 21:38:21 -0400 Subject: [PATCH 07/19] Formatting --- .../Internal/Indexes.cs | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs b/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs index 238f33e1e..80368bc1a 100644 --- a/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs +++ b/src/MiniProfiler.Providers.RavenDB/Internal/Indexes.cs @@ -8,12 +8,8 @@ namespace StackExchange.Profiling.Storage.Internal /// internal class Index_ByHasUserViewedAndUser : AbstractIndexCreationTask { - public Index_ByHasUserViewedAndUser() => Map = docs => from profiler in docs - select new - { - profiler.HasUserViewed, - profiler.User - }; + public Index_ByHasUserViewedAndUser() => + Map = docs => from profiler in docs select new { profiler.HasUserViewed, profiler.User }; } /// @@ -21,11 +17,8 @@ public Index_ByHasUserViewedAndUser() => Map = docs => from profiler in docs /// internal class Index_ByProfilerId : AbstractIndexCreationTask { - public Index_ByProfilerId() => Map = docs => from profiler in docs - select new - { - profiler.ProfilerId - }; + public Index_ByProfilerId() => + Map = docs => from profiler in docs select new { profiler.ProfilerId }; } /// @@ -33,10 +26,7 @@ public Index_ByProfilerId() => Map = docs => from profiler in docs /// internal class Index_ByStarted : AbstractIndexCreationTask { - public Index_ByStarted() => Map = docs => from profiler in docs - select new - { - profiler.Started - }; + public Index_ByStarted() => + Map = docs => from profiler in docs select new { profiler.Started }; } } From 14fe73d539db87f290e8e944511649f65fe5b325 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 21:44:20 -0400 Subject: [PATCH 08/19] Remove unused docs on object proxy --- .../Internal/MiniProfilerDoc.cs | 59 ------------------- 1 file changed, 59 deletions(-) diff --git a/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs b/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs index ad70f9c82..f79d2c9b8 100644 --- a/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs +++ b/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using StackExchange.Profiling.Internal; namespace StackExchange.Profiling.Storage.Internal { @@ -24,75 +23,17 @@ public MiniProfilerDoc(MiniProfiler profiler) } public string Id { get; set; } - - /// - /// Gets or sets the profiler id. - /// Identifies this Profiler so it may be stored/cached. - /// public Guid ProfilerId { get; set; } - - /// - /// Gets or sets a display name for this profiling session. - /// public string Name { get; set; } - - /// - /// Gets or sets when this profiler was instantiated, in UTC time. - /// public DateTime Started { get; set; } - - /// - /// Gets the milliseconds, to one decimal place, that this MiniProfiler ran. - /// public decimal DurationMilliseconds { get; set; } - - /// - /// Gets or sets where this profiler was run. - /// public string MachineName { get; set; } - - /// - /// Keys are names, values are URLs, allowing additional links to be added to a profiler result, e.g. perhaps a deeper - /// diagnostic page for the current request. - /// - /// - /// Use to easily add a name/url pair to this dictionary. - /// public Dictionary CustomLinks { get; set; } - - /// - /// JSON used to store Custom Links. Do not touch. - /// public string CustomLinksJson { get; set; } - - /// - /// Gets or sets the root timing. - /// The first that is created and started when this profiler is instantiated. - /// All other s will be children of this one. - /// public Timing Root { get; set; } - - /// - /// Gets or sets timings collected from the client - /// public ClientTimings ClientTimings { get; set; } - - /// - /// Gets or sets a string identifying the user/client that is profiling this request. - /// - /// - /// If this is not set manually at some point, the UserIdProvider implementation will be used; - /// by default, this will be the current request's IP address. - /// public string User { get; set; } - /// - /// Returns true when this MiniProfiler has been viewed by the that recorded it. - /// - /// - /// Allows POSTs that result in a redirect to be profiled. implementation - /// will keep a list of all profilers that haven't been fetched down. - /// public bool HasUserViewed { get; set; } #pragma warning disable CS0618 // Type or member is obsolete From 7466bfeec4bfe433f991d07d2125aab39bc5bc7b Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 21:45:22 -0400 Subject: [PATCH 09/19] Move doc love --- .../Internal/MiniProfilerDoc.cs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs b/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs index f79d2c9b8..c52d89023 100644 --- a/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs +++ b/src/MiniProfiler.Providers.RavenDB/Internal/MiniProfilerDoc.cs @@ -5,6 +5,19 @@ namespace StackExchange.Profiling.Storage.Internal { internal class MiniProfilerDoc { + public string Id { get; set; } + public Guid ProfilerId { get; set; } + public string Name { get; set; } + public DateTime Started { get; set; } + public decimal DurationMilliseconds { get; set; } + public string MachineName { get; set; } + public Dictionary CustomLinks { get; set; } + public string CustomLinksJson { get; set; } + public Timing Root { get; set; } + public ClientTimings ClientTimings { get; set; } + public string User { get; set; } + public bool HasUserViewed { get; set; } + public MiniProfilerDoc() { } public MiniProfilerDoc(MiniProfiler profiler) @@ -22,21 +35,7 @@ public MiniProfilerDoc(MiniProfiler profiler) HasUserViewed = profiler.HasUserViewed; } - public string Id { get; set; } - public Guid ProfilerId { get; set; } - public string Name { get; set; } - public DateTime Started { get; set; } - public decimal DurationMilliseconds { get; set; } - public string MachineName { get; set; } - public Dictionary CustomLinks { get; set; } - public string CustomLinksJson { get; set; } - public Timing Root { get; set; } - public ClientTimings ClientTimings { get; set; } - public string User { get; set; } - - public bool HasUserViewed { get; set; } - -#pragma warning disable CS0618 // Type or member is obsolete +#pragma warning disable CS0618 // Type or member is obsolete (MiniProfiler serialization constructor) public MiniProfiler ToMiniProfiler() => new MiniProfiler { Id = ProfilerId, @@ -51,6 +50,6 @@ public MiniProfilerDoc(MiniProfiler profiler) User = User, HasUserViewed = HasUserViewed }; -#pragma warning restore CS0618 // Type or member is obsolete +#pragma warning restore CS0618 // Type or member is obsolete (MiniProfiler serialization constructor) } } From 04e699630b70a0e369b3bd2103c8c6306591c132 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 21:47:38 -0400 Subject: [PATCH 10/19] Cleanup --- src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs index 65a75ffcb..dc12c37d3 100644 --- a/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs +++ b/src/MiniProfiler.Providers.RavenDB/RavenDbStorage.cs @@ -330,7 +330,6 @@ public async Task> GetUnviewedIdsAsync(string user) /// /// Returns the . /// - /// public IDocumentStore GetDocumentStore() => _store; } } From f328474209880b02a6de721b1a720ac342c89384 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 22:14:59 -0400 Subject: [PATCH 11/19] Naming consistency --- .../Storage/{RavenDbStoreTest.cs => RavenDbStoreTests.cs} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename tests/MiniProfiler.Tests/Storage/{RavenDbStoreTest.cs => RavenDbStoreTests.cs} (94%) diff --git a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTests.cs similarity index 94% rename from tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs rename to tests/MiniProfiler.Tests/Storage/RavenDbStoreTests.cs index 4e8a2074a..06171036f 100644 --- a/tests/MiniProfiler.Tests/Storage/RavenDbStoreTest.cs +++ b/tests/MiniProfiler.Tests/Storage/RavenDbStoreTests.cs @@ -11,9 +11,9 @@ namespace StackExchange.Profiling.Tests.Storage { - public class RavenDbStoreTest : StorageBaseTest, IClassFixture + public class RavenDbStoreTests : StorageBaseTest, IClassFixture { - public RavenDbStoreTest(RavenDbStoreFixture fixture, ITestOutputHelper output) + public RavenDbStoreTests(RavenDbStoreFixture fixture, ITestOutputHelper output) : base(fixture, output) { } From 513255905703dfbbfd9f31f4c6d3cb426f6145af Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Sun, 24 May 2020 22:15:41 -0400 Subject: [PATCH 12/19] Move test compose into \tests --- docker-compose.yml => tests/docker-compose.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docker-compose.yml => tests/docker-compose.yml (100%) diff --git a/docker-compose.yml b/tests/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to tests/docker-compose.yml From 312b4c1b296d4a086412cb012652cdc89d6f06a9 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Mon, 25 May 2020 07:50:00 -0400 Subject: [PATCH 13/19] Move docker-compose.yml in solution --- MiniProfiler.sln | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MiniProfiler.sln b/MiniProfiler.sln index c0deacc7e..54aa4f487 100644 --- a/MiniProfiler.sln +++ b/MiniProfiler.sln @@ -15,7 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "global", "global", "{CC4009 nuget.config = nuget.config Readme.md = Readme.md version.json = version.json - docker-compose.yml = docker-compose.yml EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniProfiler", "src\MiniProfiler\MiniProfiler.csproj", "{386222BD-6B6E-480F-A342-8DE1AB516E2C}" @@ -50,6 +49,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{33644D67-D9BB-4989-9B7A-98D51967059B}" ProjectSection(SolutionItems) = preProject tests\Directory.Build.props = tests\Directory.Build.props + tests\docker-compose.yml = tests\docker-compose.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E0DA4035-4D64-4BB8-8EA1-42197DE62519}" @@ -245,8 +245,8 @@ Global {A14EA029-60E2-485A-B757-3626511CF2C4} = {5C8ED0C0-7DBB-4660-836E-A760E25160A0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - LessCompiler = 6a2b5b70-1c32-482f-b5c6-0597e2d4e376 SolutionGuid = {9373F37A-A996-4545-A251-1902C8886E3F} + LessCompiler = 6a2b5b70-1c32-482f-b5c6-0597e2d4e376 EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = StackExchange.Profiling.vsmdi From 04f9b0ffd4df886cb495530dd95b29bec86bcf77 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Mon, 25 May 2020 07:50:16 -0400 Subject: [PATCH 14/19] Add other storage providers to docker-compose Yay, so handy --- .../MiniProfiler.Tests/Helpers/TestConfig.cs | 2 +- tests/docker-compose.yml | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/MiniProfiler.Tests/Helpers/TestConfig.cs b/tests/MiniProfiler.Tests/Helpers/TestConfig.cs index 32bb650a2..112d184b4 100644 --- a/tests/MiniProfiler.Tests/Helpers/TestConfig.cs +++ b/tests/MiniProfiler.Tests/Helpers/TestConfig.cs @@ -35,7 +35,7 @@ public class Config public string RedisConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(RedisConnectionString)) ?? "localhost:6379"; public string SQLServerConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(SQLServerConnectionString)) ?? "Server=.;Database=tempdb;Trusted_Connection=True;"; public string SQLServerCeConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(SQLServerCeConnectionString)) ?? "Data Source=TestData.sdf;"; - public string MySQLConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(MySQLConnectionString)) ?? "server=localhost;uid=root;pwd=root;database=test;Allow User Variables=true;SslMode=none"; + public string MySQLConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(MySQLConnectionString)) ?? "server=localhost;uid=root;pwd=root;database=test;Allow User Variables=True;SslMode=none;AllowPublicKeyRetrieval=True"; public string PostgreSqlConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(PostgreSqlConnectionString)) ?? "Server=localhost;Port=5432;Database=test;User Id=postgres;Password=postgres;"; public string MongoDbConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(MongoDbConnectionString)) ?? "mongodb://localhost:27017/test"; public string RavenDbUrls { get; set; } = Environment.GetEnvironmentVariable(nameof(RavenDbUrls)) ?? "http://localhost:8080"; diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 36e56ecf1..a0e4b7c05 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -1,18 +1,38 @@ version: "3" services: + mongo: + image: mongo:4 + container_name: mongo + ports: + - 27017:27017 + mysql: + image: mysql:8 + container_name: mysql + ports: + - 3306:3306 + environment: + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: test postgres: image: postgres:alpine container_name: postgres ports: - 5432:5432 environment: - POSTGRES_PASSWORD: "postgres" + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: test raven: image: ravendb/ravendb container_name: raven-db ports: - - 8080:8080 + - 8080:8080 environment: RAVEN_ARGS: '--Setup.Mode=None' RAVEN_License_Eula_Accepted: 'true' - RAVEN_Security_UnsecuredAccessAllowed: 'PrivateNetwork' \ No newline at end of file + RAVEN_Security_UnsecuredAccessAllowed: 'PrivateNetwork' + redis: + image: redis:6-alpine + container_name: redis + ports: + - 6379:6379 \ No newline at end of file From 4207875b34737d6492068d9373d1ab1b549ac8b3 Mon Sep 17 00:00:00 2001 From: Nick Craver Date: Mon, 25 May 2020 08:02:29 -0400 Subject: [PATCH 15/19] Update release notes --- docs/Releases.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/Releases.md b/docs/Releases.md index 48f4314a4..adda7d9ef 100644 --- a/docs/Releases.md +++ b/docs/Releases.md @@ -7,11 +7,12 @@ This page tracks major changes included in any update starting with version 4.0. #### Version 4.2.0 (In preview) - **New**: + - Added RavenDB Storage provider ([#483](https://github.com/MiniProfiler/dotnet/pull/483) - thanks [@lillo42](https://github.com/lillo42)!) - Added `