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

Documentation #21

Open
bcrosnier opened this issue May 9, 2016 · 8 comments
Open

Documentation #21

bcrosnier opened this issue May 9, 2016 · 8 comments
Assignees

Comments

@bcrosnier
Copy link
Member

This is to gather ideas for a documentation about the various components of CK-Core.
I intend to make a PR initializing this soon with DocFX.

What we're interested in is not only the raw API documentation, which is basically written in the code, but also more general overviews of the various components, with general use cases.

The README.md has the general idea, but needs some buffing up.

@bcrosnier bcrosnier self-assigned this May 9, 2016
@ablanchet
Copy link

It's a very good idea and DocFX allows to add arbitrary MD documents alongside the generated API doc.

Personnaly I'd love to read a real life example about how to use your CK.Monitor/GrandOutput/CK.Core.CrypticLogging.ActivitySink.That.I.Never.Understood.Right ... You know ... the logging thing 😅 .

I'm thinking about a console or WPF application created from scratch that will do some simple work, and more complicated work ... possibly asynchronously ... with aggregated exceptions ... etc. The idea behind this is to demonstrate how to setup the whole thing, how to use it normaly (no fancy tricks), what output you can expect from it, and finally explain the theory behing it.

It would be so nice to be able to use this thing without being forced to have @olivier-spinelli in the office 😉 .

@olivier-spinelli
Copy link
Member

:)
My dear Antoine,

You actually need 2 lines of code in your 'main':

SystemActivityMonitor.RootLogPath = AppSettings.Default[SystemActivityMonitor.AppSettingsKey] ?? "Logs";
GrandOutput.EnsureActiveDefaultWithDefaultSettings();

This uses the RooLogPath defined in Application.config file if it exists:

<appSettings>
    <add key="CK.Core.SystemActivityMonitor.RootLogPath" value="C:\Somewhere\Logs" />
</appSettings>

... Or a "Logs" sub folder in the executable folder.
This automatically creates the following structure in the Logs folder:

  • Logs/
    • CriticalErrors/
    • GranOutputDefault/
    • GrandOutputConfig.xml

And the default GrandOutputConfig.xml file that is automatically monitored (any change to it will reload the new configuration of the GrandOutput):

<GrandOutputConfiguration>
    <Channel MinimalFilter="Debug">
        <Add Type="TextFile" Name="All" Path="GrandOutputDefault" MaxCountPerFile="20000" />
    </Channel>
</GrandOutputConfiguration>

That's it.

@ablanchet
Copy link

Thanks ! I now have the a good example of the initial setup. But I still have a lot of questions coming from this 😲 :

  1. What's an activity monitor ?
  2. What's the differences between the three implementations of it ?
  3. What's a channel ?
  4. What the topic means on an ActivityMonitor ?
  5. What's the recommended way to obtain the GrandOutput ?
  6. What's the recommended way to obtain an ActivityMonitor ?
  7. What's a Sink ?
  8. What's a client ?
  9. What's the IActivityMonitorOutput ?
  10. Wow you can bridge through app domains ? Crazy
  11. How does the configuration work ? On which levels ?
  12. How could I read binary logs ?
  13. Is it possible to add custom serializer in order to lower the allocations while creating binary logs ?
  14. Why "GrandOutput" ? Is it some kind of a logging guru ?
  15. ...

Ok, I'll read the code I'm too curious now. But still, I think a quick start with a step by step example that demonstrate the different entities and how you can use it could be a very helpful for an external user or even a new comer at Invenietis.

I'll be happy to help if you need. I think I know little enough to review the doc like a total beginner :)

Ps: And by the way the default configuration of the "GrandOutput" currently uses a binary file

@bcrosnier
Copy link
Member Author

I've set up a DocFX output over at http://bcrosnier.github.io/ck-core/ using my forked repo (DocFX source). Not much for now, but it's a start. If this looks all right, I can make a PR and reel it in here.

I agree with basically all of @ablanchet's questions, with a bonus "Why the hell would I want to use that over common-logging or NLog or whatever".
Not to sound harsh, obviously -- But I'm pretty sure the ActivityMonitor does things differently enough that it deserves its own page.

Ps: And by the way the default configuration of the "GrandOutput" currently uses a binary file

The text file has been set as default starting with version 5.0.0-epsilon, which is in prerelease right now (latest stable is still 4.2).

Admittedly, CreateDefaultConfig() still creates a BinaryFileConfiguration, and I'm pretty sure that's a bug.

Why "GrandOutput" ? Is it some kind of a logging guru ?

Good question. Wonder if it could be renamed to some kind of CentralizedMonitorOutput, GlobalOutput or something among those lines.

@olivier-spinelli
Copy link
Member

Congratulations, you just gave birth to the OAK (Once Asked Questions 😃)!
Let me answer to some of them.

What's an ActivityMonitor?

It is a rather small object you use to send logs into. It is not thread-safe and not thread-affine: it is tied to an "activity', i.e. a logical sequence of operations (whatever the actual thread is actually doing the job). A single instance is then perfectly adapted to aysnc/await and other continuations patterns.

The IActivityMonitor abstraction exposes only 10 members. This lightweight interface makes façade/wrapper/hook very easy to implement if needed. However this is not the way we most often use/extend it... almost every feature are achieved through the Clients.

What's a Client ?

A IActivityMonitorClient is registered on a monitor and will receive the structured logs and can do what it wants with them. Have a look at the ActivityMonitorConsoleClient that specializes ActivityMonitorTextWriterClient for a simple example.

Registering a Client to a monitor is simple:

var console = new ActivityMonitorConsoleClient();
_monitor.Output.RegisterClient( console );

And removing it is obvious; _monitor.Output.UnregisterClient( console );

This leads to an interesting pattern: locally create and register a Client to monitor things...

bool hasError = false;
using( monitor.OnError( () => hasError = true ) )
using( monitor.OpenInfo().Send( "Handling StObj objects." ) )
{
    // ... some complex code that may emit errors....
}
if( hasError ) ...

...or to alter things:

IActivityMonitor m = new ActivityMonitor();
m.MinimalFilter = LogFilter.Terse;
using( m.SetMinimalFilter( LogFilter.Debug ) )
{
    Assert.That( m.ActualFilter == LogFilter.Debug );
}
Assert.That( m.ActualFilter == LogFilter.Terse, "Filter has been restored to previous value." );

This example leas us to on important point: the filter management that is quite different from other logging framework.

What's the MinimalFilter and ActualFilter?

The ActivityMonitor acts as a mediator between multiple participants regarding what it SHOULD log. The developer can set the MinimalFilter whenever it wants in the code: this is his demand. But the developer is not alone... If it sets MinimalFilter to Off for a given code path, others can disagree (a system administrator for example).
An ActivityMonitor handles this by maintaining an ActualFilter that is the basically the most verbose level wanted by the participants: any Client can define their own MinimalFilter at any time that is guaranteed to be honored.

What's the recommended way to obtain an ActivityMonitor?

Good question! Very simple answer:

  • The best way is to expose the monitor as an explicit dependency:
    • a simple parameter is often fine since it enables the caller to choose the monitor to use for each call.
    • of course, constructor injection with a readonly _monitor field is also possible.
  • Create one when you need it (with no parameters).
    • It will be automatically configured by external components (like the GrandOuput) if required.
    • And keep it alive for the "activity":
      • in a mono-threaded windows service you only need one monitor.
      • in a web server, one activity per request is the way to go.

Wow you can bridge through app domains ? Crazy

Yes it was. But no more. We removed this in the 5.0.0 version to follow the dotnet evolution where AppDomains are dead.
Bridges continue to exist however, even if we have almost never used this feature so far...

Is it possible to add custom serializer in order to lower the allocations while creating binary logs?

Yes of course. However the immutable LogEntry object that is received by the sink will still need to be allocated. I think it is possible to limit the allocations by allowing log entries to be reused (pool of entries) but there will always be all the small strings (the message itself) that need to be allocated...

Why "GrandOutput" ? Is it some kind of a logging guru ?

The intent (see http://www.dictionary.com/browse/grand) is that you never need anything else because it is "impressive", "highly ambitious", "includes everything"...

@ablanchet
Copy link

Looks good, if it's possible it would be nice to use a container-fluid instead of a container in the layout of DocFx. Some types and method prototypes are pretty long and don't fit in the tight container width.

It's a good start anyway, the code doc is fairly good and reading it on a browser help a lot to understand the different entities (at least the interfaces etc).

I can't wait to have the answer to

"Why the hell would I want to use that over common-logging or NLog or whatever".

I haven't even dared to ask this to my almighty former boss 😝

(wow @olivier-spinelli that's a big comment, better start a FAQ on the CK.Core's DocFx instead of OAK here don't you think ?)

@bcrosnier
Copy link
Member Author

I added preliminary information about the ActivityMonitor over at http://bcrosnier.github.io/ck-core/articles/using-the-activitymonitor.html .

I'm going to submit the PR with the DocFx project. We can continue from there.

@bcrosnier
Copy link
Member Author

I've added doc for the CK.Core assembly over at http://bcrosnier.github.io/ck-core/articles/ck-core.html . I'll let you guys read before submitting a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants