logtree: implement raw logging

Test Plan: Covered by new tests.

X-Origin-Diff: phab/D640
GitOrigin-RevId: 786ab2851710bf2819dcb91571b3567e8da3e377
diff --git a/core/pkg/logtree/journal.go b/core/pkg/logtree/journal.go
index fe6d80c..893eff0 100644
--- a/core/pkg/logtree/journal.go
+++ b/core/pkg/logtree/journal.go
@@ -106,20 +106,19 @@
 	}
 }
 
-// filter is a predicate that returns true if a log subscriber or reader is interested in a log entry at a given
-// severity and logged to a given DN.
-type filter func(origin DN, severity Severity) bool
+// filter is a predicate that returns true if a log subscriber or reader is interested in a given log entry.
+type filter func(*entry) bool
 
-// filterALl returns a filter that accepts all log entries.
+// filterAll returns a filter that accepts all log entries.
 func filterAll() filter {
-	return func(origin DN, _ Severity) bool { return true }
+	return func(*entry) bool { return true }
 }
 
 // filterExact returns a filter that accepts only log entries at a given exact DN. This filter should not be used in
 // conjunction with journal.scanEntries - instead, journal.getEntries should be used, as it is much faster.
 func filterExact(dn DN) filter {
-	return func(origin DN, _ Severity) bool {
-		return origin == dn
+	return func(e *entry) bool {
+		return e.origin == dn
 	}
 }
 
@@ -131,8 +130,8 @@
 	}
 
 	rootParts := strings.Split(string(root), ".")
-	return func(origin DN, _ Severity) bool {
-		parts := strings.Split(string(origin), ".")
+	return func(e *entry) bool {
+		parts := strings.Split(string(e.origin), ".")
 		if len(parts) < len(rootParts) {
 			return false
 		}
@@ -150,11 +149,19 @@
 // filterSeverity returns a filter that accepts log entries at a given severity level or above. See the Severity type
 // for more information about severity levels.
 func filterSeverity(atLeast Severity) filter {
-	return func(origin DN, s Severity) bool {
-		return s.AtLeast(atLeast)
+	return func(e *entry) bool {
+		return e.leveled != nil && e.leveled.severity.AtLeast(atLeast)
 	}
 }
 
+func filterOnlyRaw(e *entry) bool {
+	return e.raw != nil
+}
+
+func filterOnlyLeveled(e *entry) bool {
+	return e.leveled != nil
+}
+
 // scanEntries does a linear scan through the global entry list and returns all entries that match the given filters. If
 // retrieving entries for an exact event, getEntries should be used instead, as it will leverage DN-local linked lists
 // to retrieve them faster.
@@ -168,7 +175,7 @@
 
 		passed := true
 		for _, filter := range filters {
-			if !filter(cur.origin, cur.leveled.severity) {
+			if !filter(cur) {
 				passed = false
 				break
 			}
@@ -193,7 +200,7 @@
 
 		passed := true
 		for _, filter := range filters {
-			if !filter(cur.origin, cur.leveled.severity) {
+			if !filter(cur) {
 				passed = false
 				break
 			}