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

debug module events panel #3842

Closed
Ragazzo opened this issue Jun 12, 2014 · 30 comments
Closed

debug module events panel #3842

Ragazzo opened this issue Jun 12, 2014 · 30 comments

Comments

@Ragazzo
Copy link
Contributor

Ragazzo commented Jun 12, 2014

Usually when creating application and using EDA or SOA it is good to have ability to check events and data that they hold.
I think this panel would be useful in debug module, several modern fw also includes it.

The only thing here we have to solve is how to subscribe to all or part of events, since we dont have wildcard matching and we dont have any central point for event. My suggestion is to either add wildcard matching or introduce in events panel property neededEvents in format:

'neededEvents' => [
     'some\component\class' => [
          //list of events to subscribe
     ],
],

In the same way we can make exclude option. Data that will be collected upon each event is its public properties json encoded or we can use Yii2 var_export not sure about the last one though .

@cebe
Copy link
Member

cebe commented Jun 13, 2014

What would you display in the panel? What information exactly?

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 13, 2014

what events occured in system and with what data, for example:

UserSignupedEvent([
   'user' => ...,
])
UserChangedPasswordEvent([
   'user' => ...,
   'oldPassword' => ...,
   'newPassword' => ...
])
ItemOrderAddedEvent([
     'item' => ...,
     'order' => ...
])

and so on. You can look for similar things in L4 or Symfony .

@cebe
Copy link
Member

cebe commented Jun 13, 2014

👍

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 13, 2014

@cebe Also i think we should add maxNestedLevel for collecting data from events, so if it is object than if level is 2 we will also collect data from its objects that are accessible through public properties.
Will work on this one .

@samdark
Copy link
Member

samdark commented Jun 13, 2014

Could be useful.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 14, 2014

Also, @qiangxue @samdark need your advice here, we have 2 ways to implement this one:

  • directly subscribe to needed events (debug event handlers will be the first one since it is in preload section);
  • use Yii::trace + VarDumper::export().

As for me first one (events) approach is better. In the same way we can then make then Assets and Views rendering tracking. What your thoughts on this one ?

@samdark
Copy link
Member

samdark commented Jun 14, 2014

I'd go for events.

@klimov-paul
Copy link
Member

directly subscribe to needed events

How are you planing to do this? There is no way to specify event handler (event a class event handler) without knowing the event name. This means you should either specify all affected events at panel config, which reduces the benefit of such panel, or try to define it in automatic mode, which elimiates the ability to track any custom events.

use Yii::trace + VarDumper::export()

Would not this produce too much log entries at the end of application run? What about memory usage?

@samdark
Copy link
Member

samdark commented Jun 16, 2014

Using trace will produce lots of log entries in debug mode, true. That's why I prefer adding an ability to subscribe to any events. Of course, it should be performance-profiled since it will require executing some additional code on each event.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

@klimov-paul

This means you should either specify all affected envents at panel config, which reduces the benefit of such panel,

this is how it supposed to be used. I dont think that developer will change subscribed events very often. It is only one time setup, see above first comment about how to configure panel. So i think it will be implemented with first approach, direct subscribing to events.

@klimov-paul
Copy link
Member

Such panel may be very useful while debugging application, because it allows to see, which events are actually fired. This is exceptionaly useful for the newcomers, who may not yet realize how events work and what they may affect.
Using predefined list of event names at this panel is just like using predefined list of query patterns for DbPanel.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

@klimov-paul not sure if i understand you ) you are against or for this one ? Mainly it is not for newcomers but for EDA and SOA applications, yet we can make somethign like EventPanel::subscribeToCoreEvents = true , that will make easily for developers to debug core events too without need to specifying them. But yet main approach it like in first comment .

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

Also stacktrace should be supported ofcourse .

@klimov-paul
Copy link
Member

You can look for similar things in L4 or Symfony

What was their solution on this matter?

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

they have central point and if needed can subscribe with wildcards, that was restricted and discarded in Yii2 .

@klimov-paul
Copy link
Member

Also do we really need to log all fired events? Does it makes sense?
For me the main interest will be seeing events, which have some handlers attached to them, so I can see at which stage normal program flow is affected.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

Well, main thing here is that event is raised and not that handler is attached to it, handlers can cause some 3rd party libs to act, and developer can deatach them for debugging purposes, so we should only catch events.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

so should i implement this one ? will also check on how to collect info about called and not called listeners too, as it is done in syfmony webprofilerbundle.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

@klimov-paul as for your request, we can make it in two ways:

  • adding Yii::trace after calling each subscriber of the event in Component class;
  • raising SubscriberCalledEvent after each subscriber is called in Component class.

What do you prefer better ? As for me last one is better.

@klimov-paul
Copy link
Member

raising SubscriberCalledEvent after each subscriber is called in Component class

Don't we trying to track all events here? Who will track SubscriberCalledEvent then?

adding Yii::trace after calling each subscriber of the event in Component class;

Perhaps Yii::trace is an only option here. Still there is no necessity of calling it after each handler. For the log it will be enough to see list of assigned handler callbacks.

so should i implement this one ?

Сertainly it worth trying. Maybe having some implementation at sight we can figure out all details.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

Don't we trying to track all events here?

some kind of, SubscriberCalledEvent will be tracked by EventPanel and maybe some other developers custome code that need to know if was called some subscriber or not. So i prefer adding Event here, i dont think that it can downgrade performance since often it will be unused, however it is a good thing.

@klimov-paul
Copy link
Member

Would not it create a recursion inside the code?

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jun 16, 2014

well, for this case user just need to handle this situation by himself as for me. We can get in trouble with recursion almost at any event if it can trigger actions that are generating event on what class is subscribed. So i think it is fine here.
In this case handler that is subscribed to SubscriberCalledEvent will not be triggering any event, so we will not get in trouble.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jul 12, 2014

@qiangxue @klimov-paul need your opinion here for this question and probably solutions:

Question:

We need to get list of all subscribers to the particular event of component and track what subscribers where called and what was not.

Solution:

the only good solution i see as was noted by introducing new event to make it possible to determine on what event subscriber was called, We cant use someYii::trace() since it will not contain info about particular event instance and we cant get from it on what event instance exactly subscriber was called.

Will this (introducing new event) result in some performance disadvantages? Currently it is the only way as i see to solve this problem.

Brief overview:

//in events panel after catch event

$this->_eventsInfo[$eventId]['subscribers'] = $event->sender->getSubscribers();

//after catch SubsriberCalledEvent
$this->_eventsInfo[$eventId]['called_subscribers'] = $event->subscriber;

of course above is just short code to get understading of how it should works. So what would be the solution? Maybe we need to check performance but currently i don't understand how to do this. Also not sure if it will have big impact on performance since this event is more for some internal processing and usually developers should not use it.

Also where is Component::getEventHandlers() method, i remember it was there?

@qiangxue
Copy link
Member

I don't think we should raise another event for each event. It's too much overhead and also mess up with the normal event triggering workflow.

Yii::trace() can take complex data as its first parameter. However, I also think this is not a good approach because the data will be held in the logger, which may have big impact in memory usage (because the data may be big, unlike normal string messages).

I think we may consider introducing some broadcasting mechanism (something like global events but much lighter). For example,

// register a callback for a specified channel
Yii::watch('channel', $callback);

...

// send $content to the channel, which will call the callbacks registered with the channel
Yii::broadcast('channel', $content);

Now inside of Component::trigger(), we can call Yii::broadcast() and send the event object.

This mechanism is a bit similar to the event mechanism, but it's much lighter because it doesn't need to create a new event object, and the watchers are not allowed to interrupt the broadcasting (event handlers can stop event handling).

This is just a rough idea. Not sure if there's any loophole.

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jul 13, 2014

i see, so callback will have $event as it parameter. So maybe then remove all events with this one and using array instead of classes? I am not sure about this one because it may confuse people when to use event and when broadcasting, is there any clarification line?

For now will implement first part without history of called / not called subscribers . And same question as in above:

Also where is Component::getEventHandlers() method, i remember it was there?

How to get all subscribers?

@qiangxue
Copy link
Member

Callback will get $content as its parameter.

Nope, this will not replace the current event mechanism. In most cases, you should use events which are essential if you want a component to support behaviors.

You may view this approach as a sort of logging. The difference is that the content is processed right away instead of being sent to the targets in batches. Also, no inspection on this approach will be supported.

We can add getEventHandlers().

@Ragazzo
Copy link
Contributor Author

Ragazzo commented Jul 13, 2014

We can add getEventHandlers().

yes, that would be great, not sure why it was removed. Not critical for now though, after first implementation we can do this

@dynasource
Copy link
Member

thanks Paul.
I see that this discussion is already 8 months old, but hasnt lost its relevance. In my opinion Ragazzo has a good point in that Events should be logged. EDA or SOA are already some kind of magic inside your application architecture, why not showing these in the Debug toolbar? Use case could be:

  • spot unnecessary events
  • spot events that weren't closed yet
  • see the order of events

Of course, this functionality should not go at too much cost of memory. I think we should keep it easy. A simple trace of $class + $name should be already enough to get a good point of whats happening (see #7277) at what time.

When using Event to trace & debug data, performance will be lost. Solutions like Qiang suggested, are then necessary. It will definately be of use, as we can then put a magnify glass on specific data throughput. It should be optimal though, performance wise.

@yii-bot
Copy link

yii-bot commented Jan 24, 2016

Issue moved to yiisoft/yii2-debug#77

@yii-bot yii-bot closed this as completed Jan 24, 2016
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

7 participants