Merge pull request #1430 from zan-mateusz/fixes/coercion-error-logbook-class-filtering-dynamic-update
Fixes/coercion error logbook class filtering dynamic update
diff --git a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
index 75dcb0b..dd773ea 100644
--- a/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
+++ b/core/src/main/java/org/apache/brooklyn/core/catalog/internal/CatalogInitialization.java
@@ -312,10 +312,10 @@
/**
* Populates the initial catalog, but not via an official code-path.
- *
- * Expected to be called only during tests, where the test has not gone through the same
+ *
+ * Expected to be called only during tests, where the test has not gone through the same
* management-context lifecycle as is done in BasicLauncher.
- *
+ *
* Subsequent calls will fail to things like {@link #populateInitialCatalogOnly()} or
* {@link #populateInitialAndPersistedCatalog(ManagementNodeState, PersistedCatalogState, RebindExceptionHandler, RebindLogger)}.
*/
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java
index e6b89ca..a041b72 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/ha/BrooklynBomOsgiArchiveInstaller.java
@@ -145,7 +145,7 @@
private ManagementContextInternal mgmt() {
return (ManagementContextInternal) osgiManager.getManagementContext();
}
-
+
private synchronized void init() {
if (result!=null) {
if (zipFile!=null || zipIn==null) return;
@@ -836,6 +836,7 @@
throw Exceptions.propagate(e);
}
}
+
}
};
if (deferredStart) {
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/logbook/LogBookQueryParams.java b/core/src/main/java/org/apache/brooklyn/util/core/logbook/LogBookQueryParams.java
index d726b57..704eb48 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/logbook/LogBookQueryParams.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/logbook/LogBookQueryParams.java
@@ -50,6 +50,9 @@
private String entityId;
+ /** The logger/class name prefix to filter log items by, e.g. "o.a.b.SSH" */
+ private String loggerName;
+
public Integer getNumberOfItems() {
return numberOfItems;
}
@@ -121,4 +124,12 @@
public void setEntityId(String entityId) {
this.entityId = entityId;
}
+
+ public String getLoggerName() {
+ return loggerName;
+ }
+
+ public void setLoggerName(String loggerName) {
+ this.loggerName = loggerName;
+ }
}
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/logbook/file/FileLogStore.java b/core/src/main/java/org/apache/brooklyn/util/core/logbook/file/FileLogStore.java
index 375ec07..5b37b77 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/logbook/file/FileLogStore.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/logbook/file/FileLogStore.java
@@ -196,6 +196,11 @@
if (Strings.isBlank(brooklynLogEntry.getMessage()) || !brooklynLogEntry.getMessage().contains(params.getSearchPhrase())) return false;
}
+ // Check logger/class name prefix.
+ if (Strings.isNonBlank(params.getLoggerName())) {
+ if (Strings.isBlank(brooklynLogEntry.getClazz()) || !brooklynLogEntry.getClazz().startsWith(params.getLoggerName())) return false;
+ }
+
return true;
};
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStore.java b/core/src/main/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStore.java
index 4a98893..9c76a66 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStore.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStore.java
@@ -305,6 +305,11 @@
queryBoolMustListBuilder.add(buildMatchPhraseOf("message", params.getSearchPhrase()));
}
+ // Apply logger/class name prefix.
+ if (Strings.isNonBlank(params.getLoggerName())) {
+ queryBoolMustListBuilder.add(ImmutableMap.of("prefix", ImmutableMap.of("class", params.getLoggerName())));
+ }
+
ImmutableList<Object> queryBoolMustList = queryBoolMustListBuilder.build();
if (queryBoolMustList.isEmpty()) {
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java
index c9468f1..65a40db 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/internal/TypeCoercionsTest.java
@@ -355,11 +355,41 @@
public void testYamlMapsDontGoTooFarWhenWantingListOfString() {
List<?> s = TypeCoercions.coerce("[ a: 1, b: 2 ]", List.class);
assertEquals(s, ImmutableList.of(MutableMap.of("a", 1), MutableMap.of("b", 2)));
-
+
s = TypeCoercions.coerce("[ a: 1, b : 2 ]", new TypeToken<List<String>>() {});
assertEquals(s, ImmutableList.of("a: 1", "b : 2"));
}
+ @SuppressWarnings("serial")
+ @Test
+ public void testYamlBlockListCoercionToStringList() {
+ // YAML block list syntax should be parsed correctly for List<String>
+ List<?> s = TypeCoercions.coerce("- a\n- b", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("a", "b"));
+
+ s = TypeCoercions.coerce("- a\n- b\n- c", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("a", "b", "c"));
+
+ // single item
+ s = TypeCoercions.coerce("- a", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("a"));
+
+ // multi-word items
+ s = TypeCoercions.coerce("- hello world\n- foo bar", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("hello world", "foo bar"));
+
+ // numeric items should coerce to strings
+ s = TypeCoercions.coerce("- 1\n- 2", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("1", "2"));
+
+ // comma-separated and bracket forms still work for List<String>
+ s = TypeCoercions.coerce("a, b, c", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("a", "b", "c"));
+
+ s = TypeCoercions.coerce("[a, b]", new TypeToken<List<String>>() {});
+ assertEquals(s, ImmutableList.of("a", "b"));
+ }
+
@Test
public void testURItoStringCoercion() {
String s = TypeCoercions.coerce(URI.create("http://localhost:1234/"), String.class);
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/logbook/file/FileLogStoreTest.java b/core/src/test/java/org/apache/brooklyn/util/core/logbook/file/FileLogStoreTest.java
index 4b4a7a6..969cf6e 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/logbook/file/FileLogStoreTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/logbook/file/FileLogStoreTest.java
@@ -496,6 +496,58 @@
assertTrue(brooklynLogEntries.stream().anyMatch(Predicates.not(e -> e.getTaskId().equals(logBookQueryParams.getTaskId()))));
}
+ @Test
+ public void testQueryLogSampleWithLoggerName() {
+ File file = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(JAVA_LOG_SAMPLE_PATH)).getFile());
+ mgmt = LocalManagementContextForTests.newInstance();
+ mgmt.getBrooklynProperties().put(LOGBOOK_LOG_STORE_PATH.getName(), file.getAbsolutePath());
+ LogBookQueryParams logBookQueryParams = new LogBookQueryParams();
+ logBookQueryParams.setNumberOfItems(1000);
+ logBookQueryParams.setTail(false);
+ logBookQueryParams.setLevels(ImmutableList.of());
+ logBookQueryParams.setLoggerName("i.c.b"); // matches all AbstractToscaYamlConverter entries
+ FileLogStore fileLogStore = new FileLogStore(mgmt);
+ List<BrooklynLogEntry> brooklynLogEntries = fileLogStore.query(logBookQueryParams);
+
+ assertEquals(4, brooklynLogEntries.size());
+ assertTrue(brooklynLogEntries.stream().allMatch(e -> e.getClazz().startsWith("i.c.b")));
+ }
+
+ @Test
+ public void testQueryLogSampleWithLoggerNameAndPhrase() {
+ File file = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(JAVA_LOG_SAMPLE_PATH)).getFile());
+ mgmt = LocalManagementContextForTests.newInstance();
+ mgmt.getBrooklynProperties().put(LOGBOOK_LOG_STORE_PATH.getName(), file.getAbsolutePath());
+ LogBookQueryParams logBookQueryParams = new LogBookQueryParams();
+ logBookQueryParams.setNumberOfItems(1000);
+ logBookQueryParams.setTail(false);
+ logBookQueryParams.setLevels(ImmutableList.of());
+ logBookQueryParams.setLoggerName("i.c.b");
+ logBookQueryParams.setSearchPhrase("testing");
+ FileLogStore fileLogStore = new FileLogStore(mgmt);
+ List<BrooklynLogEntry> brooklynLogEntries = fileLogStore.query(logBookQueryParams);
+
+ assertEquals(2, brooklynLogEntries.size());
+ assertTrue(brooklynLogEntries.stream().allMatch(e -> e.getClazz().startsWith("i.c.b")));
+ assertTrue(brooklynLogEntries.stream().allMatch(e -> e.getMessage().contains("testing")));
+ }
+
+ @Test
+ public void testQueryLogSampleWithNonMatchingLoggerName() {
+ File file = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(JAVA_LOG_SAMPLE_PATH)).getFile());
+ mgmt = LocalManagementContextForTests.newInstance();
+ mgmt.getBrooklynProperties().put(LOGBOOK_LOG_STORE_PATH.getName(), file.getAbsolutePath());
+ LogBookQueryParams logBookQueryParams = new LogBookQueryParams();
+ logBookQueryParams.setNumberOfItems(1000);
+ logBookQueryParams.setTail(false);
+ logBookQueryParams.setLevels(ImmutableList.of());
+ logBookQueryParams.setLoggerName("o.a.b.SSH"); // no entries with this class prefix
+ FileLogStore fileLogStore = new FileLogStore(mgmt);
+ List<BrooklynLogEntry> brooklynLogEntries = fileLogStore.query(logBookQueryParams);
+
+ assertEquals(0, brooklynLogEntries.size());
+ }
+
private LogBookQueryParams newQueryParams(boolean recursive) {
LogBookQueryParams params = new LogBookQueryParams();
params.setNumberOfItems(5); // Request first five only
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStoreTest.java b/core/src/test/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStoreTest.java
index 5517111..393d0df 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStoreTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/logbook/opensearch/OpenSearchLogStoreTest.java
@@ -171,6 +171,31 @@
}
@Test
+ public void queryWithLoggerName() {
+ OpenSearchLogStore cut = new OpenSearchLogStore();
+ LogBookQueryParams p = new LogBookQueryParams();
+ p.setNumberOfItems(10);
+ p.setTail(false);
+ p.setLevels(ImmutableList.of());
+ p.setLoggerName("o.a.b.SSH");
+ String query = cut.getJsonQuery(p);
+ assertEquals(query, "{\"sort\":{\"timestamp\":\"asc\"},\"size\":10,\"query\":{\"bool\":{\"must\":[{\"prefix\":{\"class\":\"o.a.b.SSH\"}}]}}}");
+ }
+
+ @Test
+ public void queryWithLoggerNameAndPhrase() {
+ OpenSearchLogStore cut = new OpenSearchLogStore();
+ LogBookQueryParams p = new LogBookQueryParams();
+ p.setNumberOfItems(10);
+ p.setTail(false);
+ p.setLevels(ImmutableList.of());
+ p.setLoggerName("o.a.b.SSH");
+ p.setSearchPhrase("some phrase");
+ String query = cut.getJsonQuery(p);
+ assertEquals(query, "{\"sort\":{\"timestamp\":\"asc\"},\"size\":10,\"query\":{\"bool\":{\"must\":[{\"match_phrase\":{\"message\":\"some phrase\"}},{\"prefix\":{\"class\":\"o.a.b.SSH\"}}]}}}");
+ }
+
+ @Test
public void queryWithTaskIdAndPhrase() {
OpenSearchLogStore cut = new OpenSearchLogStore();
LogBookQueryParams p = new LogBookQueryParams();
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/task/AutoFlagsCallbackTest.java b/core/src/test/java/org/apache/brooklyn/util/core/task/AutoFlagsCallbackTest.java
index 37d2361..bf7eb59 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/task/AutoFlagsCallbackTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/task/AutoFlagsCallbackTest.java
@@ -55,8 +55,8 @@
Asserts.assertThat(depth.get(), x -> x>=0);
app.start(null);
- // but by the time start completes it should be back to 0
- Asserts.assertEquals(depth.get(), 0);
+ // sensor tasks triggered during start may complete slightly after start() returns; wait for them
+ Asserts.eventually(() -> depth.get(), x -> x == 0);
Entities.submit(app, Tasks.create("test1", () -> {
log.info("running test 1" + " / " + Tasks.current().getId());
diff --git a/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java b/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
index a3f4c32..97ef1bc 100644
--- a/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
+++ b/launcher/src/test/java/org/apache/brooklyn/launcher/BrooklynLauncherUpgradeCatalogOsgiTest.java
@@ -406,7 +406,7 @@
assertEquals(resultWithoutForceCode, ResultCode.IGNORING_BUNDLE_FORCIBLY_REMOVED);
assertEquals(resultWithoutForce.get().getMetadata().getVersionedName(), bundleV2.getVersionedName());
assertTrue(resultWithoutForceMessage.contains("Bundle "+bundleV1.getVersionedName()+" forcibly removed, upgraded to 2.0.0"), "msg="+resultWithoutForceMessage);
-
+
launcher.terminate();
}
}
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
index a792c70..563fe12 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
@@ -441,8 +441,25 @@
Maybe<?> resultM = null;
Collection<?> result = null;
if (parameters.length==1 && TypeTokens.isAssignableFromRaw(CharSequence.class, parameters[0])) {
- // for list of strings, use special parse
- result = JavaStringEscapes.unwrapJsonishListStringIfPossible(inputS);
+ // for list of strings: if input uses YAML block list syntax ("- item" lines), parse
+ // it directly with YAML (wrapping in brackets kills the block sequence markers).
+ // Only adopt the YAML result when all elements are simple values — this preserves
+ // the behaviour that "[ a: 1, b: 2 ]" stays as ["a: 1", "b: 2"] rather than
+ // being coerced from map objects to their toString representations.
+ if (inputS.trim().startsWith("- ")) {
+ try {
+ Object yamlDoc = Iterables.getOnlyElement(Yamls.parseAll(inputS));
+ if (yamlDoc instanceof List &&
+ ((List<?>) yamlDoc).stream().noneMatch(x -> x instanceof Map || x instanceof Collection)) {
+ result = (Collection<?>) yamlDoc;
+ }
+ } catch (Exception e) {
+ Exceptions.propagateIfFatal(e);
+ }
+ }
+ if (result == null) {
+ result = JavaStringEscapes.unwrapJsonishListStringIfPossible(inputS);
+ }
} else {
// any other type, use YAMLish parse
resultM = JavaStringEscapes.tryUnwrapJsonishList(inputS);