Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RNET-1161: Implement support for using a log level for a specific log category #3634

Merged
merged 44 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
a4bf132
Implement 'LogCategory' classes.
elle-j Jun 26, 2024
0f65081
Update Core wrapper for setting log level.
elle-j Jun 26, 2024
7dfb380
Update 'SharedRealmHandle' for logging and setting log level and cate…
elle-j Jun 26, 2024
b33aba1
Update 'Logger' classes to account for category.
elle-j Jun 26, 2024
a2fbca7
Replace static '_logLevel' member with call into Core.
elle-j Jun 26, 2024
c0d9aa4
Update signature in 'UnityLogger'.
elle-j Jun 26, 2024
596e7f5
Replace use of 'LeafLogCategory' with the base.
elle-j Jun 28, 2024
f4c9574
Remove 'LogCategory' getter.
elle-j Jun 28, 2024
5f8cbf4
Update todo comments.
elle-j Jun 28, 2024
7e909c2
Add first tests.
elle-j Jun 28, 2024
84535af
Log with SDK category if not provided.
elle-j Jun 28, 2024
e728ff2
Pass parent category to create name.
elle-j Jul 1, 2024
dc7af0a
Marshal log category names from Core.
elle-j Jul 1, 2024
dedf349
Test matching Core category names.
elle-j Jul 1, 2024
cc68acb
Add API docs.
elle-j Jul 2, 2024
69bd809
Add more tests.
elle-j Jul 2, 2024
2919b03
Show category hierarchy in API docs.
elle-j Jul 2, 2024
84e8733
Add CHANGELOG entry.
elle-j Jul 2, 2024
5232577
Change arg. order to not break 'LogImpl()' API.
elle-j Jul 2, 2024
d1977ee
Deprecate old APIs.
elle-j Jul 2, 2024
c2dfcfa
Update CHANGELOG.
elle-j Jul 2, 2024
b4dcaad
Point to updated Core.
elle-j Jul 2, 2024
61f05a3
Change marshaled vector from heap-allocated to global.
elle-j Jul 2, 2024
a86513c
Update 'shared_realm_get_log_level'.
elle-j Jul 2, 2024
461e090
Update usage of now-deprecated APIs.
elle-j Jul 2, 2024
b19f081
Update API doc.
elle-j Jul 5, 2024
8fafa12
Use braced initializer when returning marshaled vector.
elle-j Jul 5, 2024
f09ae91
Try to fix Windows marshaling.
elle-j Jul 5, 2024
28455dd
Make marshallable struct unnested.
elle-j Jul 5, 2024
7c91e71
Make marshalable nested.
elle-j Jul 5, 2024
e5a6a8e
Fix Windows marshaling once and for all.
elle-j Jul 5, 2024
40195c3
Fix Windows marshaling twice and for all
nirinchev Jul 10, 2024
4eb128a
Merge branch 'main' into lj/logger
nirinchev Jul 10, 2024
55f074d
Deprecate 'Logger' and use its base class.
elle-j Jul 11, 2024
66cdff5
Check log level for 'Realm.SDK' in 'SyncSocketProvider'.
elle-j Jul 11, 2024
b4efe05
Move marshalling from 'MarshaledVector' onto 'TypeErasedMarshaledVect…
elle-j Jul 11, 2024
c66bdf1
Minor update to API docs.
elle-j Jul 11, 2024
5307414
Update 'cref's to resolve doc links.
elle-j Jul 11, 2024
e7de88a
Add a log API for Core-only messages to avoid checking level.
elle-j Jul 11, 2024
f2a938d
Make arg order in wrapper consistent.
elle-j Jul 11, 2024
a3e3deb
Call non-level-check log impl from 'Log()'.
elle-j Jul 11, 2024
db579ee
Rename 'CoreLog' to 'LogAnyLevel' to suit current call pattern.
elle-j Jul 11, 2024
cf65350
Remove internal 'LogDefault()'.
elle-j Jul 11, 2024
c0b98fb
Update CHANGELOG.
elle-j Jul 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
## vNext (TBD)

### Deprecations
* The `Logger.LogLevel` `set` and `get` accessors have been deprecated. Please use `Logger.SetLogLevel()` and `Logger.GetLogLevel()` (see **Enhancements** below).
* The `Logger.Function(Action<LogLevel, string> logFunction)` have been deprecated. Please use `Logger.Function(Action<LogLevel, LogCategory, string> logFunction)` (see **Enhancements** below).

### Enhancements
* Allow `ShouldCompactOnLaunch` to be set on `SyncConfiguration`, not only `RealmConfiguration`. (Issue [#3617](https://github.com/realm/realm-dotnet/issues/3617))
* Reduce the size of the local transaction log produced by creating objects, improving the performance of insertion-heavy transactions (Core 14.10.0).
* Performance has been improved for range queries on integers and timestamps. Requires that you use the "BETWEEN" operation in `Realm.All<T>().Filter(...)`. (Core 14.10.1)
* Allowed `ShouldCompactOnLaunch` to be set on `SyncConfiguration`, not only `RealmConfiguration`. (Issue [#3617](https://github.com/realm/realm-dotnet/issues/3617))
* Introduced a `LogCategory` and allowed for more control over which category of messages should be logged and at which criticality level:
* Allowed setting and getting a `LogLevel` for a given `LogCategory`. The hierarchy of categories starts at `LogCategory.Realm`.
```csharp
Logger.SetLogLevel(LogLevel.Warn, LogCategory.Realm.Sync);
Logger.GetLogLevel(LogCategory.Realm.Sync.Client.Session); // LogLevel.Warn
```
* Added a function logger that accepts a callback that will receive the `LogLevel`, `LogCategory`, and the message when invoked.
```csharp
Logger.Default = Logger.Function((level, category, message) => /* custom implementation */);
```
* Added an optional category as a last parameter to `Logger.Log()`. If unset, `LogCategory.Realm.SDK` will be used.
```csharp
Logger.Default.Log(LogLevel.Warn, "A warning message", LogCategory.Realm);
```
(PR [#3634](https://github.com/realm/realm-dotnet/pull/3634))

### Fixed
* A `ForCurrentlyOutstandingWork` progress notifier would not immediately call its callback after registration. Instead you would have to wait for some data to be received to get your first update - if you were already caught up when you registered the notifier you could end up waiting a long time for the server to deliver a download that would call/expire your notifier. (Core 14.8.0)
Expand Down
4 changes: 2 additions & 2 deletions Realm/Realm.UnityUtils/UnityLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ namespace UnityUtils
{
public class UnityLogger : Logger
{
protected override void LogImpl(LogLevel level, string message)
protected override void LogImpl(LogLevel level, string message, LogCategory? category = null)
{
var toLog = FormatLog(level, message);
var toLog = FormatLog(level, message, category!);
elle-j marked this conversation as resolved.
Show resolved Hide resolved
switch (level)
{
case LogLevel.Fatal:
Expand Down
25 changes: 20 additions & 5 deletions Realm/Realm/Handles/SharedRealmHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
nirinchev marked this conversation as resolved.
Show resolved Hide resolved
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -63,8 +64,9 @@
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DisposeGCHandleCallback(IntPtr handle);

// TODO(lj): Update arg order to be the same across the SDK.

Check warning on line 67 in Realm/Realm/Handles/SharedRealmHandle.cs

View workflow job for this annotation

GitHub Actions / Verify TODOs

Realm/Realm/Handles/SharedRealmHandle.cs#L67

TODO entry doesn't have a link to Github issue or Jira ticket lj): Update arg order to be the same across the SDK.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LogMessageCallback(StringValue message, LogLevel level);
public delegate void LogMessageCallback(StringValue message, LogLevel level, StringValue categoryName);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void HandleTaskCompletionCallback(IntPtr tcs_ptr, [MarshalAs(UnmanagedType.U1)] bool invoke_async, NativeException ex);
Expand Down Expand Up @@ -223,8 +225,14 @@
[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_refresh_async", CallingConvention = CallingConvention.Cdecl)]
public static extern bool refresh_async(SharedRealmHandle realm, IntPtr tcs_handle, out NativeException ex);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_get_log_level", CallingConvention = CallingConvention.Cdecl)]
public static extern LogLevel get_log_level([MarshalAs(UnmanagedType.LPWStr)] string category_name, IntPtr category_name_len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're trying to go with using Realm.Native.StringValue in wrapper calls when needing to pass strings. Am I correct @nirinchev ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding here was that StringValue is mainly used for the returned strings (Core -> DotNet), whereas the MarshalAs is DotNet -> Core primarily?


[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_set_log_level", CallingConvention = CallingConvention.Cdecl)]
public static extern bool set_log_level(LogLevel level);
public static extern void set_log_level(LogLevel level, [MarshalAs(UnmanagedType.LPWStr)] string category_name, IntPtr category_name_len);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_get_log_category_names", CallingConvention = CallingConvention.Cdecl)]
public static extern MarshaledVector<StringValue> get_log_category_names();

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "shared_realm_get_operating_system", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr get_operating_system(IntPtr buffer, IntPtr buffer_length);
Expand Down Expand Up @@ -271,7 +279,14 @@
notifyObject, notifyDictionary, onMigration, shouldCompact, handleTaskCompletion, onInitialization);
}

public static void SetLogLevel(LogLevel level) => NativeMethods.set_log_level(level);
public static LogLevel GetLogLevel(LogCategory category) => NativeMethods.get_log_level(category.Name, (IntPtr)category.Name.Length);

public static void SetLogLevel(LogLevel level, LogCategory category) => NativeMethods.set_log_level(level, category.Name, (IntPtr)category.Name.Length);

public static string[] GetLogCategoryNames() => NativeMethods.get_log_category_names()
.ToEnumerable()
.Select(name => name.ToDotnetString()!)
.ToArray();

[Preserve]
protected SharedRealmHandle(IntPtr handle) : base(handle)
Expand Down Expand Up @@ -822,9 +837,9 @@
}

[MonoPInvokeCallback(typeof(NativeMethods.LogMessageCallback))]
private static void LogMessage(StringValue message, LogLevel level)
private static void LogMessage(StringValue message, LogLevel level, StringValue categoryName)
{
Logger.LogDefault(level, message!);
Logger.LogDefault(level, message!, LogCategory.FromName(categoryName!));
}

[MonoPInvokeCallback(typeof(NativeMethods.MigrationCallback))]
Expand Down
226 changes: 226 additions & 0 deletions Realm/Realm/Logging/LogCategory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2024 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

using System.Collections.Generic;
using Realms.Helpers;

namespace Realms.Logging
{
/// <summary>
/// Specifies the category to receive log messages for when logged by the default
/// logger. The <see cref="LogLevel"/> will always be set for a specific category.
/// Setting the log level for one category will automatically set the same level
/// for all of its subcategories.
/// <code>
/// Realm
elle-j marked this conversation as resolved.
Show resolved Hide resolved
/// ├─► Storage
/// │ ├─► Transaction
/// │ ├─► Query
/// │ ├─► Object
/// │ └─► Notification
/// ├─► Sync
/// │ ├─► Client
/// │ │ ├─► Session
/// │ │ ├─► Changeset
/// │ │ ├─► Network
/// │ │ └─► Reset
/// │ └─► Server
/// ├─► App
/// └─► Sdk
/// </code>
/// </summary>
/// <example>
/// <code>
/// LogCategory.Realm.Sync.Client
/// </code>
/// </example>
public class LogCategory
{
/// <summary>
/// Gets the name of the category.
/// </summary>
public string Name { get; }

/// <summary>
/// Gets the top-level category for receiving log messages for all categories.
/// </summary>
public static RealmLogCategory Realm { get; } = new();

internal static readonly Dictionary<string, LogCategory> NameToCategory = new()
{
{ Realm.Name, Realm },
{ Realm.Storage.Name, Realm.Storage },
{ Realm.Storage.Transaction.Name, Realm.Storage.Transaction },
{ Realm.Storage.Query.Name, Realm.Storage.Query },
{ Realm.Storage.Object.Name, Realm.Storage.Object },
{ Realm.Storage.Notification.Name, Realm.Storage.Notification },
{ Realm.Sync.Name, Realm.Sync },
{ Realm.Sync.Client.Name, Realm.Sync.Client },
{ Realm.Sync.Client.Session.Name, Realm.Sync.Client.Session },
{ Realm.Sync.Client.Changeset.Name, Realm.Sync.Client.Changeset },
{ Realm.Sync.Client.Network.Name, Realm.Sync.Client.Network },
{ Realm.Sync.Client.Reset.Name, Realm.Sync.Client.Reset },
{ Realm.Sync.Server.Name, Realm.Sync.Server },
{ Realm.App.Name, Realm.App },
{ Realm.SDK.Name, Realm.SDK },
};

private LogCategory(string name, LogCategory? parent) => Name = parent == null ? name : $"{parent}.{name}";

internal static LogCategory FromName(string name)
{
Argument.Ensure(NameToCategory.TryGetValue(name, out var category), $"Unexpected category name: '{name}'", nameof(name));

return category;
}

/// <summary>
/// Returns a string that represents the category, equivalent to its name.
/// </summary>
/// <returns>A string that represents the category, equivalent to its name.</returns>
public override string ToString() => Name;

/// <summary>
/// The top-level category for receiving log messages for all categories.
/// </summary>
public class RealmLogCategory : LogCategory
{
/// <summary>
/// Gets the category for receiving log messages pertaining to database events.
/// </summary>
public StorageLogCategory Storage { get; }

/// <summary>
/// Gets the category for receiving log messages pertaining to Atlas Device Sync.
/// </summary>
public SyncLogCategory Sync { get; }

/// <summary>
/// Gets the category for receiving log messages pertaining to Atlas App.
/// </summary>
public LogCategory App { get; }

// TODO(lj): Prefer `SDK` or `Sdk` for c#?

Check warning on line 118 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Verify TODOs

Realm/Realm/Logging/LogCategory.cs#L118

TODO entry doesn't have a link to Github issue or Jira ticket lj): Prefer `SDK` or `Sdk` for c#?
elle-j marked this conversation as resolved.
Show resolved Hide resolved
/// <summary>

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Source Generation

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Analyze C#

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Analyze C#

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Analyze C#

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Package NuGet

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Package NuGet

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Package NuGet

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md)

Check warning on line 119 in Realm/Realm/Logging/LogCategory.cs

View workflow job for this annotation

GitHub Actions / Test Code Coverage

Element documentation header should be preceded by blank line (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1514.md) [/home/runner/work/realm-dotnet/realm-dotnet/Realm/Realm/Realm.csproj::TargetFramework=net8.0]
/// Gets the category for receiving log messages pertaining to the SDK.
/// </summary>
public LogCategory SDK { get; }

internal RealmLogCategory() : base("Realm", null)
{
Storage = new StorageLogCategory(this);
Sync = new SyncLogCategory(this);
App = new LogCategory("App", this);
SDK = new LogCategory("SDK", this);
}
}

/// <summary>
/// The category for receiving log messages pertaining to database events.
/// </summary>
public class StorageLogCategory : LogCategory
{
/// <summary>
/// Gets the category for receiving log messages when creating, advancing, and
/// committing transactions.
/// </summary>
public LogCategory Transaction { get; }

/// <summary>
/// Gets the category for receiving log messages when querying the database.
/// </summary>
public LogCategory Query { get; }

/// <summary>
/// Gets the category for receiving log messages when mutating the database.
/// </summary>
public LogCategory Object { get; }

/// <summary>
/// Gets the category for receiving log messages when there are notifications
/// of changes to the database.
/// </summary>
public LogCategory Notification { get; }

internal StorageLogCategory(LogCategory parent) : base("Storage", parent)
{
Transaction = new LogCategory("Transaction", this);
Query = new LogCategory("Query", this);
Object = new LogCategory("Object", this);
Notification = new LogCategory("Notification", this);
}
}

/// <summary>
/// The category for receiving log messages pertaining to Atlas Device Sync.
/// </summary>
public class SyncLogCategory : LogCategory
{
/// <summary>
/// Gets the category for receiving log messages pertaining to sync client operations.
/// </summary>
public ClientLogCategory Client { get; }

/// <summary>
/// Gets the category for receiving log messages pertaining to sync server operations.
/// </summary>
public LogCategory Server { get; }

internal SyncLogCategory(LogCategory parent) : base("Sync", parent)
{
Client = new ClientLogCategory(this);
Server = new LogCategory("Server", this);
}
}

/// <summary>
/// The category for receiving log messages pertaining to sync client operations.
/// </summary>
public class ClientLogCategory : LogCategory
{
/// <summary>
/// Gets the category for receiving log messages pertaining to the sync session.
/// </summary>
public LogCategory Session { get; }

/// <summary>
/// Gets the category for receiving log messages when receiving, uploading, and
/// integrating changesets.
/// </summary>
public LogCategory Changeset { get; }

/// <summary>
/// Gets the category for receiving log messages pertaining to low-level network activity.
/// </summary>
public LogCategory Network { get; }

/// <summary>
/// Gets the category for receiving log messages when there are client reset operations.
/// </summary>
public LogCategory Reset { get; }

internal ClientLogCategory(LogCategory parent) : base("Client", parent)
{
Session = new LogCategory("Session", this);
Changeset = new LogCategory("Changeset", this);
Network = new LogCategory("Network", this);
Reset = new LogCategory("Reset", this);
}
}
}
}
Loading
Loading