You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ivy-user@ant.apache.org by Phil Clay <pi...@yahoo.com> on 2010/11/29 21:31:10 UTC

instrumented vs non-instrumented artifacts with shared dependencies

Here’s an interesting use case for your consideration.  I’m using ivy currently, 
but I’m not happy with some of the configuration.  I’d like to get your input to 
see if a simpler way exists (or perhaps file a feature request to make this 
easier).
 
I have a multi-module project (30+ modules), each with 5+ configurations.  I’ll 
simplify this down to the very basics.... two modules, with two configurations 
each....
 
For each module:
	* a non-instrumented runtime  jar is published under the “deploy” configuration 
, and
	* an instrumented runtime jar is published under the “instrumented” 
configuration.
 
Dev uses the instrumented jars for unit test code coverage, and QA uses them for 
their testing code coverage.  The non-instrumented jars are used in production.
 
An instrumented deployment consists of A) our instrumented jars and B) 3rd party 
dependencies.  A non-instrumented deployment consists of C) our non-instrumented 
jars and B) 3rd party dependencies.
 
 
Here is a vastly simplified example of two of our modules as currently 
configured.  moduleB depends on moduleA....
 
 
<ivy-modulexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"version="2.0"
    xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
 
    <infomodule="moduleA" organisation="com.company"/>
 
    <configurations>
        <confname="deploy"/>
        <confname="instrumented"/>
    </configurations>
 
    <publications>
        <artifactconf="deploy" type="jar"/>
        <artifactconf="instrumented" type="instrumented.jar"/>
    </publications>
 
    <dependencies>
        <dependencyconf="deploy;instrumented->deploy" org="org.apache" 
name="commons-lang"/>
    </dependencies>
 
</ivy-module>
 
 
<ivy-modulexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
    xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
 
    <infomodule="moduleB"/>
 
    <configurations>
        <confname="deploy"/>
        <confname="instrumented"/>
    </configurations>
 
    <publications>
        <artifactconf="deploy" type="jar"/>
        <artifactconf="instrumented" type="instrumented.jar"/>
    </publications>
 
    <dependencies>
        <dependencyconf="deploy;instrumented" org="com.company" name="moduleA"/>
        <dependencyconf="deploy;instrumented->deploy" org="org.apache" 
name="commons-codec"/>
    </dependencies>
 
</ivy-module>
 
 
 
This works, but I’m managing 30+ modules, each with LOTS of dependencies.  I 
want to simplify the configuration down to the least possible denominator.  (I'm 
seeing other developers consistently forget to add the "instrumented->deploy" 
configuration for 3rd party dependencies.  I want to simplify the configuration 
to reduce the possible errors.)

 
Ideally, I would like to completely remove any mention of “instrumented->deploy” 
or “instrumented” from the dependencies section.  i.e. I would like to be able 
to completely handle the instrumented vs non-instrumented logic in the 
configurations and/or publications section.
 
If that is not possible, I would at least like to remove the 
“instrumented->deploy” mapping for all third party dependencies that also have 
the “deploy” configuration in the dependency element.  (i.e. leave 
“instrumented” in the dependency configuration for sibling modules in the same 
project)
 
 
Initially, I thought I could just make the “instrumented” configuration extend 
the “deploy” configuration.  BUT if I did that, it would mean that anybody that 
depended on the “instrumented” configuration of moduleA would retrieve BOTH the 
non-instrumented and instrumented jars, which is not what I want.
 
 
A few possibilities come to mind:
	* Be able to exclude configurations to which an artifact is published  (e.g. 
<artifactconf="deploy,!instrumented" type="jar"/>)
	* Be able to exclude artifacts in the conf element (e.g. 
<confname="instrumented" extends="deploy"><exclude org="com.company" 
type="jar"/></conf>)
	* Allow a configuration to 'inherit' only dependencies, but not publications.

 
 
Is what I’m looking for currently possible with ivy today?
 
If not, does anybody have a suggestion on how this could look if ivy were to 
support this type of configuration?
 
Thanks for the consideration.
 
Phil


      

Re: instrumented vs non-instrumented artifacts with shared dependencies

Posted by Mitch Gitman <mg...@gmail.com>.
Here's something I was able to quick slap together for moduleB. I can't
vouch that this is precisely what will work, but at least it should be a
starting point that someone else can refine:
<ivy-module xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
   xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd
">

   <info module="moduleB"/>

   <configurations>
       <conf name="common" />
       <conf name="deploy" extends="common" />
       <conf name="instrumented" extends="common" />
   </configurations>

   <publications>
       <artifact conf="deploy" type="jar"/>
       <artifact conf="instrumented" type="instrumented.jar"/>
   </publications>

   <dependencies defaultconf="deploy->deploy;instrumented->instrumented">
       <dependency org="com.company" name="moduleA"/>
       <dependency conf="common->default" org="org.apache"
name="commons-codec"/>
   </dependencies>

</ivy-module>

Points:
* Third-party libraries are depended upon by the new common conf. They're
needed both for deploy and instrumented.
* Third-party libraries have their own confs apart from deploy and
instrumented. Instrumentation is not relevant to them. For commons-codec,
I'm assuming it has a conf called "default".
* The dependencies element specifies a defaultconf. This way, you're assured
that someone doesn't forget to make deploy depend on deploy and instrumented
depend on instrumented on the particular dependency. This default is geared
towards in-house modules, not third-party modules.
* For common, you might make visibility="private" so that it can't be
depended upon directly. I believe that will still work, but double-check.

I notice that you aren't specifying a name for your artifacts. I would
recommend being explicit about that, so that you just don't fall back to the
Ivy module name. But I also find it odd that the type of "instrumented.jar"
is able to coexist with "jar" even though both artifacts ostensibly have the
same name. This may be a feature of Ivy I wasn't aware of. Does the
instrumented JAR appear with the name moduleB.instrumented.jar, such that
Ivy is able infer the filename from the extended type name? The following
would accomplish the same:
<artifact conf="instrumented" type="jar" ext="instrumented.jar" />

One other note. I'm not used to seeing JARs that have been instrumented for
code coverage being published if only because the coverage report is being
done on the tests of the project at hand, rather than on projects that
depend on it. But I see your QA team is also doing coverage so I can
understand.

On Mon, Nov 29, 2010 at 12:31 PM, Phil Clay <pi...@yahoo.com> wrote:

> Here’s an interesting use case for your consideration.  I’m using ivy
> currently,
> but I’m not happy with some of the configuration.  I’d like to get your
> input to
> see if a simpler way exists (or perhaps file a feature request to make this
> easier).
>
> I have a multi-module project (30+ modules), each with 5+ configurations.
>  I’ll
> simplify this down to the very basics.... two modules, with two
> configurations
> each....
>
> For each module:
>        * a non-instrumented runtime  jar is published under the “deploy”
> configuration
> , and
>        * an instrumented runtime jar is published under the “instrumented”
> configuration.
>
> Dev uses the instrumented jars for unit test code coverage, and QA uses
> them for
> their testing code coverage.  The non-instrumented jars are used in
> production.
>
> An instrumented deployment consists of A) our instrumented jars and B) 3rd
> party
> dependencies.  A non-instrumented deployment consists of C) our
> non-instrumented
> jars and B) 3rd party dependencies.
>
>
> Here is a vastly simplified example of two of our modules as currently
> configured.  moduleB depends on moduleA....
>
>
> <ivy-modulexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
> "version="2.0"
>    xsi:noNamespaceSchemaLocation="
> http://ant.apache.org/ivy/schemas/ivy.xsd">
>
>    <infomodule="moduleA" organisation="com.company"/>
>
>    <configurations>
>        <confname="deploy"/>
>        <confname="instrumented"/>
>    </configurations>
>
>    <publications>
>        <artifactconf="deploy" type="jar"/>
>        <artifactconf="instrumented" type="instrumented.jar"/>
>    </publications>
>
>    <dependencies>
>        <dependencyconf="deploy;instrumented->deploy" org="org.apache"
> name="commons-lang"/>
>    </dependencies>
>
> </ivy-module>
>
>
> <ivy-modulexmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
> version="2.0"
>    xsi:noNamespaceSchemaLocation="
> http://ant.apache.org/ivy/schemas/ivy.xsd">
>
>    <infomodule="moduleB"/>
>
>    <configurations>
>        <confname="deploy"/>
>        <confname="instrumented"/>
>    </configurations>
>
>    <publications>
>        <artifactconf="deploy" type="jar"/>
>        <artifactconf="instrumented" type="instrumented.jar"/>
>    </publications>
>
>    <dependencies>
>        <dependencyconf="deploy;instrumented" org="com.company"
> name="moduleA"/>
>        <dependencyconf="deploy;instrumented->deploy" org="org.apache"
> name="commons-codec"/>
>    </dependencies>
>
> </ivy-module>
>
>
>
> This works, but I’m managing 30+ modules, each with LOTS of dependencies.
>  I
> want to simplify the configuration down to the least possible denominator.
>  (I'm
> seeing other developers consistently forget to add the
> "instrumented->deploy"
> configuration for 3rd party dependencies.  I want to simplify the
> configuration
> to reduce the possible errors.)
>
>
> Ideally, I would like to completely remove any mention of
> “instrumented->deploy”
> or “instrumented” from the dependencies section.  i.e. I would like to be
> able
> to completely handle the instrumented vs non-instrumented logic in the
> configurations and/or publications section.
>
> If that is not possible, I would at least like to remove the
> “instrumented->deploy” mapping for all third party dependencies that also
> have
> the “deploy” configuration in the dependency element.  (i.e. leave
> “instrumented” in the dependency configuration for sibling modules in the
> same
> project)
>
>
> Initially, I thought I could just make the “instrumented” configuration
> extend
> the “deploy” configuration.  BUT if I did that, it would mean that anybody
> that
> depended on the “instrumented” configuration of moduleA would retrieve BOTH
> the
> non-instrumented and instrumented jars, which is not what I want.
>
>
> A few possibilities come to mind:
>        * Be able to exclude configurations to which an artifact is
> published  (e.g.
> <artifactconf="deploy,!instrumented" type="jar"/>)
>        * Be able to exclude artifacts in the conf element (e.g.
> <confname="instrumented" extends="deploy"><exclude org="com.company"
> type="jar"/></conf>)
>        * Allow a configuration to 'inherit' only dependencies, but not
> publications.
>
>
>
> Is what I’m looking for currently possible with ivy today?
>
> If not, does anybody have a suggestion on how this could look if ivy were
> to
> support this type of configuration?
>
> Thanks for the consideration.
>
> Phil
>
>
>

Re: instrumented vs non-instrumented artifacts with shared dependencies

Posted by Tim Brown <tp...@gmail.com>.
Hi Phil,

I started down a similar path a while back, but decided against it...

For each module:
>        * a non-instrumented runtime  jar is published under the “deploy”
> configuration
> , and
>        * an instrumented runtime jar is published under the “instrumented”
> configuration.
>
> Dev uses the instrumented jars for unit test code coverage, and QA uses
> them for
> their testing code coverage.  The non-instrumented jars are used in
> production.
>
>
A couple of quick thoughts on the above  [I've had a bit o' scotch tonight,
so pardon the ramblings]:

If developers are writing unit tests, those tests are for the particular
module they're bundled with.   Since it's the module they're working on,
it's available as source in the IDE [for reviewing coverage as they work],
and later as part of your build process [for aggregation of the metric
'formally'].

Wouldn't counting coverage of the instrumented jars fall under incidental
coverage, and as such not be counted?

As for the QA / functional test code coverage.  We opted to optionally
instrument the deployable [WAR, whatever] as part of our deployment process
for a couple of reasons:
1) It "feels" more like we're producing one binary for all environments.
Yes, it's not necessarily true since we're technically changing it via
instrumentation, but we use a multi-stage functional test approach.
 Instrumentation is only collected on the first stage [non-integrated;
integration points are stubbed dynamically].
1.1) Side note - don't collect functional test code coverage in a shared
environment. Exploratory and manual testing will munge your coverage data.
Ditto if you're doing concurrent test runs from parallel suites.
2) Instrumentation, at least EMMA's, conflicted with other instrumentations
that were necessary -- namely Oracle/Tangosol Coherence. [We also had issues
with it and AspectJ, but we dropped AJ, for other reasons].

Point #2 was really the inflection point for us.  The app was instrumented
for Coherence in Prod, but we didn't want (and shouldn't have) it enabled in
the first functional test stage.  Since the app was already technically
different than prod, we chose to keep the stages when the app was different
to a minimum, and near the start of the pipeline.  [and FWIW, we actually
"de-Tangosol" the binary in this stage, then EMMA instrument it].

If it's helpful, the configurations we ended up with are:
- config - externalized configuration
- runtime - things bundled in the deployable and available at runtime
(extends config)
- compile - things necessary at compile time [but usually are container
provided thus not inside the deployable] (extends runtime)
- test-public - A "special" config for when we actually need the test
artifacts of another module for our 'test' config [factories, etc.].  yes..
this one is a big smell.  (extends runtime)
- test - things necessary for test compilation or execution, but not in
compile/runtime (private. extends compile, test-public)

Configuration mapping goes something
like: runtime->runtime(*);config->config(*);test->runtime(*);compile->runtime(*);"
 [test-public would require a explicitly mapped dependency]

hth,

~Tim