Skip to content

Add Logging engine Log::Any and add support for context logging#1761

Draft
mikkoi wants to merge 1 commit intoPerlDancer:mainfrom
mikkoi:add-log-any-engine
Draft

Add Logging engine Log::Any and add support for context logging#1761
mikkoi wants to merge 1 commit intoPerlDancer:mainfrom
mikkoi:add-log-any-engine

Conversation

@mikkoi
Copy link
Contributor

@mikkoi mikkoi commented Jan 25, 2026

Log::Any has a new feature: Logging structed data. Essentially it means that you can add a hash after or in place of the logging message.
This can be really convenient if you simultaneously write the information into logs as JSON and pump the JSON into a logviewer where you can search or categorise by any JSON element.

This PR adds a logger engine for Log::Any and changes Dancer2::Core::Role::Logger to support the action.

@xsawyerx
Copy link
Member

Is there a particular benefit to putting this in core instead of a plugin on CPAN?

@mikkoi
Copy link
Contributor Author

mikkoi commented Jan 25, 2026

Is there a particular benefit to putting this in core instead of a plugin on CPAN?

No.

I actually considered that: building the whole thing as a plugin. That would mean creating a new set of keywords and a lot of duplicate code. I am okay with that.

However, I also wanted to raise the point that Dancer2's logging has shortcomings. It is not possible as it is to do what I need. I think we should consider Log::Any's example.

A true overhaul is not possible, though, because that would mean incompatible changes to the API.

@mikkoi mikkoi marked this pull request as draft January 25, 2026 11:59
@xsawyerx
Copy link
Member

However, I also wanted to raise the point that Dancer2's logging has shortcomings. It is not possible as it is to do what I need. I think we should consider Log::Any's example.

Good to raise this point. Is there anything you would suggest to improve specifically? Maybe this could lead to a core improvement, regardless of this being merged into core or not.

("Doing this in core is very difficult because of how core is" is a fair reason to suggest doing this in core, but it also raises the question of what we can do better in it.)

@cromedome
Copy link
Contributor

You can accomplish this already with Log::Any.

In your app config:

logger: LogAny
engines:
  logger:
    LogAny:
      logger:
        - JSON
        - structure.log

And then in your Dancer2 app:

get '/' => sub {
    debug { foo => 'bar', baz => 'bah' };
    template 'index';
};

Am I missing something?

Recommend we close this. I could do a PR to add this to the cookbook. What do y'all think?

@racke
Copy link
Member

racke commented Jan 25, 2026

Yes, makes sense to me.

@mikkoi
Copy link
Contributor Author

mikkoi commented Jan 25, 2026

You can accomplish this already with Log::Any.

This doesn't work for me. It does not support structured logging.
Example of how structured logging could work:

info 'Create user', { user => 'Mikko', request_id => 123, trx_active => 1, };

And then the output would be:

{"level":"info","category":"MyApp:Web","message":"Create user","user":"Mikko","request_id":123,"trx_active":1,"file":"/[..]/lib/MyApp/Web.pm","line":234}

Additionally, to emulate Log::Any we could have command "log_context" to create "base" context for all logging done within the scope:

{
    logging_context { request_id => 123, };
    info 'Create user', { user => 'Mikko', trx_active => 1, };
}

@cromedome
Copy link
Contributor

You can accomplish this already with Log::Any.

This doesn't work for me. It does not support structured logging.

It does; if you build a new skeleton app, make sure to disable the console logger in environments/development.yml. I just generated a new app from scratch and tried it. Can you try again and see if this meets your needs?

That being said, I find logging_context() intriguing.

@mikkoi
Copy link
Contributor Author

mikkoi commented Jan 31, 2026

You can accomplish this already with Log::Any.

This doesn't work for me. It does not support structured logging.

It does; if you build a new skeleton app, make sure to disable the console logger in environments/development.yml. I just generated a new app from scratch and tried it. Can you try again and see if this meets your needs?

It does close but not quite. I get this:

{"category":"Dancer2::Logger::LogAny","level":"debug","message":"{'baz' => 'bah','foo' => 'bar'}","timestamp":"2026-01-31T22:37:48.531242Z"}

When I want:

{"category":"Dancer2::Logger::LogAny","level":"debug","message":"","baz":"bah","foo":"bar","timestamp":"2026-01-31T22:37:48.531242Z"}

The problem is the {'baz' => 'bah','foo' => 'bar'} which would need to be processed separately.

It also doesn't handle a message and structure:

`debug "Something happens here", { foo => 'bar', baz => 'bah' };`

That being said, I find logging_context() intriguing.

We can add all sorts of additional info there which a logviewer can index.

@cromedome
Copy link
Contributor

I see two different things happening in this PR:

  • Fixing some shortcomings in Dancer2's logging
  • Adding Log::Any support to the Dancer2 core

Would you please submit this as two separate PRs? The core logging improvements I would 👍 in a hot minute. The other requires some discussion:

If we merge this, I'd need to see some more docs on how to configure this adapter with multiple Log::Any adapters.

I am always happy to see PRs from you @mikkoi :) Look forward to working through this with you.

@1nickt
Copy link
Contributor

1nickt commented Feb 3, 2026

Some thoughts:

I am in favor of adding support for structured logging to the core.

However, I think it's not needed to duplicate my plugin.

And, I would want the support to provide more options than simple Log::Any structured logging, i.e. arbitrary data structures -- not just a hashref -- as supported e.g. by Log::Any::JSON (which also provides millisecond timestamp resolution). This would require making _serialize more complex., though.

@mikkoi
Copy link
Contributor Author

mikkoi commented Feb 3, 2026

Thanks, @cromedome

This is quite radical proposal, but how about if we changed Dancer2's own logging system to Log::Any?
With the caveat that we can maintain backwards compatibility, of course.

@cromedome
Copy link
Contributor

This is quite radical proposal, but how about if we changed Dancer2's own logging system to Log::Any? With the caveat that we can maintain backwards compatibility, of course.

I don't have an immediate answer, and need to dwell on that for a bit. There's a lot to think over there, and I am not sure the gains are worth the effort. I think Log::Any is overkill for a lot of our users. Other core team members might have another view they'd like to share.

@cromedome
Copy link
Contributor

@mikkoi in the interim, I'd love a new/updated PR with the non-Log::Any part of this.

@veryrusty
Copy link
Member

changed Dancer2's own logging system to Log::Any

I use Log::Any extensively for $work projects; yet I'm not keen on using it for the default logger.

For our apps, we want consitent logging calls everywhere, which is why we chose Log::Any. That implies using $log->info("hey"); in scripts, business logic modules and within dancer routes rather than using the DSL keywords. (The existing Dancer2::Logger::LogAny handles core logs.)

@1nickt
Copy link
Contributor

1nickt commented Feb 4, 2026

SLIGHTLY OT ...

For our apps, we want consitent logging calls everywhere, which is why we chose Log::Any. That implies using $log->info("hey"); in scripts, business logic modules and within dancer routes rather than using the DSL keywords. (The existing Dancer2::Logger::LogAny handles core logs.)

Hi @veryrusty
I'm just curious what you mean when you say that you have to use $log in Dancer routes rather than the logging keywords. The logging keywords certainly can be used to log with the LogAny logger.

@veryrusty
Copy link
Member

what you mean when you say that you have to use $log in Dancer routes

I think I said we wanted consistency. Sure, the keywords work. But consistently using $log everywhere has its benefits; such as being able to easily grep your code to see where logs are generated, and I find I mentally grok $log quicker than the individual level keywords (but that may be because I've done it this way for so long!).

cromedome added a commit that referenced this pull request Mar 11, 2026
This also includes a few minor doc fixes, and some internal refactoring.

This is @mikko's patch, extracted from PR #1761.
cromedome added a commit that referenced this pull request Mar 11, 2026
This also includes a few minor doc fixes, and some internal refactoring.

This is @mikkoi's patch, extracted from PR #1761.
cromedome added a commit that referenced this pull request Mar 11, 2026
This also includes a few minor doc fixes, and some internal refactoring.

This is @mikkoi's patch, extracted from PR #1761.
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.

6 participants