stcarrez / ada-util

Ada Utility Library - Composing streams, processes, logs, serialization, encoders and more
Apache License 2.0
69 stars 14 forks source link

Custom log appender #32

Closed mgrojo closed 1 year ago

mgrojo commented 1 year ago

I've created my own custom implementation of a log appender, but I had to add the new derived type as a child of Util.Log.Appenders because there's no other way to initialize the private field Name, necessary for the logic to find the new Appender. Is this the intended way, have I missed something or can it be considered a bug/lack of a feature?

stcarrez commented 1 year ago

You should try using the Util.Log.Appenders.Factories generic package. You instantiate it with the log appender name and a function that is responsible for allocating and creating the named appender.

  package Console_Factory is
     new Util.Log.Appenders.Factories (Name   => "aktConsole",
                                       Create => Create_Console_Appender'Access);
mgrojo commented 1 year ago

Yes, I used that, but I miss a way to initialize Name in my Appender implementation. Inside the package hierarchy, the built-in Appenders have public visibility of Name as in https://github.com/stcarrez/ada-util/blob/e4de779576938e1972df2e2c0d29a9b5eaf04009/src/base/log/util-log-appenders-consoles.adb#L89

But I didn't know how to initialize it using the public view. I thought in using the parent's Create function, but then, how I free that new object returned? Should I forget about, because it will be called once?

mgrojo commented 1 year ago

Sorry, I'm mixing things. I think the parent's Create had another problem. It does not create a new object, but maybe it returns only already registered appenders?

stcarrez commented 1 year ago

Ok, I understand your issue...

I introduced the factory of appenders with commit cfdc44305f4f0dc27d42a2138dd3e83d15c7739f and before that the Appender type was also private. The commit made the type public and gave visibility to the Name but also some internal members such as Next which maintains a simple and memory efficient list of appenders.

Then commit c5f2892a0e00bbab653b80e4406a540ee71b7646 moved the Appender type declaration from the public part to the private part which brings your issue.

On one hand it is not good to expose the internal which is the reason why I moved the type to the private part. On the other hand, this prevents or brings unnecessary complexity if we want to extend the type.

I will try to change the type to use something like:

   type Appender_Internal is limited private;

   type Appender (Length : Positive) is abstract
     new Ada.Finalization.Limited_Controlled with record
      Next     : Appender_Internal;
      Level    : Level_Type := INFO_LEVEL;
      Layout   : Layout_Type := FULL;
      Name     : String (1 .. Length);
   end record;

and make Name, Level and Layout visible since there is no real constraints in hiding them and have the Appender_Internal that hides the internal.

Just curious, what kind of appender have you written?

mgrojo commented 1 year ago

Thanks, that should allow extending without hanging from Util.Log.Appenders.

The appender is very specific to my system, which uses a particular format and some custom fields. The idea is that any log produced using Util.Log is forwarded to the log package of this system, so everything is integrated. In fact, only level and message are reused, because I forward them to my package, which is a complete log implementation. It's working fine, and the only issue was having to meddle in the private part.