Skip to content
Permalink
Browse files
better logging and rendering of errors
  • Loading branch information
ahgittin committed Jan 14, 2016
1 parent 649a08d commit 01833f20621a34bf5437d0a4dff8a775823fcbb8
Showing 5 changed files with 33 additions and 6 deletions.
@@ -139,7 +139,7 @@ private static EntitySpec<?> createEntitySpecFromServicesBlock(String plan, Broo
return appSpec;

} else {
throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at);
throw new IllegalStateException("Unable to instantiate YAML; invalid type or parameters in plan:\n"+plan);
}

}
@@ -463,8 +463,10 @@ private void collectCatalogItems(String sourceYaml, Map<?,?> itemMetadata, List<
PlanInterpreterGuessingType planInterpreter = new PlanInterpreterGuessingType(null, item, sourceYaml, itemType, libraryBundles, result).reconstruct();
if (!planInterpreter.isResolved()) {
throw Exceptions.create("Could not resolve item"
+ (Strings.isNonBlank(id) ? " "+id : Strings.isNonBlank(symbolicName) ? " "+symbolicName : Strings.isNonBlank(name) ? name : "")
// better not to show yaml, takes up lots of space, and with multiple plan transformers there might be multiple errors
+ (Strings.isNonBlank(id) ? " '"+id+"'" : Strings.isNonBlank(symbolicName) ? " '"+symbolicName+"'" : Strings.isNonBlank(name) ? " '"+name+"'" : "")
// better not to show yaml, takes up lots of space, and with multiple plan transformers there might be multiple errors;
// some of the errors themselves may reproduce it
// (ideally in future we'll be able to return typed errors with caret position of error)
// + ":\n"+sourceYaml
, planInterpreter.getErrors());
}
@@ -124,7 +124,12 @@ public Response create(String yaml) {
Map<String,Object> result = MutableMap.of();

for (CatalogItem<?,?> item: items) {
result.put(item.getId(), CatalogTransformer.catalogItemSummary(brooklyn(), item));
try {
result.put(item.getId(), CatalogTransformer.catalogItemSummary(brooklyn(), item));
} catch (Throwable t) {
log.warn("Error loading catalog item '"+item+"' (rethrowing): "+t);
throw Exceptions.propagate(t);
}
}
return Response.status(Status.CREATED).entity(result).build();
}
@@ -93,9 +93,12 @@ public Response toResponse(Throwable throwable1) {
}
}

Builder rb = ApiError.builderFromThrowable(Exceptions.collapse(throwable2));
Throwable throwable3 = Exceptions.collapse(throwable2);
Builder rb = ApiError.builderFromThrowable(throwable3);
if (Strings.isBlank(rb.getMessage()))
rb.message("Internal error. Contact server administrator to consult logs for more details.");
if (Exceptions.isPrefixImportant(throwable3))
rb.message(Exceptions.getPrefixText(throwable3)+": "+rb.getMessage());
return rb.build().asResponse(Status.INTERNAL_SERVER_ERROR, MediaType.APPLICATION_JSON_TYPE);
}
}
@@ -33,6 +33,7 @@
import javax.annotation.Nullable;

import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.javalang.JavaClassNames;
import org.apache.brooklyn.util.text.Strings;

import com.google.common.base.Predicate;
@@ -324,7 +325,23 @@ public static RuntimeException create(@Nullable String prefix, Collection<? exte
return new CompoundRuntimeException(prefix, exceptions);
}
if (Strings.isBlank(prefix)) return new CompoundRuntimeException(exceptions.size()+" errors, including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions);
return new CompoundRuntimeException(prefix+", "+exceptions.size()+" errors including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions);
return new CompoundRuntimeException(prefix+"; "+exceptions.size()+" errors including: " + Exceptions.collapseText(exceptions.iterator().next()), exceptions);
}

/** Some throwables require a prefix for the message to make sense,
* for instance NoClassDefFoundError's message is often just the type.
*/
public static boolean isPrefixImportant(Throwable t) {
if (t instanceof NoClassDefFoundError) return true;
return false;
}

/** For {@link Throwable} instances where know {@link #isPrefixImportant(Throwable)},
* this returns a nice message for use as a prefix; otherwise this returns the class name.
* Callers should typically suppress the prefix if {@link #isPrefixBoring(Throwable)} is true. */
public static String getPrefixText(Throwable t) {
if (t instanceof NoClassDefFoundError) return "Type not found";
return JavaClassNames.cleanSimpleClassName(t);
}

}

0 comments on commit 01833f2

Please sign in to comment.