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

Added a new ResettableInterface and implemented it where possible. #997

Merged
merged 2 commits into from
Nov 4, 2018

Conversation

lyrixx
Copy link
Contributor

@lyrixx lyrixx commented May 31, 2017

Added a new ResetableInterface and implemented it where possible.

When one use Monolog in a long process like an AMQP worker with a
FingersCrossedHandler or BufferHandler there is a drawback: as soon as there
is an AMQP message that generate a log >= error (for example), all next AMQP
messages will output logs, even if theses messages don't generate log where
level >= error.

In the same context there is a drawback for processor that add an UUID to the
logs. The UUID should change for each AMQP messages.


This patch address this issue with a new interface: ResettableInterface interface.
Side note: reset(), flush(), clear(), are already used in Monolog. So
basically, one can use the reset() on the Logger and on some
Handlers / Processors.

It's especially useful for

  • the FingersCrossedHandler: it close() the buffer, then it clear() the buffer.
  • the BufferHandler: it flush() the buf

@lyrixx
Copy link
Contributor Author

lyrixx commented Jun 1, 2017

I forgot to say that we are using this "feature" for years at SensioLabs. But in a very hacky way (with reflection). IMHO, it's better to expose a clean API. That's why I created this PR.

@Seldaek Seldaek added this to the 2.0 milestone Jun 19, 2017
@lyrixx
Copy link
Contributor Author

lyrixx commented Apr 5, 2018

This PR needs a rebase, but before finishing it I would like to be sure If it will/could be merged.

More over Symfony get a new component: Messenger. So (I hope so) AMQP (or other queue system) will become more standard. So people will expects a nice logging system.

ping @fabpot @nicolas-grekas @sroze

Next step: wire this restart method after each message processed in the Messenger Component

Copy link
Contributor

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

LGTM, just one comment

@@ -43,4 +45,9 @@ public function getUid(): string
{
return $this->uid;
}

public function restart(int $length = 7)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd suggest to store the length as a property instead of adding in here

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed. None of the APIs are calling it with a value anyway, and we want it to be called with the original config.

@nicolas-grekas
Copy link
Contributor

Next step: wire this restart method after each message processed in the Messenger Component

and on container reset

@stof
Copy link
Contributor

stof commented Apr 5, 2018

Why is it in the 2.0 milestone rather than adding this new feature in 1.x (2.0 is kind of stale, and Symfony will have a hard time moving to it due to the non-continuous migration path for handler authors currently)

@@ -325,6 +325,21 @@ public function addRecord(int $level, string $message, array $context = []): boo
return true;
}

public function restart($a = null)
Copy link
Contributor

Choose a reason for hiding this comment

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

why having an argument here ?

@@ -43,4 +45,9 @@ public function getUid(): string
{
return $this->uid;
}

public function restart(int $length = 7)
Copy link
Contributor

Choose a reason for hiding this comment

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

agreed. None of the APIs are calling it with a value anyway, and we want it to be called with the original config.


public function restart(int $length = 7)
{
$this->__construct($length);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would rather move the uid generation to a private method and call it, rather than reusing __construct (which will be necessary anyway when applying the suggestions). I don't want to push people to think that calling __construct as a method is a supported usage of the library.

@lyrixx
Copy link
Contributor Author

lyrixx commented Apr 5, 2018

Why is it in the 2.0 milestone

I would prefer 1.X yes.

@stof
Copy link
Contributor

stof commented Apr 5, 2018

Well, I think the 2.0 milestone is because this was submitted to master.

Copy link

@sroze sroze left a comment

Choose a reason for hiding this comment

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

I don't see either why it would be 2.0 as there is no harm in having that now.

src/Monolog/RestartableInterface.php Outdated Show resolved Hide resolved
@@ -43,4 +45,9 @@ public function getUid(): string
{
return $this->uid;
}

public function restart(int $length = 7)
Copy link

Choose a reason for hiding this comment

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

It's very unlikely that this is going to have its argument populated anyway because the chains don't forward the arguments. Instead, I'd use strlen($this->uid) as __construct argument (or store $length as a property).

Copy link
Contributor

Choose a reason for hiding this comment

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

getting the length of the existing uid is a nice trick to get it 😄

@lyrixx lyrixx changed the base branch from master to 1.x April 5, 2018 15:09
@lyrixx
Copy link
Contributor Author

lyrixx commented Apr 5, 2018

Thanks. I have addressed your comments and now this PR targets the 1.X branch.

@@ -0,0 +1,25 @@
<?php declare(strict_types=1);
Copy link

Choose a reason for hiding this comment

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

Is that OK even if Monolog's 1.x's target is PHP 5.3 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oups ;)

@lyrixx lyrixx force-pushed the resetable branch 2 times, most recently from eb81195 to 535b8c5 Compare April 5, 2018 16:18
@lyrixx
Copy link
Contributor Author

lyrixx commented Apr 5, 2018

There is a failure on HHVM, but for another test. So this PR is ready.

@fabpot
Copy link
Contributor

fabpot commented Apr 6, 2018

I would recommend to drop HHVM support as almost all project have done by now (even on 1.x).

@lyrixx
Copy link
Contributor Author

lyrixx commented Jun 7, 2018

Rebased and green.

@nicolas-grekas How could we handle your new ResettableInterface from symfony/symfony#27093 ?

  1. Include the deps here
  2. create a bridge/decorator in Symfony ?
  3. ???

@nicolas-grekas
Copy link
Contributor

s/RestartableInterface::restart()/ResettableInteraface::reset()/?
then later one add the Symfony interface on the classes here (or as a child of the Symfony interface?)

@lyrixx
Copy link
Contributor Author

lyrixx commented Jun 7, 2018

Hmm, reset is already used in monolog with a different meanings.

IIRC, this is why I choose restart instead of reset

@nicolas-grekas
Copy link
Contributor

a bridge/proxy would do it also

@Seldaek
Copy link
Owner

Seldaek commented Jun 18, 2018

Hey, this is something I wanted to support in 2.0, as well as having a Logger::close() to be able to close all handlers (as 2.0 has close in the HandlerInterface).

I am not against supporting this in 1.x though, but I wonder if we shouldn't call this reset rather than restart. The only name conflict is in the FingersCrossedHandler but really the only reason it has a reset() is to do exactly the same thing as this PR intends, so I don't think it's a problem at all, it just generalizes the concept to the rest of Monolog.

@Seldaek Seldaek modified the milestones: 2.0, 1.x Jun 18, 2018
@lyrixx lyrixx changed the title Added a new RestartableInterface and implemented it where possible. Added a new ResetableInterface and implemented it where possible. Jul 6, 2018
@lyrixx
Copy link
Contributor Author

lyrixx commented Jul 6, 2018

I updated the PR to rename ResartableInterface to ResetableInterface

@nicolas-grekas
Copy link
Contributor

s/ResetableInterface/ResettableInterface

@lyrixx lyrixx changed the title Added a new ResetableInterface and implemented it where possible. Added a new ResettableInterface and implemented it where possible. Jul 6, 2018
@lyrixx
Copy link
Contributor Author

lyrixx commented Jul 6, 2018

@nicolas-grekas Thanks ; done

* Handler or Processor implementing this interface will be reseted when Logger::reset is called.
*
* Reseting an Handler or a Processor usually means cleaning all buffers or
* reseting in its internal state.
Copy link
Contributor

Choose a reason for hiding this comment

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

double "t": resetted, resetting

@@ -77,7 +77,7 @@ class TestFirePHPHandler extends FirePHPHandler
{
protected $headers = array();

public static function reset()
public static function resetInternalState()
Copy link
Contributor

Choose a reason for hiding this comment

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

resetStatic?

@lyrixx
Copy link
Contributor Author

lyrixx commented Jul 6, 2018

@nicolas-grekas @Seldaek Should be ok ;)

namespace Monolog;

/**
* Handler or Processor implementing this interface will be reseted when Logger::reset is called.
Copy link
Contributor

Choose a reason for hiding this comment

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

resetted ;)
Logger::reset()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I used reset instead of resetted

When one use Monolog in a long process like an AMQP worker with a
`FingersCrossedHandler` or `BufferHandler` there is a drawback: as soon as there
is an AMQP message that generate a log >= error (for example), all next AMQP
messages will output logs, even if theses messages don't generate log where
level >= error.

In the same context there is a drawback for processor that add an UUID to the
logs. The UUID should change for each AMQP messages.

---

This patch address this issue with a new interface: `ResettableInterface` interface.
Side note: `reset()`, `flush()`, `clear()`,  are already used in Monolog. So
basically, one can use the `reset()` on the `Logger` and on some
`Handler`s / `Processor`s.

It's especially useful for

* the `FingersCrossedHandler`: it `close()` the buffer, then it `clear()` the buffer.
* the `BufferHandler`: it `flush()` the buffer, then it `clear()` the buffer.
* the `UidProcessor`: it renew the `uid`.
@nicolas-grekas
Copy link
Contributor

What do you think of symfony/symfony#27093 (comment)?

image

@Seldaek
Copy link
Owner

Seldaek commented Jul 9, 2018

We have FormattableHandler/ProcessableHandler interfaces already in master so Resettable is kinda in line with that, but maybe should be ResettableHandlerInterface for real consistency.

@Seldaek Seldaek merged commit a03084c into Seldaek:1.x Nov 4, 2018
@Seldaek
Copy link
Owner

Seldaek commented Nov 4, 2018

Thanks!

@Seldaek
Copy link
Owner

Seldaek commented Nov 4, 2018

Hey folks so just one more thing before I release this in 1.x.. The more I look at it especially in the master branch for 2.0 where I made close() part of the HandlerInterface, it seems to me like close() and reset() do essentially the same thing.. Or at least they should. Do you also see it like that or not? If so I am thinking to just remove close() in 2.0 and make HandlerInterface implement ResettableInterface. I think it'd simplify things, and it resolves what I had in mind for #197 to add Logger::close() to close all handlers as Logger::reset() was part of this PR.

@nicolas-grekas
Copy link
Contributor

If we want to identify a difference, I could see this one: reset is meant to put a service back in a reusable state. This does not necessarily imply closing connections to remote backends. Actually, when using the same kernel in a loop, having connections already open for next requests should be a significant part of why these apps are faster (ie no PDO::__construct() overhead).
Not sure how it applies here, so that's just for thoughts :)

@Seldaek
Copy link
Owner

Seldaek commented Nov 4, 2018

That makes sense yes, although I don't know how many handlers would actually benefit from this distinction. But then I need to change the implementation a bit, because right now reset() calls close(), so things are even more confusing.

It seems to me like the main use case for reset() is fingers crossed and buffer handlers to make sure they're cleared in between two requests/jobs in long running apps.

The use case for close() is to do some cleanup at the very end, but also right now that's when we flush buffers and stuff like that, so I guess in the buffer case you'd want to flush on reset instead of close. And then close() would become mostly useless, except sometimes it calls reset() to flush, and in a few rare cases it closes some resource. Makes sense? Mostly thinking out loud here..

@nicolas-grekas
Copy link
Contributor

Makes sense to me yes :)

@sroze
Copy link

sroze commented Nov 4, 2018 via email

@Seldaek
Copy link
Owner

Seldaek commented Nov 4, 2018

OK see e07c948 for changes/clarifications. Happy to get any feedback on this.

@Seldaek
Copy link
Owner

Seldaek commented Nov 4, 2018

b803523 is the core of the changes for 1.x but I messed up the commit msg :s

@lyrixx lyrixx deleted the resetable branch November 5, 2018 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants