In the same way that you can get information about Entities and Fields I think that we should create a page that show all the available services on a site.

I'm suggesting that we put this information on the /devel/service/info path, and use Drupal::service("kernel")->getCachedContainerDefinition() to retrive the available services and individual information about them.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tlyngej created an issue. See original summary.

lussoluca’s picture

Webprofiler (submodule of devel) already has a widget that show all the services defined, isn't enough?

tlyngej’s picture

Status: Active » Needs review
FileSize
1.83 KB

Nope! :-)

I really think that this should be available, in a basic format as the Entity and Field information are, in the Devel module itself.

lussoluca’s picture

Status: Needs review » Needs work

I really think that this should be available, in a basic format as the Entity and Field information are, in the Devel module itself.

Ok, just a couple of quick fixes:

  1. +++ b/src/Controller/DevelController.php
    @@ -232,4 +232,24 @@ class DevelController extends ControllerBase {
    +    $container_definition = \Drupal::service("kernel")->getCachedContainerDefinition();
    

    kernel service should be injected

  2. +++ b/src/Controller/DevelController.php
    @@ -232,4 +232,24 @@ class DevelController extends ControllerBase {
    +    foreach ($container_definition["services"] as $name => $definition) {
    +      $container_definition["services"][$name] = unserialize($definition);
    

    Can we use single quotes here?

Then we should wait for Moshe and willzyx to approve this.

tlyngej’s picture

@lussoluca

How do you say one can access those informations from the Webprofiler?

tlyngej’s picture

Status: Needs work » Needs review
FileSize
4.22 KB

I didn't inject the kernel service because the rest of the module was calling calling the static \Drupal::service(). The service is properly injected now.

The double quotes was just me being a lazy lad, copying code. Fixed now.

tlyngej’s picture

Bloody hell! I had some unwanted changes in that earlier patch.

This should not involve changes in webprofiler/src/DataCollector/TimeDataCollector.php :-)

tlyngej’s picture

lussoluca’s picture

FileSize
1.08 MB

Why your patch finds 608 services (on my test site) and Webprofiler 615?

andrewmacpherson’s picture

@tlyngej: I love it! Some feedback on your patch:

  • Why just the services ($container_definition['services']) and not the entire $container_definition? There is some useful stuff in the $container_definition['parameters'] for example.
  • Could the list of services be sorted alphabetically? It would make the list easier to browse.

@lussoluca - a comparison with the web profiler widget:

  • The services widget from web profiler isn't enabled by default. A minor point, but I didn't know it was available. The new page at devel/service/info automatically inserts into the Development menu block, the Druplicon menu provided by admin_toolbar_tools module, and the toolbox menu near the start of web profiler.
  • The service info page from this patch lets me see more information than webprofiler does. For example, the listing at devel/service/info identifies the factory method and arguments for a service.
  • Webprofiler identifies which (and how many) services are initialized for a given page load, which isn't really in scope here.
tlyngej’s picture

Excellent question!

Let's compare the webprofiler code with mine.

tlyngej’s picture

Snap! Looks like @andrewmacpherson beaten me to it :-)

@andrewmacpherson
I guess $container_definition['parameters'] would be useful as well. But I better put parameters and services in different UI containers, that can be expanded. So that the page doesn't looks so scary.

Excellent idea ordering by service name! I'll look into that.

tlyngej’s picture

This patch includes both parameters and services, wrapped up in collapsible fieldsets.

Both sorted by array key.

lussoluca’s picture

Why your patch finds 608 services (on my test site) and Webprofiler 615?

Webprofiler also shows private services. I should print this information somewhere so developers know that those services cannot be used directly (#2828361: Add more information to services widget).

willzyx’s picture

@tlyngej thanks for contributing!
I'm ok with the changes but IMHO the issue needs some work

  1. why not create a new controller (ServiceInfoController?) instead of polluting DevelController with the methods for all the functionalities?
  2. +++ b/src/Controller/DevelController.php
    @@ -232,4 +260,40 @@ class DevelController extends ControllerBase {
    +    $output['parameters'] = array(
    ...
    +      'content' => array(
    ...
    +    $output['services'] = array(
    

    can we use short array syntax?

  3. +++ b/src/Controller/DevelController.php
    @@ -232,4 +260,40 @@ class DevelController extends ControllerBase {
    +    $output['services'] = array(
    +      '#type' => 'details',
    +      '#title' => $this->t('Services'),
    +      'content' => array(
    +      '#markup' => kpr($container_definition['services'], TRUE),
    +      ),
    +    );
    

    we can inject devel.dumper service and use $this->dumper->exportAsRenderable($var) instead of manually create the render array and use kpr()

  4. and very important... we need test coverage for this!! :)

also (not blocking and to be explored) we could think to show the services/parameters in a table with js quick filter for a simpler and better UX.. If we do this what kind of info we will loose?

willzyx’s picture

Status: Needs review » Needs work
tlyngej’s picture

@willzyx

Sounds to me like you are pointing out a more general issue.

I agree that having all of the pages existing in one controller is about to get out of hand, but that's how it currently works. This is not what the issue is about.
I also agree that using shorthand arrays would be preferred, but again, that's not used in the rest of the file.

So I merely followed the existing protocol and did what others have done before me.

tlyngej’s picture

Gah, submitted comment to soon. :-)

So in my opinion, this feature is done, ready for a review. What you are suggesting requires a lot more work, and a dedicated issue.

willzyx’s picture

So in my opinion, this feature is done, ready for a review.

and I have reviewed it :)

I agree that having all of the pages existing in one controller is about to get out of hand, but that's how it currently works.

Have all the methods in a single controller looks very wrong to me and since we choose to gradually split DevelController for a better organization and for consistency (see #2792227: Move entity debug methods to a dedicated controller) we should stop to polluting DevelController with the methods for all the functionalities.

What you are suggesting requires a lot more work, and a dedicated issue.

if we add NEW functionalities they should be maintainable and with test coverage!

Since we are adding a new functionality I do not see why not do the things properly :)

If you need help with the suggested changes I'm glad to help you

tlyngej’s picture

@willzyx

Gotcha! New patch coming right up.

tlyngej’s picture

Status: Needs work » Needs review

Here we go!

In it's own controller, injecting devel.dumper, and with a test.

I didn't know of DevelDumperManager::exportAsRenderable before you mentioned it. Nifty stuff!

I'm a big fan of the idea of having some JS magic to make the info more digestable. But that's a bit more than I can handle right now.

tlyngej’s picture

Let's try uploading the patch, shall we?

tlyngej’s picture

Fixing some Coding Standard issues

tlyngej’s picture

And decided to rename the test class, prefixing it with Devel, as the rest of the tests.

willzyx’s picture

A lot better :)
a quick review

  1. +++ b/src/Controller/ServiceInfoController.php
    @@ -0,0 +1,86 @@
    +  public function __construct(DrupalKernel $kernelService, DevelDumperManager $dumper) {
    

    we need to use interfaces for the DI not the concrete classes

  2. +++ b/src/Controller/ServiceInfoController.php
    @@ -0,0 +1,86 @@
    +    $output['parameters'] = [
    +      '#type' => 'details',
    +      '#title' => $this->t('Parameters'),
    +      'content' => $this->dumper->exportAsRenderable($container_definition['parameters']),
    +    ];
    ...
    +    $output['services'] = [
    +      '#type' => 'details',
    +      '#title' => $this->t('Services'),
    +      'content' => $this->dumper->exportAsRenderable($container_definition['services']),
    +    ];
    

    since some of devel plugins already wrap the output in a detail element (see DoctrineDebug and DrupalVariable) when you use ::exportAsRenderable() not sure if it is the best solution..

  3. +++ b/src/Tests/DevelServiceInfoTest.php
    @@ -0,0 +1,40 @@
    +class DevelServiceInfoTest extends WebTestBase {
    +
    +  /**
    +   * Modules to enable.
    +   *
    +   * @var array
    +   */
    +  public static $modules = ['devel'];
    +
    +  /**
    +   * Does the page exist and load the expected two sets of output?
    +   */
    +  public function testServiceInfoPage() {
    +
    +    $web_user = $this->drupalCreateUser([
    +      'access devel information',
    +    ]);
    +
    +    $this->drupalLogin($web_user);
    +
    +    $this->drupalGet('devel/service/info');
    +    $this->assertResponse(200);
    +    $this->assertText('Service info');
    +    $this->assertText('service_container');
    +    $this->assertText('factory.keyvalue');
    +
    +  }
    +
    +}
    

    probably we need to expand a bit the test coverage

Good job @tlyngej

tlyngej’s picture

@willzyx

  1. Do you want this patch to include an interface for controllers (DevelControllerInterface)
  2. or is there one already that I haven't found?

  3. Not sure I completely follow you there. Can you elaborate what you mean?
  4. Any clues on what more to test? There isn't much functionality on the page.
willzyx’s picture

FileSize
17 KB
Do you want this patch to include an interface for controllers (DevelControllerInterface)

no absolutely..

+++ b/src/Controller/ServiceInfoController.php
@@ -0,0 +1,86 @@
+  public function __construct(DrupalKernel $kernelService, DevelDumperManager $dumper) {

this should be changed to use the interfaces. In this way the ServiceInfoController is not coupled with concrete services implementation and the injected services can be swapped without problems
DrupalKernel => DrupalKernelInterface
DevelDumperManager => DevelDumperManagerInteface

Not sure I completely follow you there. Can you elaborate what you mean?

Try to set DrupalVariable or DoctrineDebug plugin as default dumper and visit the service info page

there are two nested detail elements because some of devel plugins already wrap the output in a detail element (see DoctrineDebug and DrupalVariable) when you use ::exportAsRenderable()

Any clues on what more to test? There isn't much functionality on the page.

probably we can test that the dump of what we expect is present on the page

Also I think that we can display also the aliases retrieved by the cached container definition ($container_definitions['aliases']) in addition to services and parameters

tlyngej’s picture

  1. Aliases is now added to the page
  2. I have not removed the details element around the arrays. I can not assume that the var dumper will provide one. Kint and Symfony VarDumper doesn't
  3. I already did test for various strings that I expect to be there, but I threw in some more assertions
  4. The DI is now using the interfaces instead of the concrete classes

Status: Needs review » Needs work

The last submitted patch, 28: devel-service_info-2828116-28.patch, failed testing.

tlyngej’s picture

tlyngej’s picture

Status: Needs work » Needs review
willzyx’s picture

FileSize
90.59 KB
59.05 KB

sorry for the delay.. @tlyngej good job!

I already did test for various strings that I expect to be there, but I threw in some more assertions

Testing dumper output on the web pages is always tricky.. I'm open to expand the test coverage in another issue

In the attached patch I'm exploring another solution.. Show services and parameters in a table with on-fly search instead of dumping the informations. IMHO this can make the informations more readable and the on-fly search make easy to find a specific service (by id class or alias)



Clicking on the Devel operation button the user will be redirected to a page that show the service comuted definition and instacee detail



What do you think?

willzyx’s picture

oops.. and here the patch :P (with test coverage)

Status: Needs review » Needs work

The last submitted patch, 33: service_info_page-2828116-33.patch, failed testing.

willzyx’s picture

Status: Needs work » Needs review
tlyngej’s picture

@willzyx

I haven't tested (or even read the patch) but based on description and the screenshots, I really like it.

Dividing the services, parameters and aliases into different tabs gives the developer a much cleaner interface.

The believe that the search thingy will prove very useful. Good job on that one!

willzyx’s picture

I am considering to commit the patch in the coming days.. there is someone who wants to review/test it?

willzyx’s picture

Title: Service info page » Add Container info page
willzyx’s picture

minor changes in tests

  • willzyx committed 149a310 on 8.x-1.x
    Issue #2828116 by tlyngej, willzyx, lussoluca: Add Container info page
    
willzyx’s picture

Status: Needs review » Fixed

Committed and pushed to 8.x. Thanks to all and especially to @tlyngej :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.