-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring event logs #821
Conversation
DirectBuffer buffer, | ||
int index, | ||
int length); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add
public final class EventFomatter
{
public static EventFomatter instantiate()
{
... use service loader to discover event formatter spis and return an event formatter that can delegate
}
public String format(
int msgTypeId,
DirectBuffer buffer,
int index,
int length)
{
... lookup event formatter spi by type id and return formatted event
}
}
String formatEventEx( | ||
int msgTypeId, | ||
DirectBuffer buffer, | ||
int index, | ||
int length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String formatEventEx( | |
int msgTypeId, | |
DirectBuffer buffer, | |
int index, | |
int length); | |
String format( | |
DirectBuffer buffer, | |
int index, | |
int length); |
We already advertised our required type, so we don't need to pass it again here.
Map<String, EventFormatterSpi> formatters = ServiceLoader.load(EventFormatterSpi.class) | ||
.stream() | ||
.collect(Collectors.toMap( | ||
provider -> provider.get().type(), | ||
provider -> provider.get() | ||
)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move this service loader code to the engine
, exposed as an EventFormatter
obtained from EngineContext
.
See comments on EventFormatterSpi
for more details.
(normally we don't expose the spis outside of the engine except as interfaces for implementation classes)
@@ -48,7 +53,7 @@ public ExporterHandler attach( | |||
LongFunction<KindConfig> resolveKind) | |||
{ | |||
StdoutExporterConfig stdoutExporter = new StdoutExporterConfig(exporter); | |||
return new StdoutExporterHandler(config, context, stdoutExporter); | |||
return new StdoutExporterHandler(config, formatters, context, stdoutExporter); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return new StdoutExporterHandler(config, formatters, context, stdoutExporter); | |
return new StdoutExporterHandler(config, formatter, context, stdoutExporter); |
where formatter
is an EventFormatter
provided by the engine
private static final String FORMAT = "%s [%s] %s%n"; // qname [timestamp] extension\n | ||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer we use a single format and avoid the supplementary date time formatter.
See https://stackoverflow.com/a/61502608
private static final String FORMAT = "%s [%s] %s%n"; // qname [timestamp] extension\n | |
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z"); | |
private static final String FORMAT = "%s [%2$tD:%2$tT] %s%n"; // qname [timestamp] extension\n |
@@ -63,6 +63,6 @@ public class Http2EventsIT | |||
public void connectionHeaders() throws Exception | |||
{ | |||
k3po.finish(); | |||
output.expect(Pattern.compile("test.net0 - \\[[^\\]]+\\] REQUEST_ACCEPTED http GET localhost:8080 /\n")); | |||
output.expect(Pattern.compile("ephemeral.net0 \\[[^\\]]+\\] REQUEST_ACCEPTED - http GET localhost:8080 /\n")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be the wrong binding id on the event.
We need to change this test to use test
binding and break dependency on http
binding, then additional type-specific tests in the stdout exporter are no longer needed.
import io.aklivity.zilla.runtime.binding.http.internal.types.event.HttpRequestAcceptedExFW; | ||
import io.aklivity.zilla.runtime.engine.event.EventFormatterSpi; | ||
|
||
public class HttpEventFormatter implements EventFormatterSpi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that formatters are not thread-safe, we'll need to switch up the spi strategy to use an EventFormatterFactorySpi
that creates an EventFormatterSpi
when needed to instantiate an EventFormatter
per worker, instead of one instance of each EventFormatterSpi
shared across all workers.
import io.aklivity.zilla.runtime.binding.http.internal.types.event.EventFW; | ||
import io.aklivity.zilla.runtime.binding.http.internal.types.event.HttpEventExFW; | ||
|
||
public class HttpEventFormatterTest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize you prefer to write this as a unit test, but now I think we don't actually have an IT that proves the event is written when the scenario occurs, say like authorization failed.
Suggest we instead convert these unit tests to ITs and configure test exporter to have a list of expected events, so we can verify binding id, formatted event text and throw an exception if they don't match so the IT will fail.
That approach should give us good clarity in the scenarios both that the event has occurred and how it is formatted.
This feedback applies to all event formatter unit tests -> ITs.
{ | ||
case AUTHORIZATION_FAILED: | ||
{ | ||
result = AUTHORIZATION_FAILED_FORMAT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suspect we'd like to have attempted identity here, much like guard auth failed, agree?
@@ -108,6 +108,7 @@ scope core | |||
int64 timestamp; | |||
int64 traceId; | |||
int64 namespacedId; | |||
octets extension; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do this in frames because extension is optional, but it is required for events (agree?) so perhaps it would be more convenient to put Extension
as the type here instead of octets
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good so far, needs the ITs now instead of the Tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good so far.
Make sure to add tls client tests, and verify minimal dependencies on stdout exporter pom now that we only need the engine apis and test binding with test events.
@Specification({ | ||
"${app}/client.handshake.timeout/client", | ||
"${net}/client.handshake.timeout/server" }) | ||
@Configure(name = "zilla.binding.tls.handshake.timeout", value = "1") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These strings should be constants on TlsConfigurationTest, and TlsConfigurationTest test method should verify that the constant string matches the config property name.
Please apply the same feedback about constants (plus tests) to any new tests you've added that use @Configure
.
// THEN | ||
assertThat(result, equalTo("REMOTE_ACCESS_REJECTED GET http://localhost:8080/hello 500")); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be replaced by an IT, right?
import java.util.function.Function; | ||
|
||
import io.aklivity.zilla.runtime.engine.config.OptionsConfig; | ||
|
||
public final class TestBindingOptionsConfig extends OptionsConfig | ||
{ | ||
public final String mode; | ||
public final List<String> catalogs; | ||
public final List<Guard> guards; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change guards
of type List<Guard>
to authorization
(one, not list) of type TestAuthorizationConfig
with a String name
(of the referenced guard) and credentials
(the token). This is more or less how we do it for HTTP binding with HttpAuthorizationConfig
except that one is extracting the token from a patterned string, and here we can just specify the token directly instead.
The syntax in yaml
should also follow the same approach as other binding authorization
syntax.
bindings:
test0:
type: test
kind: server
options:
authorization:
jwt0:
credentials: token
// THEN | ||
assertThat(result, equalTo("AUTHORIZATION_FAILED user")); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be removed as we have an IT instead that exercises the event formatter via declarative test.
Please remove all the other event formatter tests as they are also covered by their ITs instead.
"guards": | ||
{ | ||
"type": "array", | ||
"items": | ||
{ | ||
"type": "object", | ||
"properties": | ||
{ | ||
"guard": | ||
{ | ||
"type": "string" | ||
}, | ||
"token": | ||
{ | ||
"type": "string" | ||
} | ||
} | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change to authorization
with patternProperties
and credentials
as described in other feedback comment.
bindings: | ||
net0: | ||
type: test | ||
kind: server | ||
options: | ||
guards: | ||
- guard: jwt0 | ||
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImV4YW1wbGUifQ.eyJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImV4cCI6MTcwODk0MDQ0MCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmV4YW1wbGUuY29tIiwic3ViIjoidXNlciJ9.KwZt_rDTDEOQ33URwZ8Gd1WqQjAIJESbt5Et309Yz7AJm1wWWyFhWm7AV6lt1rkX-eD-jVh0wHAsy7L4kdzBOErCdwFcdaB4u2jFDGn_9IK28lCedxIYmYtI4qn6eY916IIqRpwZcqzw08OEljfYUKo4UeX7JPAtha0GQmfZY1-NNcncg06xw3xkKSZ1SnIh9MZM1FNH_5QPZPL4NHP7DRXtaMn2w6YpO7n695Sc_3LuSDlfDDMVIUWuEreOzOXem6jheGIbJ-eDKhIXXPrOz1NBAJmvizbugMR7m_bodiEzzqt5ttKDs1974alrR_sYP8OYmR_rCqXc5N3lp_SW3A | ||
exit: app0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bindings: | |
net0: | |
type: test | |
kind: server | |
options: | |
guards: | |
- guard: jwt0 | |
token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImV4YW1wbGUifQ.eyJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImV4cCI6MTcwODk0MDQ0MCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmV4YW1wbGUuY29tIiwic3ViIjoidXNlciJ9.KwZt_rDTDEOQ33URwZ8Gd1WqQjAIJESbt5Et309Yz7AJm1wWWyFhWm7AV6lt1rkX-eD-jVh0wHAsy7L4kdzBOErCdwFcdaB4u2jFDGn_9IK28lCedxIYmYtI4qn6eY916IIqRpwZcqzw08OEljfYUKo4UeX7JPAtha0GQmfZY1-NNcncg06xw3xkKSZ1SnIh9MZM1FNH_5QPZPL4NHP7DRXtaMn2w6YpO7n695Sc_3LuSDlfDDMVIUWuEreOzOXem6jheGIbJ-eDKhIXXPrOz1NBAJmvizbugMR7m_bodiEzzqt5ttKDs1974alrR_sYP8OYmR_rCqXc5N3lp_SW3A | |
exit: app0 | |
bindings: | |
net0: | |
type: test | |
kind: server | |
options: | |
authorization: | |
jwt0: | |
credentials: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImV4YW1wbGUifQ.eyJhdWQiOiJodHRwczovL2FwaS5leGFtcGxlLmNvbSIsImV4cCI6MTcwODk0MDQ0MCwiaXNzIjoiaHR0cHM6Ly9hdXRoLmV4YW1wbGUuY29tIiwic3ViIjoidXNlciJ9.KwZt_rDTDEOQ33URwZ8Gd1WqQjAIJESbt5Et309Yz7AJm1wWWyFhWm7AV6lt1rkX-eD-jVh0wHAsy7L4kdzBOErCdwFcdaB4u2jFDGn_9IK28lCedxIYmYtI4qn6eY916IIqRpwZcqzw08OEljfYUKo4UeX7JPAtha0GQmfZY1-NNcncg06xw3xkKSZ1SnIh9MZM1FNH_5QPZPL4NHP7DRXtaMn2w6YpO7n695Sc_3LuSDlfDDMVIUWuEreOzOXem6jheGIbJ-eDKhIXXPrOz1NBAJmvizbugMR7m_bodiEzzqt5ttKDs1974alrR_sYP8OYmR_rCqXc5N3lp_SW3A | |
exit: app0 |
Description
This change refactors the event definitions and introduces *EventFormatter classes.