During the first phase of the project I had to make several design decisions. My mentor was a big help on each of them and so far I am pleased with how they turned out. Reading through the chats we had, I am amazed at how many decisions were based on the input of my mentor.
The biggest decision was to base the dashboard on Forms. My DashboardForm subclasses Form. To provide callbacks to the Controllers that are associated with the panels, it intercepts the httpSubmission method. In this case, the idea was mine, but it solidified during a discussion with my mentor.
Another nice example of my interaction with my mentor is the way that adding things to the dashboard is currently handled. I was originally thinking along the lines of directly adding the FormFields to that Form. My mentor suggested using an intermediary object, and thus DashboardPanel was born. After implementing it, I stumbled across a problem with the log tab. When I talked about this to my mentor he told me that Session is initiated at a later stage, making it necessary to insert data that is loaded via Session at a later point. This lead to the method getPanelContent, which allows adding data at a later stage.
Yesterday, I ported dbprofiler to my dashboard. It was amazing to see how easy and fast this could be done. It took me longer to switch the jQuery table sorter to an implementation that works with current versions of jquery than to move dbprofiler to my dashboard. If you want to see how it works check out the dashboard branch.
SilverStripe Developer Toolbar
A 2012 Google Summer of Code project.
Jul 24, 2012
Jul 13, 2012
Halftime
The midterm evaluations have taken place this week, marking the half time in my project.
So far, I have a working module that can already be used an integrates with the existing SS_Log / Zend_Log infrastructure. The UI is based on SilverStripe Forms, something which developers are already familiar with.
A nice thing this week was the implementation of the DashboardLogFilter, which allows enabling or disabling logs for URL patterns. The Zend_Log infrastructure made writing this very easy, it's just a class that implements Zend_Log_Filter_Interface. At the beginning of the implementation I came across the point where I thought: "there is no way to make sure this works by manual testing", so I actually started writing the unit tests before implementing most of the functionality. This is the first time I tried my hands at a tests first approach and I am very pleased with the way this turned out.
Next week I'll be taking a break, and after that it's back to coding. Apart from the smaller things that are collected in my issues list (https://github.com/jakr/developer_dashboard/issues), I will try to integrate the existing dbprofiler extension with my dashboard. This is a good first test to see if my API is complete and if someone else's code will actually be able to use the dashboard. And if it works I get a fully functioning query log as a free extra.
So far, I have a working module that can already be used an integrates with the existing SS_Log / Zend_Log infrastructure. The UI is based on SilverStripe Forms, something which developers are already familiar with.
A nice thing this week was the implementation of the DashboardLogFilter, which allows enabling or disabling logs for URL patterns. The Zend_Log infrastructure made writing this very easy, it's just a class that implements Zend_Log_Filter_Interface. At the beginning of the implementation I came across the point where I thought: "there is no way to make sure this works by manual testing", so I actually started writing the unit tests before implementing most of the functionality. This is the first time I tried my hands at a tests first approach and I am very pleased with the way this turned out.
Next week I'll be taking a break, and after that it's back to coding. Apart from the smaller things that are collected in my issues list (https://github.com/jakr/developer_dashboard/issues), I will try to integrate the existing dbprofiler extension with my dashboard. This is a good first test to see if my API is complete and if someone else's code will actually be able to use the dashboard. And if it works I get a fully functioning query log as a free extra.
Jun 11, 2012
Quick update
It's now three weeks into the coding phase. So far the coding itself has been smooth, but I could commit less time to the project than I had expected. The semester at my university ends in June and last week I had no time for my project at all. I only had a quick chat with my mentor.
The week before I did a a proof of concept implementation (see the github repository at <https://github.com/jakr/developer_dashboard/>). It's in a very rough state but it shows what I aim for on the logging side.
This week I'll work on integrating the urlvariabletools. This will require some logic that allows adding tabs, buttons, and other UI elements to my dashboard.
The week before I did a a proof of concept implementation (see the github repository at <https://github.com/jakr/developer_dashboard/>). It's in a very rough state but it shows what I aim for on the logging side.
This week I'll work on integrating the urlvariabletools. This will require some logic that allows adding tabs, buttons, and other UI elements to my dashboard.
May 21, 2012
Planning
Two weeks ago I had a long chat with my mentor about the project. For the rest of the week I was busy with university, so I did not work much on my project in that time. This week we just had a short call.
For information gathering we need to come up with a way of representing objects that should be logged. The logger should be context aware and support both HTML and command line output. The functions that call the logger should not include HTML output.
In the initial implementation, the dashboard will use the stream identifier as the tab name. If needed, we could extend it later by separating the tab concept out from the stream identifier.
At the midterm goal I will have completed the POC, fleshed out the server side debugging capabilities, and a basic interaction with the front end working. This includes a view to display some of the current debugging options in the new dashboard and an expanded ajax handler to provide this additional data to the dashboard.
Some more requirements
In our chat we came across some requirements that I had not taken into account before:- Debugging and logging should happen around streams. Each module can either write to an existing stream or start a new one. This way, a developer can pick and choose the level of debugging info he wants to receive.
- Log Streams are loosely coupled to modules by a naming convention: sapphire_sql.
- The developer needs to be able to choose what he is interested in. For that, there needs to be a list of all available streams. Therefore, any module (including the sapphire framework code itself) that can publish debug streams needs a way to say "I generate this, this and this". It should be able to tell the logging framework what streams they generate. Setup could be a matter of classes implementing an interface, or calling a method to register the stream.
- Performance: When debugging is disabled, we should cause only a low
overhead . The modules need to be aware of what streams of debugging
they should be producing. Sometimes it is expensive for modules to
generate and collect the debugging information, so they shouldn't do
anything if nobody wants to look at the result. Something like:
if(Debug::streamEnabled($streamID)) Debug::log(blah);
- Debugging info can be generated in the framework before the framework is set up. e.g. before there is a DB connection. So the mechanism should not be at too high a level of abstraction. Early parts of the request have to be able to generate debugging info too, in case the developer has enabled the streams.
- The dashboard controller could record the debug events in the session, and maybe keep the last n requests there. That way, the developer dashboard could show details across multiple requests.
- Easy way to print out debugging information. It should be as simple as calling Debug::show().
- Filtering / sorting into tabs probably has to be done client side, because a interleaved display is also possible (i.e. output from all streams, sorted by time).
Structure
Starting from these requirements, the logging framework breaks down into three components:- Registering a capability to generate debugging events.
- Capturing those debugging events while a request is processing.
- Forwarding them to the dashboard and displaying them.
For information gathering we need to come up with a way of representing objects that should be logged. The logger should be context aware and support both HTML and command line output. The functions that call the logger should not include HTML output.
Workflow
- The developer selects a control somewhere to turn on the dashboard
- The dashboard has a list of debugging streams to choose from.
- The dashboard saves the developer's preferences to his session.
- During the processing of the next requests (could be a normal page view or via AJAX), code on the execution path writes to it's debug stream (in case the stream is enabled).
- The dashboard controller sends the event data to the dashboard.
- the dashboard displays that event data in an organized way.
Setup
We discussed two versions how the setup could work:- The code that wants to have something logged can just say "put this text there" and the logging code sorts out the rest - Much like you currently add fields to the CMS back end
- Modules generate data streams.
In the initial implementation, the dashboard will use the stream identifier as the tab name. If needed, we could extend it later by separating the tab concept out from the stream identifier.
Timeline
Not all things that are discussed here might end up in the project. Nevertheless, this blog is a first step to documented them as future enhancements.Before Midterm
In the first two weeks I will work on a proof of concept (POC) implementation. It consist of an implementation of the log writer including the log() support method and a simple front end with no fancy bits. It writes the event data to a simple list in session. This will include some basic AJAX capability. Furthermore, I want to complete ticket 2644. Therefore, I will write a global error handler and provide event streams for exceptions and user errors.At the midterm goal I will have completed the POC, fleshed out the server side debugging capabilities, and a basic interaction with the front end working. This includes a view to display some of the current debugging options in the new dashboard and an expanded ajax handler to provide this additional data to the dashboard.
After Midterm
After the midterm I will be away for a week, so I only have three weeks. In the second part, I will flesh out the UI of the dashboard itself. This consist of:- organization of events by tab,
- an option to view the events sequentially (i.e. information from all tabs combined, ordered by time),
- ability to expand and collapse different parts to control the level of detail,
- ability for the developer to select the streams they want to have generated and displayed (client side UI) and
- server side preference storage - number of requests to store, which streams should be generated, etc.
- May 21st - June 3rd: Proof of Concept Implementation
- June 4th - June 17th: Server Side debugging: Reorganize the way debugging is done.
- June 18th - July 1st: Front End Interaction, include existing urlvariabletools in dashboard
- July 2nd - July 13th: Finish leftovers from previous tasks, start working on frontend UI
- July 13th: Mid term
- July 15th-July 21st: Not working on GSOC
- July 22nd-August 5th: Work on frontend UI
- August 6th-August 9th: Cleanup
- August 9th: Pencils down
- August 10th-August 19th: Not working on GSOC
May 7, 2012
Additional Requirements
In the last post I did not include everything that was covered by my initial proposal and the discussion on the mailing list.
Context Awareness
In ticket 5768 context awareness is brought up. Some parts of SilverStripe can be run from the command line. The logging/debugging functionality should be aware of this, i.e. no html output in command line mode. This fits well with my idea that the all code that is concerned with formatting / output should be in a central place, either in the logging class or somewhere elseDebugging Fatal Errors
Sometimes we will need to debug fatal errors. Since we cannot send any output after the error occurred, we will need to bypass any caching that we do and dump messages as soon as they come in.Author Toolbar
This feature is not included in the default blackcandy theme and therefore probably not well known (at least I never heard about it before this project). I should check if any things that I introduce for the developer dashboard can be applied to this toolbar as well.Additional Features
- Debugging/Displaying the generated YAML configuration
- other things
Optional Stuff
FirePHP integration and anything else we come up with if I finish early and get bored.May 4, 2012
Rough Ideas
On April 25th I had a first chat with my mentor. First, we got to
know each other a bit. We then started to talk about the project. We
agreed that I will post the results of our weekly meetings on this blog.
My next steps are to
In my original proposal I talked about a toolbar. This term is usually used for one or more rows of icons, but my toolbar will also contain other information, such as debug output. Therefore, I will talk about a dashboard instead. This dashboard contains several tabs, any tab can be a toolbar (in the conventional sense).
Debugging is mostly concerned with what happens within one request. The data is usually displayed but not kept around. Logging is used to check for things that change between different requests. Debugging will therefore be concerned with things like displaying the values of variables, checking if a statement is reached ("I'm here") and viewing the generated SQL statements.
Logging is more about aggregating information from multiple requests to check if everything works, and what changes in a case that triggers a bug.
Some of the content and settings will have to be persisted in some way, to be available across different requests. This could be done in a log file or in the user session.
When dumping objects, it would be very nice to be able to
In some cases, however, it would be useful to have all information in one place. This would make it easier to see which value of a variable results in which SQL statement. I am not sure how well this fits with the way I imagine the toolbar to work.
One question is how feasible it is to generalize debugging/logging of objects. Dumping should be relatively straightforward, but in many cases it would be interesting to display only the relevant parts of an object's state. Usually only the object itself knows which information is most relevant in the current context.
Logging is possible on various levels (e.g. warn, info, debug), and the developer is able to configure the required level of detail on a per module basis, e.g.
So far I haven't had a look at the new way configuration is done in SS3, so the way that this works might be actually a little different. Regardless of the way configuration is done, a developer will be able to specify which type of information he is currently interested in.
Therefore, we need an API that allows modules to add tabs and content to the dashboard.
For me, the front end features are much more tangible. Therefore, they are much easier to think and talk about. The back end components are much more vague.
My next steps are to
- get familiar with git,
- start working with my fork of the sapphire framework and
- flesh out my project plan in more detail.
In my original proposal I talked about a toolbar. This term is usually used for one or more rows of icons, but my toolbar will also contain other information, such as debug output. Therefore, I will talk about a dashboard instead. This dashboard contains several tabs, any tab can be a toolbar (in the conventional sense).
Debugging vs. logging
In the context of my project "debugging" will be short for "displaying debug information". Of course there is much more to debugging (like the ability to set breakpoints, inspect variables and to step through code, etc.), but this is excluded from the project. Logging is a more general form of displaying debug information, I will therefore treat debugging as a special type of logging.Debugging is mostly concerned with what happens within one request. The data is usually displayed but not kept around. Logging is used to check for things that change between different requests. Debugging will therefore be concerned with things like displaying the values of variables, checking if a statement is reached ("I'm here") and viewing the generated SQL statements.
Logging is more about aggregating information from multiple requests to check if everything works, and what changes in a case that triggers a bug.
Role within SilverStripe
The project will touch several parts of sapphire (the SilverStripe framework). I will unify and improve upon the existing logging functionalities.Front End
The front end part is the "developer dashboard". When a site is in development mode and an administrator is logged on, a button is displayed on the front end. If the admin clicks on this button, the dashboard opens. It contains tabs that display information, such as the output of debug statements, the contents of $_GET and $_POST and SQL queries. It also contains an easily way to access the urlvariabletools. This might be in form of a toolbar, i.e. a list of icons.Some of the content and settings will have to be persisted in some way, to be available across different requests. This could be done in a log file or in the user session.
When dumping objects, it would be very nice to be able to
- expand and collapse branches and to
- explore their relations.
tail -f
command in UNIX.Grouping Information
In most cases, we would want to group information by type. All SQL statements are on the "SQL" tab, debug output is on the "Debug" tab, etc.In some cases, however, it would be useful to have all information in one place. This would make it easier to see which value of a variable results in which SQL statement. I am not sure how well this fits with the way I imagine the toolbar to work.
Back End
The project basically breaks up into two parts. The first is responsible for collecting and displaying information for logging and debugging. The second part is the infrastructure that allows modules to add information to the developer dashboard.Logging
One aim of this project is to unify the existing logging functionality, which is spread around SS_Log, Debug as well as many other places. Like the existing logging system, this will be based on Zend_Log.One question is how feasible it is to generalize debugging/logging of objects. Dumping should be relatively straightforward, but in many cases it would be interesting to display only the relevant parts of an object's state. Usually only the object itself knows which information is most relevant in the current context.
Logging is possible on various levels (e.g. warn, info, debug), and the developer is able to configure the required level of detail on a per module basis, e.g.
LoggerClass::setLogLevel('MyModule', LoggerClass::LEVEL_DEBUG)
.So far I haven't had a look at the new way configuration is done in SS3, so the way that this works might be actually a little different. Regardless of the way configuration is done, a developer will be able to specify which type of information he is currently interested in.
Dashboard
The dashboard should in principle be agnostic of the rest of the logging functionality. It is a thing that displays information. Any module can display information on this dashboard. The urlvariabletools could add icons to a toolbar. The database driver could add the SQL tab. A custom module could add another tab.Therefore, we need an API that allows modules to add tabs and content to the dashboard.
In between
Some things are needed in between these two parts. I currently think about:- A way to register URL parameters. Per module this can be done in the controller, but I don't know how "global" URL paramters, like isDev are currently handled.
- A way to persist settings in the user session. Some of the global settings should be persisted. This way, a developer can navigate the site without having to apply a certain parameter to every URL.
- Some general code to dump an object.
- And probably many other things I overlooked.
Personal Notes
I am still trying to grasp the whole project, to come up with a list of the features that are needed and how they relate to the existing framework. It is quite difficult for me to turn the high level ideas into "bullet points", i.e. break them up into tasks and milestones.For me, the front end features are much more tangible. Therefore, they are much easier to think and talk about. The back end components are much more vague.
About this blog
My proposal for this year's (2012) Google Summer of Code (GSoC) has been accepted, and I am looking forward to working with my mentor for the SilverStripe CMS. I will be working on tools that support SilverStripe developers. The proposal that I submitted can be found on Google melange and on the SilverStripe GSoC Wiki.
I will use this blog to share my experiences during the GSoC.
I will use this blog to share my experiences during the GSoC.
Subscribe to:
Posts (Atom)