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

to 1.2.4: Add trace logging and consistent logging #932

Open
wants to merge 4 commits into
base: v1.2.4
Choose a base branch
from

Conversation

kentbull
Copy link
Contributor

@kentbull kentbull commented Jan 28, 2025

This PR adds the logging changes made to 1.1.27+ from here: #913
and from here: #930

There is be a similar PR to the main branch: #933

The result of this PR is:

  • Adds TRACE logging level in keri.help.init module.
  • Moves escrow logs to TRACE logging level.
  • Moves event body logging to DEBUG level.
  • INFO log level contains SAID or prefix of events rather than an event body.
  • Uniformly uses log substitution where it would improve performance.
  • Uniformly uses f-strings where performance is equivalent yet readability is enhanced.
  • serder.pretty() used in favor of serder.ked or json.dumps(serder.ked, indent=1)
  • Added escrow-specific strings to each escrow to clarify in logs which escrow produced which log message.
  • Various spelling corrections and wording cleanups like Kevery process to Kevery

@kentbull kentbull force-pushed the add-trace-logging-and-consistent-logging branch from e0c5fde to 51d8cd7 Compare January 29, 2025 00:03
Copy link
Member

@pfeairheller pfeairheller left a comment

Choose a reason for hiding this comment

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

I would like to find a way to avoid the prefixes added to all the log messages.

Most log messages are unique enough that a simple search of the code base finds the one you are looking for. And if they aren't, I'd rather update the few that are to be more specific / descriptive and avoid this bespoke cataloging of log messages.

@kentbull kentbull changed the title Add trace logging and consistent logging to 1.2.4: Add trace logging and consistent logging Jan 29, 2025
@kentbull
Copy link
Contributor Author

avoid the prefixes added to all the log messages

I agree that it does add some noise, though I believe it is well worth the tradeoff, especially for newcomers like me. I added a module prefix in most places and in some places I added the identifier prefix. The reason I added this is because while debugging multisig I had the question of which multisig participant was receiving a message or completing a multisig group.

If there's a different or better way to accomplish this understanding I'm all ears. Adding prefixes to the log messages really helped especially when I wanted to distinguish between things like the KERIA Anchorer and the KERIpy Anchorer and similar cases.

I like being able to follow the log messages without having to refer back to the codebase, though that is personal preference. I'll go remove the prefixes if you'd rather have them be removed.

@iFergal
Copy link
Contributor

iFergal commented Jan 29, 2025

Can we configure the logger to just (optionally?) prefix logs with the module and class name?

I do agree that it would be nice to get this info when less familiar with the code as jumping back to search for log line by line is a lot of context to keep in mind trying to debug.

@kentbull
Copy link
Contributor Author

@iFergal no, sadly that does not work because the HIO logger always uses the "hio.ogler.help" module as the module name, sadly.

@pfeairheller
Copy link
Member

@iFergal no, sadly that does not work because the HIO logger always uses the "hio.ogler.help" module as the module name, sadly.

I believe Fergal is correct. You can configure the logger after retrieving it in whatever application starts your logging and with that configuration you could add something like %{packagePath)s.%(module)s in the format string.

All of my applications override the module name when I start my loggers.

@pfeairheller
Copy link
Member

pfeairheller commented Jan 29, 2025

For example, the logging for my RACK gateways looks like this:

2025-01-29 11:31:21 [rack] INFO essr -> [EP8HM9KgEK9sAqGWFGcnuPwG0JcUW0TQI2XCK4eAVt62]/[EFY-eb3NpuZIYYy2TH0GiutZvaenae7rHF7fSrxChhag] -> tcp: msg sent.
2025-01-29 11:31:21 [rack] INFO Behavior for /ack missing or does not have verify for said=ECbt-GW49k1Sntc3jyEDxo8LL__57FVkKMQZbJxBnDke
2025-01-29 11:31:21 [rack] INFO ack=ECbt-GW49k1Sntc3jyEDxo8LL__57FVkKMQZbJxBnDke received for exn message EMeBC44r1_A1gY-Dse35iBPTFrmH_2lvtPFfOynlZutl
2025-01-29 11:31:21 [rack] INFO tcp client cue received for evt=ECbt-GW49k1Sntc3jyEDxo8LL__57FVkKMQZbJxBnDke
2025-01-29 11:31:21 [rack] INFO Behavior for /ack missing or does not have verify for said=EHRtV1Xtj1dzRX4QTxEH219m20KlK82LbG0QN1jhe4_M
2025-01-29 11:31:21 [rack] INFO ack=EHRtV1Xtj1dzRX4QTxEH219m20KlK82LbG0QN1jhe4_M received for exn message EMiuCy24UrBYV-8qk_3SmK4f0cPvXGcKzm13ZbPc5u3q
2025-01-29 11:31:21 [rack] INFO tcp client cue received for evt=EHRtV1Xtj1dzRX4QTxEH219m20KlK82LbG0QN1jhe4_M
2025-01-29 11:32:21 [rack] INFO httpsrv -> []/[] -> essr: msg recv.
2025-01-29 11:32:21 [rack] INFO httpsrv -> []/[] -> essr: msg sent.

@kentbull
Copy link
Contributor Author

I believe Fergal is correct.

I will try it again. When I tried to add the module name to the logger format like you say it always returned hio.ogler.help so I must have misconfigured it.

@pfeairheller do you mind posting how you got HIO's logger to include the module name? I see the app name rack in those log messages yet I do not see the module name.

Adding the app prefix like you have is easy. The thing that did not work for me is the module name, which is why I added it manually to all the log messages I wrote at the INFO level.

@pfeairheller
Copy link
Member

So here it is with package, function name and line number:

2025-01-29 15:51:35 [rack] exchanging.processEvent-150 INFO Behavior for /essr/req missing or does not have verify for said=EDPQNW_BxBLh1DD43ipwE6uajFoH9RB6qKknrfWrwQST
2025-01-29 15:51:35 [rack] exchanging.processEvent-161 INFO Behavior for /essr/req missing or does not have handle for said=EDPQNW_BxBLh1DD43ipwE6uajFoH9RB6qKknrfWrwQST
2025-01-29 15:51:35 [rack] racking.processCues-484 INFO essr -> [EP8HM9KgEK9sAqGWFGcnuPwG0JcUW0TQI2XCK4eAVt62]/[EFY-eb3NpuZIYYy2TH0GiutZvaenae7rHF7fSrxChhag] -> tcp: msg recv.
2025-01-29 15:51:35 [rack] racking.processCues-497 INFO essr -> [EP8HM9KgEK9sAqGWFGcnuPwG0JcUW0TQI2XCK4eAVt62]/[EFY-eb3NpuZIYYy2TH0GiutZvaenae7rHF7fSrxChhag] -> tcp: msg sent.
2025-01-29 15:51:35 [rack] exchanging.processEvent-150 INFO Behavior for /essr/req missing or does not have verify for said=EKtyXTkU2GEAZmogii5H2CPIr2rtVpA3sgFuQkMhx6L_
2025-01-29 15:51:35 [rack] exchanging.processEvent-161 INFO Behavior for /essr/req missing or does not have handle for said=EKtyXTkU2GEAZmogii5H2CPIr2rtVpA3sgFuQkMhx6L_
2025-01-29 15:51:35 [rack] racking.processCues-484 INFO essr -> [EP8HM9KgEK9sAqGWFGcnuPwG0JcUW0TQI2XCK4eAVt62]/[EFY-eb3NpuZIYYy2TH0GiutZvaenae7rHF7fSrxChhag] -> tcp: msg recv.
2025-01-29 15:51:35 [rack] racking.processCues-497 INFO essr -> [EP8HM9KgEK9sAqGWFGcnuPwG0JcUW0TQI2XCK4eAVt62]/[EFY-eb3NpuZIYYy2TH0GiutZvaenae7rHF7fSrxChhag] -> tcp: msg sent.
2025-01-29 15:51:35 [rack] exchanging.processEvent-150 INFO Behavior for /ack missing or does not have verify for said=EEcmh7rHzmub-6gT4bDHQRIGmDSV6ScoaqdSg8trZG6v
2025-01-29 15:51:35 [rack] clienting.handle-409 INFO ack=EEcmh7rHzmub-6gT4bDHQRIGmDSV6ScoaqdSg8trZG6v received for exn message ELw53ek_faA1Ld3UQU7xjTJelu3ci8RbVuq7h1u-rR-u
2025-01-29 15:51:35 [rack] clienting.cueDo-292 INFO tcp client cue received for evt=EEcmh7rHzmub-6gT4bDHQRIGmDSV6ScoaqdSg8trZG6v

The format string for this was:

FORMAT = '%(asctime)s [rack] %(module)s.%(funcName)s-%(lineno)s %(levelname)-8s %(message)s'

And here is the full list of formatting fields:

%(asctime)s: Human-readable time when the log record was created.
%(created)f: Time when the log record was created (as a floating-point number).
%(msecs)d: Millisecond portion of the creation time.
%(relativeCreated)d: Time in milliseconds since the logging module was started.
%(levelname)s: Text logging level for the message (e.g., 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
%(levelno)s: Numeric logging level for the message (e.g., 10, 20, 30, 40, 50).
%(name)s: Name of the logger used to log the call.
%(message)s: The logged message.
%(pathname)s: Full path name of the source file where the logging call was issued.
%(filename)s: Filename portion of pathname.
%(module)s: Module name portion of pathname.
%(lineno)d: Source line number where the logging call was issued.
%(funcName)s: Function name where the logging call was issued.
%(process)d: Process ID.
%(processName)s: Process name.
%(thread)d: Thread ID.
%(threadName)s: Thread name.

@pfeairheller
Copy link
Member

I think in debug we could change the formatter to use those fields with some combination of file, path, package, function and line number. Formatter better than my quick example above.

@kentbull
Copy link
Contributor Author

kentbull commented Jan 30, 2025

@iFergal and @pfeairheller the most recent commit contains a format string added in the keri.help.__init__ module. Also, the format string cannot contain Class name, sadly, without using something like inspect() to traverse the call stack and find the class name. So if we like the class names in log messages then we can leave the existing ones there that are there. I definitely think it can get to be a bit much when the first 81 characters of your log message are context metadata rather than the log message like below.

This next snippet shows the first 81 characters of the log message using the first formatter shown below.

2025-01-30 11:26:48,489 [keri] eventing.logEvent-3187  INFO     Kever [BPFoQiWD]

This is from the following format string:

logFmt = "%(asctime)s [keri] %(module)s.%(funcName)s-%(lineno)d  %(levelname)-8s %(message)s"

The log snippet above is from logs of what it looks like on my machine to run kli witness demo with INFO logging enabled with the new logging changes, shown below:

2025-01-30 11:26:48,489 [keri] eventing.logEvent-3187  INFO     Kever [BPFoQiWD]: Added to KEL icp at sn=0 valid event SAID=EMEa7V3p1RftbjOc165klR11sk8m4ZhIfJ67rzOR9UTF for AID BPFoQiWD14zN_ng5hjelOn1_k3B02vCSGo2L91FbVy7f
2025-01-30 11:26:48,573 [keri] eventing.logEvent-3187  INFO     Kever [BPfKTvhZ]: Added to KEL icp at sn=0 valid event SAID=EIJ7F-Z1k76GVymvoKWjkyJABnItK99DK4wSr54poF6O for AID BPfKTvhZGhP33SALEwVAxNEveJZBA3VYj4ihHokSETZf
2025-01-30 11:26:48,659 [keri] eventing.logEvent-3187  INFO     Kever [BLSln4kh]: Added to KEL icp at sn=0 valid event SAID=EJMHzHpdDYGW496hJ-Yem5QJHtL42J_av2dg8vRY6RtR for AID BLSln4khIr0mgpr8vgq1Vo-2FLsOwoXAce_7U3CX579v
2025-01-30 11:26:48,738 [keri] eventing.logEvent-3187  INFO     Kever [BC2YRdAf]: Added to KEL icp at sn=0 valid event SAID=EBFSfUzxXc6lp7Ys0lSCpz8ZEBZoLmmVx22dtUYDD0Bp for AID BC2YRdAfFloFZDyXnnNfiL2Xlb1R0hwKSQcFi3G4__eU
2025-01-30 11:26:48,820 [keri] eventing.logEvent-3187  INFO     Kever [BFANVUo-]: Added to KEL icp at sn=0 valid event SAID=EMo85tLTYvOl4Vne8MjtNb5ECHM2zXqxP7Sfm_mp_ADD for AID BFANVUo-8qw3JhTKrxR5f21Gi-0xUVsg5HYmOrxXEGiF
2025-01-30 11:26:48,893 [keri] eventing.logEvent-3187  INFO     Kever [BEC-M_xt]: Added to KEL icp at sn=0 valid event SAID=EJQAonl6z1Qpt5sGT2p6w636RRvYJesMFIiqceP12Hc5 for AID BEC-M_xt4E1r_ya3QJekqv1G_8N6Cje259AIViWe_miM
2025-01-30 11:26:48,963 [keri] eventing.logEvent-3187  INFO     Kever [BBilc4-L]: Added to KEL icp at sn=0 valid event SAID=EIkO4CUmYXukX4auGU9yaFoQaIicfVZkazQ0A3IO5biT for AID BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha
2025-01-30 11:26:49,046 [keri] eventing.logEvent-3187  INFO     Kever [BLskRTIn]: Added to KEL icp at sn=0 valid event SAID=EGuHrbhKDUC6umKP5buvRr6DLUorsQwnCZGZU0hEqsSP for AID BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM
2025-01-30 11:26:49,127 [keri] eventing.logEvent-3187  INFO     Kever [BIKKuvBw]: Added to KEL icp at sn=0 valid event SAID=EC5Yh_MaLtrkgFpg7PyVNkM7Fv6htQdZb1kGxThK6Ahi for AID BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX
2025-01-30 11:26:49,205 [keri] eventing.logEvent-3187  INFO     Kever [BM35JN8X]: Added to KEL icp at sn=0 valid event SAID=EIGspjOvYwgoZkuu2ynls8d8x6RuJEYqIiqfc2l_DoHs for AID BM35JN8XeJSEfpxopjn5jr7tAHCE5749f0OobhMLCorE
2025-01-30 11:26:49,281 [keri] eventing.logEvent-3187  INFO     Kever [BIj15u5V]: Added to KEL icp at sn=0 valid event SAID=EGm5cP_LsBmVsUuLlCXhfIUgPnRZwFk4bddDfSHWYkXu for AID BIj15u5V11bkbtAxMA7gcNJZcax-7TgaBMLsQnMHpYHP
2025-01-30 11:26:49,357 [keri] eventing.logEvent-3187  INFO     Kever [BF2rZTW7]: Added to KEL icp at sn=0 valid event SAID=EBou0Po7cpqA9gEyvjHG8LsJ7zrbZVHOmX3KXYi4-_tW for AID BF2rZTW79z4IXocYRQnjjsOuvFUQv-ptCf8Yltd7PfsM
Witness wan : BBilc4-L3tFUnfM_wJr4S4OJanAv_VmF_dJNN6vkf2Ha
Witness wil : BLskRTInXnMxWaGqcpSyMgo0nYbalW99cGZESrz3zapM
Witness wes : BIKKuvBwpmDVA4Ds-EpL5bt9OqPzWPja2LigFYZN2YfX
Witness wit : BM35JN8XeJSEfpxopjn5jr7tAHCE5749f0OobhMLCorE
Witness wub : BIj15u5V11bkbtAxMA7gcNJZcax-7TgaBMLsQnMHpYHP
Witness wyz : BF2rZTW79z4IXocYRQnjjsOuvFUQv-ptCf8Yltd7PfsM

I like the more trim logging format shown next:

logFmt = "%(asctime)s [keri] %(levelname)-8s %(message)s"

which produces log output that looks like:

2025-01-30 11:39:03,619 [keri] INFO     Kever [BPFoQiWD]: Added to KEL icp at sn=0 valid event SAID=EMEa7V3p1RftbjOc165klR11sk8m4ZhIfJ67rzOR9UTF for AID BPFoQiWD14zN_ng5hjelOn1_k3B02vCSGo2L91FbVy7f
2025-01-30 11:39:03,695 [keri] INFO     Kever [BPfKTvhZ]: Added to KEL icp at sn=0 valid event SAID=EIJ7F-Z1k76GVymvoKWjkyJABnItK99DK4wSr54poF6O for AID BPfKTvhZGhP33SALEwVAxNEveJZBA3VYj4ihHokSETZf

this is 57 characters of metadata before the message is reached.

I like the more detailed INFO loggers yet a nice middle ground seems to be the more trim logging format shown above.

I did make an attempt at adding separate debug and info loggers in the place where the app starts so that we could have cleaner INFO logs and more detailed DEBUG logs yet the hio.ogler.getLogger(...) implementation shown below prevents this by removing all logging handlers, to avoid duplicates, and then adds the three shown below.

class Ogler():
    ...
    def getLogger(self, name=__name__, level=None):
        """
        Returns Basic Logger
        default is to name logger after module
        """
        logger = logging.getLogger(name)
        logger.propagate = False  # disable propagation of events
        level = level if level is not None else self.level
        logger.setLevel(level)
        for handler in list(logger.handlers):  # remove so no duplicate handlers
            logger.removeHandler(handler)
        if self.consoled:
            logger.addHandler(self.baseConsoleHandler)
        if self.syslogged:
            logger.addHandler(self.baseSysLogHandler)
        if self.filed and self.opened:
            logger.addHandler(self.baseFileHandler)
        return logger

Are we okay with either one of the two log format strings I showed here?

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

Successfully merging this pull request may close these issues.

3 participants