[GLASSFISH-13169] Add diagnostic information to explain why a module is being resolved Created: 27/Aug/10  Updated: 11/Mar/13  Resolved: 11/Mar/13

Status: Closed
Project: glassfish
Component/s: OSGi
Affects Version/s: 3.1
Fix Version/s: None

Type: Improvement Priority: Critical
Reporter: Tom Mueller Assignee: Sanjeeb Sahoo
Resolution: Invalid Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Operating System: All
Platform: All


Issuezilla Id: 13,169

 Description   

The OSGi shell permits one to view what modules have been resolved at a
particular point in time. However, it is also important to know why a module
has been resolved. What module was it that triggered getting a module resolved?

This is a request to add diagnostic information to the system so that one can
find out why a module was resolved. Preferably, this would show the entire chain
of resolutions, starting with the explicit activation of a module, i.e., a
module that is in the Active state. For example, if module A is activated, and
it references module B which reference modules C which in turn references D, it
should be possible to execute some command or view some log output and see:

D <-- C <-- B <-- A

The inspect command in the OSGi shell does this to some extent. However, it is
not clear what the meanings of package, bundle, fragment and service are WRT an
OSGi module, and the dependencies as shown by that command appear to be
theoretical based on what is declared in the meta data rather than what actually
happened when a module was loaded.



 Comments   
Comment by Richard S. Hall [ 27/Aug/10 ]

I don't think this is possible in the general sense. At a minimum, the OSGi spec
allows a framework to resolve bundles at its own discretion, which means there
may be no reason why a module was resolved other than the framework wanted it
that way.

Further, there is no sort of resolver API in the framework to ask, "If I resolve
bundle foo, what other bundle's will resolve as a result." The best you can do
is try to resolve something and then see which bundles also changed state after
the resolve. However, there are inherent race conditions with this and still the
framework is free to resolve arbitrary bundles at the same time, so there may be
no real relationship among the bundles whose state changed.

Technically, you could try to use the framework's own resolver to ask "what if"
questions, but this is not standardize API, nor do you necessarily have any
guarantees that the results are the same when you actually try to commit them.

I think the best you can do is analyze the dependencies that exist among modules
after they are resolved to determine why something may have been resolved.

Finally, the results from the "inspect" command show you actual dependencies
based on run-time information, not theoretical information.

Comment by Tom Mueller [ 27/Aug/10 ]

I haven't found the output of the inspect command to be useful for this. The capability option lists what
packages are exported by the bundle, but it doesn't say which resolved bundles are actually using those
capabilities. So short of doing an inspect p r on every resolved bundle to see which ones reference the bundle
of interest, there isn't any way of answering the question "why did this bundle get resolved?"

We probably do not need a solution in the general sense. Rather, maybe just a log message at the beginning of
the resolution of a module that indicates what module is causing the resolve to happen.

Comment by Richard S. Hall [ 27/Aug/10 ]

We might be switching to Gogo shortly and its implementation of the "inspect"
command is a little more useful in this case:

org.apache.felix.gogo.runtime [3] exports packages:
---------------------------------------------------
org.apache.felix.service.command; version=0.6.0 imported by:
org.apache.felix.gogo.command [2]
org.apache.felix.gogo.shell [4]
org.apache.felix.shell.remote [6]
org.apache.felix.service.threadio; version=0.6.0 UNUSED

You can see here that is shows who imports it. However, it doesn't walk this
transitively. However, it would be possible for us to create a command that does.

Comment by Tom Mueller [ 06/Mar/12 ]

Bulk update to reassign dochez issue to component lead.

Comment by Sanjeeb Sahoo [ 11/Mar/13 ]

Please use osgi command or osgi console. Setting felix.log.level to 4 also produces resolver output in debug mode.

Comment by Tom Mueller [ 11/Mar/13 ]

What osgi command or what capability in the console. Please provide details before marking this issue as resolved. Richard indicated that a command could be implemented that would walk the tree recursively. Has that been done?

I did find a solution for this problem:

1. Change the debug setting to be suspend=y
2. Set a breakpoint in the hk2/osgi/adapter module, the OSGiModuleImpl.start method. I used line 217.
3. Start the server with --debug
4. Set up a watchpoint in the debugger for this.bundle.getLocation(). This will print the JAR file path for each JAR that is activated.
5. Keep hitting continue until the JAR file that you are interested in shows up.

This requires looking at the stack trace to see what caused a module to be activated. This same mechanism can be used to see why a module is resolved, by putting the breakpoint in a different place.

Comment by Sanjeeb Sahoo [ 11/Mar/13 ]

Modules are resolved by OSGi framework. The command Richard talked about is a Felix shell command. HK2 has ways to report why modules get activated. Ask HK2 folks.

Comment by Richard S. Hall [ 11/Mar/13 ]

It is true that you can create a command to transitively walk dependencies in OSGi, but to reiterate my point, this will not necessarily tell you why a bundle was resolved. The OSGi spec doesn't dictate incremental module resolves. The Felix framework is incremental, but the Equinox framework is not, so it tries to resolve everything any time it resolves anything. Thus there is no causality on Equinox.

I cannot think of a good [standard] way to determine causality of resolving. Although with the OSGi R4.3 API you do have resolver hooks that give you potential triggers that started the resolve, but the hooks don't directly have access to the resolve result, they would just have to try to observe it and it still doesn't help you deal with the fact that on Equinox any resolve will result in an attempt to resolve all installed modules.

Generated at Thu Dec 08 19:52:36 UTC 2016 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.