-
Notifications
You must be signed in to change notification settings - Fork 326
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
Simplify logging interface & add RPC method #121
Conversation
AddPathStart("VK_DEVICE_LAYERS", "VkGraphicsSpy"). | ||
AddPathStart("VK_LAYER_PATH", libVkLayerGraphicsSpy.Parent().System()). | ||
Set("LD_PRELOAD", libgapii.System()), | ||
}) |
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.
It's related. There's new logic to handle stdout and stderr, which adds more options to the start function. Given the number of parameters we're passing in, I opted for a struct.
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.
Yes, I noticed that later. Sorry, I didn't realize it sends out comments right away. Is there no draft comment mode like Critique/Gerrit?
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.
Yes. Next to the single line comment button there should be a "Start Review" green button.
Now also contains GAPIC changes to display the merged logs across GAPIC, GAPIS and GAPIR. |
I'm following up with a final CL that avoids the |
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.
FYI: i've checked in a .settings folder which enables a lot of warnings in Eclipse.
dirty.set(false); | ||
} | ||
|
||
private String formatTime(Timestamp time) { |
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 static
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.
Done.
case Fatal: | ||
return theme.fatalBackground(); | ||
} | ||
return theme.infoBackground(); |
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 into a default case to make the behavior more explicit.
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.
Done.
case Fatal: | ||
return theme.fatalForeground(); | ||
} | ||
return theme.infoForeground(); |
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 into a default case to make the behavior more explicit.
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.
Done.
private Color severityBackgroundColor(Log.Severity severity) { | ||
switch (severity) { | ||
case Verbose: | ||
return theme.verboseBackground(); |
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.
nit: since the case statements are so simple, I'd prefer them to be on one line:
case Verbose: return theme.verboseBackground();
case Debug: return theme.debugBackground();
...
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.
Done.
@@ -15,54 +15,64 @@ | |||
*/ | |||
package com.google.gapid.util; | |||
|
|||
import com.google.gapid.proto.log.Log; | |||
import com.google.gapid.rpclib.schema.Method; |
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.
not actually needed
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.
Done.
|
||
static LogLevel fromLevel(Level level) { | ||
for (LogLevel logLevel : LogLevel.values()) { | ||
if (logLevel.level == level) { |
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 range based as it was before.
java.util.logging.Level is not an enum, so you also should not use '==', but .equals.
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.
Done.
} | ||
|
||
/** | ||
* Adds a {@link Log.Message} to the buffer, bypassing the Java {@link LogManager}. |
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.
Unfortunately this needs to be {@link com.google.gapid.proto.log.Log.Message}
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.
Is this Eclipse telling you this? IntelliJ seems fine with it as-is.
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.
Yes and no. Eclipse does give me the warning, but it comes straight from javadoc:
src/main/com/google/gapid/util/Logging.java:145: warning - Tag @link: reference not found: Log.Message
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.
Done.
private static final String GAPID_PREFIX = "com.google.gapid."; | ||
private static final String GOOG_PREFIX = "com.google."; | ||
|
||
private static String shorten(String className) { |
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.
make this protected, as you are using it from multiple inner classes
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'm sure I've asked this before, but why is this an issue?
Done anyway.
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.
The JVM has no concept (almost) of inner classes. To the JVM, an inner class and its container outer class are simply two different classes. You cannot call private methods of another class. The compiler adds synthetic methods to make it look like you can call private methods from inner/outer classes. These synthetic methods add unnecessary overhead and pollute stack traces. If you're going to allow access via these synthetic methods, why not give access directly?
public Runnable listener; | ||
private final StringBuilder buffer = new StringBuilder(); | ||
private final LinkedList<Log.Message> buffer = new LinkedList<>(); |
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.
buffer is shadowing Logging.buffer. I suggest renaming Logging.buffer to Logging.messageBuffer
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.
Changed in later CL.
byte[] data = ByteStreams.toByteArray(in); | ||
SearchingInputStream is = new SearchingInputStream(in); | ||
if (!is.search(PACKAGE_DATA_MARKER.getBytes())) { | ||
throw new RuntimeException("The gapit command didn't produce the data marker."); |
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.
Resource leak: 'is' is not closed at this location.
I'd suggest making the search method static and avoid the wrapping in another input stream. The SearchingInputStream class has no additional state, so it's not needed.
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.
The SearchingInputStream class has no additional state, so it's not needed.
Well, it has the buffered reader state. I've wrapped it with a try-with-resources,
Thanks, but I use IntelliJ. :) |
import java.util.logging.Logger; | ||
import java.util.logging.StreamHandler; | ||
import java.util.LinkedList; | ||
import java.util.logging.*; |
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 no * imports. I've been following the Google style for Java, and I'd like to continue to do so.
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.
Done. Another IntelliJ default that I continually battle.
|
||
/** | ||
* Logging setup and utilities. | ||
*/ | ||
public class Logging { | ||
/** | ||
* Possible log level flag values. | ||
* Possible logMessage level flag values. |
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.
Search replace?
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.
Refactor gone crazy. Fixed.
} | ||
|
||
public static final Flag<LogLevel> logLevel = Flags.value( | ||
"logLevel", LogLevel.INFO, "Logging level [OFF, ERROR, WARNING, INFO, DEBUG, ALL]."); | ||
public static final Flag<String> logDir = Flags.value( | ||
"logDir", System.getProperty("java.io.tmpdir"), "Directory for log files."); | ||
"logDir", System.getProperty("java.io.tmpdir"), "Directory for logMessage files."); |
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.
Search replace?
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.
Done.
@@ -83,7 +93,7 @@ public static void init() { | |||
|
|||
if (!logDir.get().isEmpty()) { | |||
try { | |||
FileHandler fileHandler = new FileHandler(logDir.get() + File.separator + "gapic.log"); | |||
FileHandler fileHandler = new FileHandler(logDir.get() + File.separator + "gapic.logMessage"); |
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.
Search replace?
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.
Done.
} | ||
|
||
/** | ||
* Adds a {@link Log.Message} to the buffer, bypassing the Java {@link LogManager}. |
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.
Yes and no. Eclipse does give me the warning, but it comes straight from javadoc:
src/main/com/google/gapid/util/Logging.java:145: warning - Tag @link: reference not found: Log.Message
} | ||
|
||
public static void setListener(Runnable listener) { | ||
buffer.listener = (listener == null) ? () -> { /* empty */ } : listener; | ||
public static void setListener(Listener listener_) { |
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.
Name shadowing is acceptable on setters, if you're shadowing the variable you're setting.
If you don't like to do that, please use new instead of _.
@@ -123,6 +135,7 @@ public static void setListener(Runnable listener) { | |||
*/ | |||
public static void logMessage(Log.Message message) { |
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 is now very much round-about: Buffer.publish calls Logging.logMessage, which calls Buffer.add and then fires the event.
Better to keep it they way it was:
logMessage and Buffer.publish call Buffer.add
Buffer.add fires the event
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've separated Buffer
and Handler
. The inner class was doing too much - hence the extraction of the event logic. Hopefully this is now cleaner and would be nice and simple to make the classes public if needed in the future.
* new messages. | ||
*/ | ||
private static class MessageIterator implements Iterator<Log.Message> { | ||
private final Buffer buffer; |
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.
Shadows Logging.buffer.
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 the class is static, does it?
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.
Yes, because so is Logging.buffer.
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.
Fair point.
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.
Done.
if (thrown != null) { | ||
for (StackTraceElement el : thrown.getStackTrace()) { | ||
builder.addCallstack(Log.SourceLocation.newBuilder() | ||
.setFile(el.getFileName()) |
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.
el.getFileName can return null (protos don't like nulls).
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.
Done.
Service.GetLogStreamRequest request = Service.GetLogStreamRequest.newBuilder().build(); | ||
Iterator<Log.Message> it = GapidGrpc.newBlockingStub(channel).getLogStream(request); | ||
while (it.hasNext()) { | ||
monitor.onLogMessage(it.next()); |
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 now causes an exception on clean shutdown. Before closing the connection to gapis, the logger thread should be stopped.
I think you'd be better off using a StreamObserver and the async case rather than the blocking case with an extra thread.
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.
AFAICT, streamed RPCs aren't exposed in the FutureStub (if that's what you're referring to).
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.
Now unbinds the LogMonitor
on close()
. Added warning for unexpected StatusRuntimeException
s that are thrown by the thread.
Replace all uses of log.Context with context.Context. Squash the functionality of jot, memo, severity, fault into log.
Change-Id: I39df2ad33a3f780216fcbcbdcecbfd905252796e
Change-Id: I8ca1d2b11143352dfb6b8802f17c128d5dc49ee8
Change-Id: I4532f987e77b84b976a4d10adce39b75f1ce6d8e
Turn them into log.Messages. Change-Id: I95153e2a860c6db46e9a78ebc047599685239b0c
Let's you control them on the command line. Change-Id: Ib8b12a830a5a22b9f8c1c2fe2cbe00b7a451f1b0
Change-Id: I486fb73fed83100734fcb21d2bf391d44a862d51
Fixes the package picker when also logging to stdout.
Change-Id: Ic64e73cdf4d9b913594c7d02242c9c5dd06e1980
Change-Id: Ice567770dd74c9b2093c732f80be001a6e9d23c7
Change-Id: Ib103d8f824a7e0d7226584ad73127ad291dc763d
func (ctx logContext) Alert() Logger { | ||
return ctx.At(severity.Alert) | ||
func (s Severity) String() string { | ||
switch s { |
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.
Handle Verbose...
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.
Done.
return ctx.At(severity.Critical) | ||
// Short returns the severity string with a single character. | ||
func (s Severity) Short() string { | ||
switch s { |
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.
Handle Verbose...
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.
Done.
Change-Id: I15a47ec97283efdce403b87af8491295ee9c15f9
+1 |
Change-Id: If1619af5063c4e98268a8f0dcf33678970b251dd
Change-Id: I428d36fd26c984a7ffcadc50eeb948378d7b935a
import io.grpc.okhttp.OkHttpChannelProvider; | ||
|
||
/** | ||
* A connection to a running Graphics API Server (GAPIS). | ||
*/ | ||
public abstract class GapisConnection implements Closeable { | ||
private static final Logger LOG = Logger.getLogger(Client.class.getName()); |
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.
Client.class -> GapisConnection.class
@@ -23,7 +23,8 @@ | |||
import com.google.gapid.proto.pkginfo.PkgInfo; | |||
import com.google.gapid.proto.pkginfo.PkgInfo.PackageList; | |||
|
|||
import java.io.File; | |||
import java.io.*; |
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.
Another .* import.
I think you can tell intellij not to do this by setting the minimum number of classes needed before it collapses imports to some very high number.
|
||
private static final RingBuffer buffer = new RingBuffer(BUFFER_SIZE); | ||
|
||
private static final Handler handler = new Handler() {{ |
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.
You no longer need to hang on to this reference, so just create the handler in the init() method and add it to the root logger.
* {@link Handler} that handles {@link LogRecord}s converting them to | ||
* {@link com.google.gapid.proto.log.Log.Message}s and then broadcasting them to listeners. | ||
*/ | ||
protected static class Handler extends java.util.logging.Handler { |
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.
Maybe name this class ProtoHandler, or ProtoConverter?
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.
They both sound like the Proto is the source when it's the target. Opted for LogToMessageHandler
.
} | ||
Log.Severity severity = message.getSeverity(); | ||
TreeItem item = newItem(tree, severity); | ||
String[] lines = message.getText().split("(\n)|(\r\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.
split("\r?\n")
Change-Id: I1f8ac3259cf5b528feedf0a2077c4d966f53e375
Instead of
log.Context
, now usecontext.Context
.To log something use:
Values are added to the context with:
GAPII and GAPIR log messages are parsed into the structured form so they can be filtered.
New streaming RPC
GetLogStream()
monitors all log messages from GAPIS and all subprocesses interleaved. Can be used by GAPIC to display all logs across all processes.