Closed CXuesong closed 6 years ago
WikiClientLibrary.ILogger
will be removed, and a new interface such as IWikiClientLoggable
will be introduced, like this
interface IWikiClientLoggable
{
void SetLoggerFactory(ILoggerFactory factory);
}
For a better clarity, I will take use of the "scope" feature MEL provides. The new IWikiClientLoggable
would be like this
interface IWikiClientLoggable
{
ILogger Logger { get; set; }
}
To begin with, I am worried about the multi-threading behavior of scopes, but later I took a look at MS's implementation of ILogger
,[1] which uses AsyncLocal<T>
to keep track of the current scope.[2] Perhaps I can count on this.
Under the new design, client only needs to pass ILogger
instances to WikiClient
and WikiSite
, respectively and . Other classes, such as WikiSite
can implicitly use WikiClient
's logger on initializationWikiPage
, will just use WikiSite
's logger, but in a different scope.
With the new scoped logging, the emitted log looks like
Trace: WikiClientLibrary.Client.WikiClient
-> WikiClient#17363659 -> ::InvokeAsync(452849D100000001)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> WikiClient#17363659 -> ::InvokeAsync(452849D100000002)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> WikiClient#17363659 -> ::InvokeAsync(452849D100000002)
HTTP 200, elapsed: 00:00:01.5715946
Trace: WikiClientLibrary.Client.WikiClient
-> WikiClient#17363659 -> ::InvokeAsync(452849D100000001)
HTTP 200, elapsed: 00:00:01.8922563
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> ::LoginAsync(XuesongBot) -> Wikipedia -> ::FetchTokenAsyncCore(login)
Sending request 452849D100000003, SuppressAccountAssertion=True
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> Wikipedia -> ::FetchTokenAsyncCore(login) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000003)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> Wikipedia -> ::FetchTokenAsyncCore(login) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000003)
HTTP 200, elapsed: 00:00:00.3799395
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> ::LoginAsync(XuesongBot)
Sending request 452849D100000004, SuppressAccountAssertion=True
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000004)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000004)
HTTP 200, elapsed: 00:00:01.3669340
Warning: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000004)
API warning [main]: "*": "Subscribe to the mediawiki-api-announce mailing list at <https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce> for notice of API deprecations and breaking changes. Use [[Special:ApiFeatureUsage]] to see usage of deprecated features by your application."
Warning: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000004)
API warning [login]: "*": "Main-account login via \"action=login\" is deprecated and may stop working without warning. To continue login with \"action=login\", see [[Special:BotPasswords]]. To safely continue using main-account login, see \"action=clientlogin\"."
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> ::LoginAsync(XuesongBot) -> Wikipedia -> ::RefreshAccountInfoAsync()
Sending request 452849D100000005, SuppressAccountAssertion=True
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> Wikipedia -> ::RefreshAccountInfoAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D100000005)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LoginAsync(XuesongBot) -> Wikipedia -> ::RefreshAccountInfoAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D100000005)
HTTP 200, elapsed: 00:00:00.3718677
Information: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> ::LoginAsync(XuesongBot)
Logged in as XuesongBot.
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> [WikiPage{Wikipedia:Sandbox}]::RefreshPagesAsync(FetchContent)
Fetching 1 pages.
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> [WikiPage{Wikipedia:Sandbox}]::RefreshPagesAsync(FetchContent)
Sending request 452849D100000006, SuppressAccountAssertion=False
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> [WikiPage{Wikipedia:Sandbox}]::RefreshPagesAsync(FetchContent) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000006)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> [WikiPage{Wikipedia:Sandbox}]::RefreshPagesAsync(FetchContent) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000006)
HTTP 200, elapsed: 00:00:00.4243953
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync()
Edit: Wikipedia:Sandbox#51235807: Waiting for delay 00:00:05.
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync() -> Wikipedia -> ::FetchTokenAsyncCore(csrf)
Sending request 452849D100000008, SuppressAccountAssertion=True
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync() -> Wikipedia -> ::FetchTokenAsyncCore(csrf) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000008)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync() -> Wikipedia -> ::FetchTokenAsyncCore(csrf) -> WikiClient#17363659 -> ::InvokeAsync(452849D100000008)
HTTP 200, elapsed: 00:00:00.3663925
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync()
Sending request 452849D100000007, SuppressAccountAssertion=False
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D100000007)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D100000007)
HTTP 200, elapsed: 00:00:00.5573600
Information: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> WikiPage{Wikipedia:Sandbox}::UpdateContentAsync()
Edited page. New revid=329827.
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> ::LogoutAsync()
Sending request 452849D100000009, SuppressAccountAssertion=True
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LogoutAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D100000009)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LogoutAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D100000009)
HTTP 200, elapsed: 00:00:00.4894650
Debug: WikiClientLibrary.Sites.WikiSite
-> Wikipedia -> ::LogoutAsync() -> Wikipedia -> ::RefreshAccountInfoAsync()
Sending request 452849D10000000A, SuppressAccountAssertion=True
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LogoutAsync() -> Wikipedia -> ::RefreshAccountInfoAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D10000000A)
Initiate request to: https://test2.wikipedia.org/w/api.php.
Trace: WikiClientLibrary.Client.WikiClient
-> Wikipedia -> ::LogoutAsync() -> Wikipedia -> ::RefreshAccountInfoAsync() -> WikiClient#17363659 -> ::InvokeAsync(452849D10000000A)
HTTP 200, elapsed: 00:00:00.3658774
As mentioned in #13, the current
WikiClientLibrary.ILogger
is just error-prone for the library-side code, and the class name is very likely to conflict with other logging libraries. May considerMicrosoft.Extensions.Logging.Abstractions
, thoughSerilog
might also be a good choice.A good point might be that if you pass a
ILoggerFactory
intoWikiClient
, this factory can be used automatically(or not, configured by user)[1] in other related classes, e.g.,WikiSite
s andWikiClient
s.[1] The user can manually remove the logger after the related class instance is created.