Include custom charts in email notifications?

I'm running a simple test script (but plan on adding lots more) on our data, and I generate a simple custom chart artifact containing the number of errors found:

    <build>
       <statisticValue key="badFiles" value="2"/>
       <statisticValue key="badEntries" value="69"/>
    </build>

I've added a chart to the statistics page for the build config, but I would really like to include the latest generated chart in the email that is sent out. Is there any way to do this currently? From what I can see in the documentation, it doesn't seem that way.

Can I write a plugin to enable this?

8 comments

Anders,

This is not available by single templates modificaiton.
With some amount of work it is possible to write TeamCity Java plugin to provide statistics values into the template.
However, API there is not a t all transparent, so feel free to get back if you choose to pursue with the approach.

0

That's about what I thought, thank you.

Is it in any way possible to extract custom data (for example the teamcity-info.xml data) from the last build in the email? I.e. so that I could configure it to say: "The test failed with 38 XYZ errors and 352 YZW errors".

These aren't code tests - what I've currently got is a Python script that parses a bunch of data files to see if there's anything wrong with them.

0

I've got IntelliJ and the sample plugin up and running and thought I'd try and see what's possible. I haven't touched Java in quite a while but the language itself shouldn't be too much of a problem I think. :)

From what I can understand, I will probably need to write a new Notificator class that will do the email sending. At least this is one way that seems like it could potentially work. Looking at the API briefly, it seems I don't have access to much from the notifyBuildSuccessful function though - the SRunningBuild class doesn't have much useful information, or a way to "dig deeper" that I can see.

Do you think it might be possible to combine a Notificator with something like the SampleStatisticsValue?


Or, should I instead start looking in the direction of adding more possiblities to the regular email template system, for example a markup like <@myplugin.customChartX> ? Do you think something like that would be possible?

Thanks,

Anders

0

Anders,

Provided you are on 5.1, I'd recommend to implement an extension point I've mentioned: http://confluence.jetbrains.net/display/TCD5/Extending+Notification+Templates+Model
When you get the data in the Java you can then put into into the objects avaialable in the template and then modify the template to render the data appropriately.

A note on how to get the data in the Java code. You will need:
1. Get instance of ValueProviderRegistry from Spring (just adding to the parameters of contructor of your class declared in spring xml)
2. get data via: valueProviderRegistry.getValueProvider("badFiles").getDataSet(chartSettings), where charSet has set BuildChartSettings.BUILD_TYPE_ID to the id of the build type (can be retrieved from notificationContext.getCurrentModel().get("buildType") )
3. filter the returned data to find one matching notificationContext.getCurrentModel().get("build")

I've mentioned it's not that transparent :)

0

Thanks Yegor, I've got the basics working.

However, I'd like a more "dynamic" way of detecting which build values to show; that is, I'd like to essentially loop over the metric values the build produces (in the example above, "badEntries" and "badFiles". I tried looping over all of the ValueProviders, but that seems to get me ValueProviders including those from other graphs as well.



    public Map<String, Object> fillModel(@NotNull NotificationContext context) {
        BuildType buildType = (BuildType)context.getCurrentModel().get("buildType");
        BuildChartSettings chartSettings = new BuildChartSettings(new HashMap<String, String[]>());
        chartSettings.setBuildTypeId(buildType.getBuildTypeId());



        String result = "";
        
        java.util.List<BuildValue> buildValues;
        Collection<ValueProvider> vps = valueProviderRegistry.getValueProviders();
        Iterator it = vps.iterator();
        while( it.hasNext())
        {
            ValueProvider vp = (ValueProvider) it.next();



            buildValues = vp.getDataSet(chartSettings);
            if (!buildValues.isEmpty())
            {
                BuildValue bv = buildValues.get(buildValues.size() - 1);
                result += vp.getKey() + " = " + bv.intValue() + "<br>";
            }
        }



        Map<String, Object> model = new HashMap<String, Object>();
        model.put("srekeltest", "TEST " + result);



      return model;
    }




What do you think is the best way to get just the ValueProviders that have custom statistic information generated by the build? Maybe the simplest solution is simply to loop over all of them and have a naming convention for the graph and the build, e.g something like this:

if ( vp.getKey().contains( buildType.getName() )
{
    ...
}

It seems like it's impossible to add actual images (e.g. graphs) to the email. That would be highly desireable. Is this something you're considering to add in the future?

Thanks,

Anders

0

Hi Anders,

Yegor is on vacation at the moment, so I'll try to answer as many questions as I can.
Indeed, ValueProviderRegistry.getValueProviders() returns all providers in system, and the API assumes that you know exactly what provider you need. It seems there is no convention for the key (at least public), so I don't think you can rely on it.
ValueProvider allows to obtain the list of BuildValues from CharSettings. I suppose you can create the instance of BuildChartSettings and filter the result list by build id.
This seems to be the simplest way.

E-mail attachments are not supported, the main problem is in interface - how it should be configured from the template. If you have any ideas on this matter, please share.


---
Maxim

0

Hi Maxim,

I had a try at trying to filter based on something from the BuildValue, but nothing seems to work. I'm slightly puzzled by the results actually and it almost seems like a bug inside TeamCity, but it might very well just be that I don't know how it's supposed to work. I changed my function to this:

    public Map<String, Object> fillModel(@NotNull NotificationContext context) {
        BuildType buildType = (BuildType)context.getCurrentModel().get("buildType");
        BuildChartSettings chartSettings = new BuildChartSettings(new HashMap<String, String[]>());
        chartSettings.setBuildTypeId(buildType.getBuildTypeId());

        String result = "";
        
        Collection<ValueProvider> vps;
        vps = valueProviderRegistry.getValueProviders();
        Iterator it = vps.iterator();
        while( it.hasNext())
        {
            ValueProvider vp = (ValueProvider) it.next();

            java.util.List<BuildValue> buildValues;
            buildValues = vp.getDataSet(chartSettings);
            if (!buildValues.isEmpty())
            {
                BuildValue bv = buildValues.get(buildValues.size() - 1);
                result += vp.getKey() + " :: " + bv.intValue()  + " :: " + bv.getBuildTypeId()  + " :: " + bv.getBuildNumber()  + " :: " + bv.getBuildId()  + " :: " + bv.getBuildTypeName()  + " :: " + bv.getSeries() + "<br>";
            }
        }

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("srekeltest", "TEST " + result);

        return model;
    }


This is the graph part from my main-config.xml

  <graph title="LocalisationGraph"  seriesTitle="Loc1">
    <valueType key="badFiles" title="bad Files" buildTypeId="bt2" />
    <valueType key="badEntries" title="bad Entries" buildTypeId="bt2" />
    <valueType key="badEncodings" title="bad Encodings" buildTypeId="bt2" />
  </graph>
  
    <graph title="LocalisationGraph2">
    <valueType key="asdf" title="badFiles" buildTypeId="bt1" />
    <valueType key="hfghg" title="badEntries" buildTypeId="bt1" />
    <valueType key="fgaha" title="badEncodings" buildTypeId="bt1" />
    <valueType key="hghggh" title="test" buildTypeId="bt1" />
  </graph>


And this is the output from the first three runs of the build, right after I restarted the web service (to reload the plugin and config):

1)

SREKELTEST: TEST customGraph0 :: 11 :: bt2 :: 71 :: 71 :: null :: bad Encodings
BuildCheckoutTime :: 0 :: bt2 :: 71 :: 71 :: null :: ANDERSELFGREN2
badFiles :: 10 :: bt2 :: 71 :: 71 :: null :: ANDERSELFGREN2




2)

SREKELTEST: TEST InspectionStatsW :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2
asdf :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2
customGraph0 :: 11 :: bt2 :: 72 :: 72 :: null :: bad Encodings
BuildCheckoutTime :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2
CodeCoverageAbsMTotal :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2
PassedTestCount :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2
InspectionStatsE :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2
fgaha :: 0 :: bt2 :: 72 :: 72 :: null :: ANDERSELFGREN2




3)

SREKELTEST: TEST InspectionStatsW :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2
asdf :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2
customGraph0 :: 11 :: bt2 :: 73 :: 73 :: null :: bad Encodings
BuildCheckoutTime :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2
CodeCoverageAbsMTotal :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2
PassedTestCount :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2
InspectionStatsE :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2
fgaha :: 0 :: bt2 :: 73 :: 73 :: null :: ANDERSELFGREN2

As you can see, the first run's output differs from the two after. Also, none of them show the badEntries or badEncodings keys, but do show the values from the other graph, even though it's specified to be for a different buildTypeId (bt1). It also says that they are for bt2 rather than bt1 that you might expect. The last weird thing is the "customGraph0" which prints the title for the "badEncodings" key where it should have printed the value from "bv.getSeries()", which I would have expected to be, if anything, this: "seriesTitle="Loc1""

"ANDERSELFGREN2" is my computer name (in case that helps) :)

Anything you can help with here? :)

Oh, and the teamcity-info.xml result from the build looks like this:

<build>
<statisticValue key="badFiles" value="10"/>
<statisticValue key="badEntries" value="10"/>
<statisticValue key="badEncodings" value="11"/>
<statisticValue key="test2" value="12"/>
</build>

0

Hi Anders,

This indeed looks strange. Unfortunately responsible engineer is on vacation as well, so I can't give you the answer right away.
But I'll try to investigate.


---
Maxim

0

Please sign in to leave a comment.