Skip to content

Commit

Permalink
dashboard: add the plumbing for legends and groups configuration
Browse files Browse the repository at this point in the history
Integrate the configuration bits. This changes the
/rest/1.0/sample_kinds endpoint to return the new
GroupsAndSampleKindsStore object (cached as needed via the etag).
and add a new endpoint /rest/1.0/config to return the legends
configuration.

Also rename SuperGroup to CustomGroup which seems more intuitive.

The associated client updates will be in a separate commit.

Signed-off-by: Pierre-Alexandre Meyer <pierre@ning.com>
  • Loading branch information
Pierre-Alexandre Meyer committed May 4, 2012
1 parent b30ba83 commit 8b0e13b
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@

import com.ning.arecibo.util.timeline.CategoryAndSampleKinds;

import com.google.common.collect.ImmutableList;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;

import java.util.List;

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class SuperGroup
public class CustomGroup
{
private final String name;
private final List<CategoryAndSampleKinds> kinds;

@JsonCreator
public SuperGroup(@JsonProperty("name") final String name, @JsonProperty("kinds") final List<CategoryAndSampleKinds> kinds)
public CustomGroup(@JsonProperty("name") final String name, @JsonProperty("kinds") final List<CategoryAndSampleKinds> kinds)
{
this.name = name;
this.kinds = kinds;
Expand All @@ -48,23 +47,11 @@ public List<CategoryAndSampleKinds> getKinds()
return kinds;
}

public CategoryAndSampleKinds asMetaCategoryAndSampleKinds()
{
final ImmutableList.Builder<String> sampleKinds = ImmutableList.<String>builder();
for (final CategoryAndSampleKinds member : kinds) {
for (final String attribute : member.getSampleKinds()) {
sampleKinds.add(String.format("%s::%s", member.getEventCategory(), attribute));
}
}

return new CategoryAndSampleKinds(name, sampleKinds.build());
}

@Override
public String toString()
{
final StringBuilder sb = new StringBuilder();
sb.append("SuperGroup");
sb.append("CustomGroup");
sb.append("{name='").append(name).append('\'');
sb.append(", kinds=").append(kinds);
sb.append('}');
Expand All @@ -81,7 +68,7 @@ public boolean equals(final Object o)
return false;
}

final SuperGroup that = (SuperGroup) o;
final CustomGroup that = (CustomGroup) o;

if (kinds != null ? !kinds.equals(that.kinds) : that.kinds != null) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,37 @@
package com.ning.arecibo.dashboard.config;

import com.ning.arecibo.dashboard.guice.DashboardConfig;
import com.ning.arecibo.util.timeline.CategoryAndSampleKinds;

import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SuperGroupsManager
public class CustomGroupsManager
{
private static final ObjectMapper mapper = new ObjectMapper();

private final Iterable<CategoryAndSampleKinds> kinds;
private final List<CustomGroup> customGroups = new ArrayList<CustomGroup>();

@Inject
public SuperGroupsManager(final DashboardConfig config) throws IOException
public CustomGroupsManager(final DashboardConfig config) throws IOException
{
if (config.getSuperGroupsFile() == null) {
kinds = ImmutableList.<CategoryAndSampleKinds>of();
return;
// Add custom groups if specified
if (config.getCustomGroupsFile() != null) {
final File superGroupsFile = new File(config.getCustomGroupsFile());
final List<CustomGroup> customGroups = mapper.readValue(superGroupsFile, new TypeReference<List<CustomGroup>>()
{
});
this.customGroups.addAll(customGroups);
}

final File superGroupsFile = new File(config.getSuperGroupsFile());
final List<SuperGroup> groups = mapper.readValue(superGroupsFile, new TypeReference<List<SuperGroup>>()
{
});

final ImmutableList.Builder<CategoryAndSampleKinds> kindsBuilder = ImmutableList.<CategoryAndSampleKinds>builder();
for (final SuperGroup group : groups) {
kindsBuilder.add(group.asMetaCategoryAndSampleKinds());
}

kinds = kindsBuilder.build();
}

public Iterable<CategoryAndSampleKinds> getAllKinds()
public List<CustomGroup> getCustomGroups()
{
return kinds;
return customGroups;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ public interface DashboardConfig
@Default("false")
boolean isAlertManagerEnabled();

@Config("arecibo.dashboard.superGroupsFile")
@Description("Path to the super groups file (optional)")
@Config("arecibo.dashboard.customGroupsFile")
@Description("Path to the custom super groups file (optional)")
@DefaultNull
String getSuperGroupsFile();
String getCustomGroupsFile();

@Config("arecibo.dashboard.legendGroupsFile")
@Description("Path to the legend configuration file (optional)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
import com.ning.arecibo.dashboard.alert.AlertRESTClient;
import com.ning.arecibo.dashboard.alert.AlertStatusManager;
import com.ning.arecibo.dashboard.alert.ClusterAwareAlertClient;
import com.ning.arecibo.dashboard.config.SuperGroupsManager;
import com.ning.arecibo.dashboard.config.LegendConfigurationsManager;
import com.ning.arecibo.dashboard.config.CustomGroupsManager;
import com.ning.arecibo.dashboard.format.DashboardFormatManager;
import com.ning.arecibo.dashboard.galaxy.GalaxyStatusManager;
import com.ning.arecibo.dashboard.resources.GroupsAndSampleKindsStore;
import com.ning.arecibo.event.publisher.HdfsEventPublisher;
import com.ning.arecibo.event.publisher.RandomEventServiceChooser;
import com.ning.arecibo.util.Logger;
Expand All @@ -53,7 +55,9 @@ public void configure()
final CollectorClientConfig collectorClientConfig = new ConfigurationObjectFactory(System.getProperties()).build(CollectorClientConfig.class);
bind(CollectorClientConfig.class).toInstance(collectorClientConfig);

bind(SuperGroupsManager.class).asEagerSingleton();
bind(CustomGroupsManager.class).asEagerSingleton();
bind(LegendConfigurationsManager.class).asEagerSingleton();
bind(GroupsAndSampleKindsStore.class).asEagerSingleton();

configureServiceLocator(dashboardConfig);
configureCollectorFinder(collectorClientConfig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
package com.ning.arecibo.dashboard.resources;

import com.ning.arecibo.collector.CollectorClient;
import com.ning.arecibo.dashboard.config.SuperGroupsManager;
import com.ning.arecibo.dashboard.config.LegendConfigurationsManager;
import com.ning.arecibo.dashboard.galaxy.GalaxyStatusManager;
import com.ning.arecibo.util.timeline.CategoryAndSampleKinds;
import com.ning.arecibo.util.timeline.SamplesForSampleKindAndHost;
import com.ning.jaxrs.DateTimeParameter;
import com.ning.jersey.metrics.TimedResource;
Expand All @@ -37,7 +36,10 @@
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Map;
Expand All @@ -46,14 +48,19 @@
@Path("/rest/1.0")
public class CollectorResource
{
private final SuperGroupsManager groupsManager;
private final GroupsAndSampleKindsStore groupsAndSampleKindsStore;
private final LegendConfigurationsManager legendsManager;
private final CollectorClient client;
private final GalaxyStatusManager manager;

@Inject
public CollectorResource(final SuperGroupsManager groupsManager, final CollectorClient client, final GalaxyStatusManager manager)
public CollectorResource(final GroupsAndSampleKindsStore groupsAndSampleKindsStore,
final LegendConfigurationsManager legendsManager,
final CollectorClient client,
final GalaxyStatusManager manager)
{
this.groupsManager = groupsManager;
this.groupsAndSampleKindsStore = groupsAndSampleKindsStore;
this.legendsManager = legendsManager;
this.client = client;
this.manager = manager;
}
Expand Down Expand Up @@ -91,20 +98,18 @@ public Response getHosts(@QueryParam("callback") @DefaultValue("callback") final
@Path("/sample_kinds")
@Produces(MediaType.APPLICATION_JSON)
@TimedResource
public Response getSampleKinds(@QueryParam("host") final List<String> hostNames,
public Response getSampleKinds(@Context final Request request,
@QueryParam("callback") @DefaultValue("callback") final String callback)
{
try {
final Iterable<CategoryAndSampleKinds> collectorSampleKinds = client.getSampleKinds(hostNames);
// Find super groups, if they exist
final Iterable<CategoryAndSampleKinds> superGroups = groupsManager.getAllKinds();
final String etag = groupsAndSampleKindsStore.getEtag();
final Response.ResponseBuilder responseBuilder = request.evaluatePreconditions(new EntityTag(etag));
if (responseBuilder != null) {
return responseBuilder.build();
}

final Iterable<CategoryAndSampleKinds> sampleKinds = ImmutableList.<CategoryAndSampleKinds>builder()
.addAll(collectorSampleKinds)
.addAll(superGroups)
.build();
final JSONPObject object = new JSONPObject(callback, sampleKinds);
return Response.ok(object).build();
try {
final JSONPObject object = new JSONPObject(callback, groupsAndSampleKindsStore);
return Response.ok(object).tag(etag).build();
}
catch (RuntimeException t) {
// Likely UniformInterfaceException from the collector client library
Expand Down Expand Up @@ -134,6 +139,16 @@ public Response getSamplesByHostName(@QueryParam("callback") @DefaultValue("call
}
}

@GET
@Path("/config")
@Produces(MediaType.APPLICATION_JSON)
@TimedResource
public Response getDashboardConfig(@QueryParam("callback") @DefaultValue("callback") final String callback)
{
final JSONPObject object = new JSONPObject(callback, legendsManager.getConfiguration());
return Response.ok(object).build();
}

private Response buildServiceUnavailableResponse()
{
return Response.status(Response.Status.SERVICE_UNAVAILABLE).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.ning.arecibo.dashboard.resources;

import com.ning.arecibo.collector.CollectorClient;
import com.ning.arecibo.dashboard.config.SuperGroupsManager;
import com.ning.arecibo.dashboard.config.CustomGroupsManager;
import com.ning.arecibo.dashboard.guice.DashboardConfig;
import com.ning.arecibo.util.timeline.CategoryAndSampleKinds;

Expand Down Expand Up @@ -47,7 +47,7 @@ public class GroupsAndSampleKindsStore
private final Object updateMonitor = new Object();
private final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor("sampleKindsUpdater");

private final SuperGroupsManager groupsManager;
private final CustomGroupsManager groupsManager;
private final CollectorClient client;
private final DashboardConfig config;

Expand All @@ -56,7 +56,7 @@ public class GroupsAndSampleKindsStore
private String json = null;

@Inject
public GroupsAndSampleKindsStore(final SuperGroupsManager groupsManager, final CollectorClient client, final DashboardConfig config)
public GroupsAndSampleKindsStore(final CustomGroupsManager groupsManager, final CollectorClient client, final DashboardConfig config)
{
this.groupsManager = groupsManager;
this.client = client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestSuperGroup
public class TestCustomGroup
{
private static final ObjectMapper mapper = new ObjectMapper();

Expand All @@ -33,34 +33,16 @@ public void testJsonSerialization() throws Exception
final CategoryAndSampleKinds kind = new CategoryAndSampleKinds("JVMMemory", ImmutableList.<String>of("heapUsed", "nonHeapUsed"));

final String groupName = "JVM";
final SuperGroup group = new SuperGroup(groupName, ImmutableList.<CategoryAndSampleKinds>of(kind));
final CustomGroup group = new CustomGroup(groupName, ImmutableList.<CategoryAndSampleKinds>of(kind));
Assert.assertEquals(group.getName(), groupName);
Assert.assertEquals(group.getKinds().size(), 1);

final String json = mapper.writeValueAsString(group);
Assert.assertEquals(json, "{\"name\":\"JVM\",\"kinds\":[{\"eventCategory\":\"JVMMemory\",\"sampleKinds\":[\"nonHeapUsed\",\"heapUsed\"]}]}");

final SuperGroup parsedGroup = mapper.readValue(json.getBytes(), SuperGroup.class);
final CustomGroup parsedGroup = mapper.readValue(json.getBytes(), CustomGroup.class);
Assert.assertEquals(parsedGroup, group);
Assert.assertEquals(parsedGroup.getName(), groupName);
Assert.assertEquals(parsedGroup.getKinds().size(), 1);
}

@Test(groups = "fast")
public void testAsMetaCategoryAndSampleKinds() throws Exception
{
final CategoryAndSampleKinds jvmKinds = new CategoryAndSampleKinds("JVMMemory", ImmutableList.<String>of("heapUsed", "nonHeapUsed"));
final CategoryAndSampleKinds cmsKinds = new CategoryAndSampleKinds("CMSOldGen", ImmutableList.<String>of("memoryPoolUsed", "memoryPoolMax"));

final String groupName = "Memory";
final SuperGroup group = new SuperGroup(groupName, ImmutableList.<CategoryAndSampleKinds>of(jvmKinds, cmsKinds));
final CategoryAndSampleKinds meta = group.asMetaCategoryAndSampleKinds();

Assert.assertEquals(meta.getEventCategory(), groupName);
Assert.assertTrue(meta.getSampleKinds().contains("JVMMemory::heapUsed"));
Assert.assertTrue(meta.getSampleKinds().contains("JVMMemory::nonHeapUsed"));
Assert.assertTrue(meta.getSampleKinds().contains("CMSOldGen::memoryPoolUsed"));
Assert.assertTrue(meta.getSampleKinds().contains("CMSOldGen::memoryPoolMax"));
Assert.assertEquals(ImmutableList.<String>copyOf(meta.getSampleKinds()).size(), 4);
}
}
Loading

0 comments on commit 8b0e13b

Please sign in to comment.