-
Notifications
You must be signed in to change notification settings - Fork 341
Introduce Traceformat to allow JSON format log #366
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
Conversation
@octref goes absolutely into the right direction. Only one little comment so far. |
Hey Dirk, there are a bunch of updates that happened, so I'm wondering if you can take another look at this PR. Also /cc @aeschli in case you are interested. High Level ChangesThis PR remain as it is, so:
For streaming support, it can be implemented trivially by Language Server authors using the existing API This goes against what we initially agreed on, e.g:
the benefit of leaving out logging / websocket-streaming is that we don't add dependencies ( How Things Work NowThere are 3 repos:
Play With It
|
jsonrpc/src/messages.ts
Outdated
type: LSPMessageType; | ||
message: RequestMessage | ResponseMessage | NotificationMessage; | ||
timestamp: number; | ||
} |
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.
LSP uses tabs not spaces
@@ -205,6 +206,36 @@ export namespace Trace { | |||
} | |||
} | |||
|
|||
export enum TraceFormat { |
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.
Instead of having a number enum and a TraceFormatValues would it make sense to use a string Enum which is now supported by TS?
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.
Was aligning to TraceValues
, string enum makes sense.
jsonrpc/src/main.ts
Outdated
@@ -224,6 +255,7 @@ export namespace LogTraceNotification { | |||
|
|||
export interface Tracer { | |||
log(message: string, data?: string): void; | |||
logLSP(message: string): void; |
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 a breaking API change. We should either make it optional or reuse the log
signature. I looked at the client code and I was under the impression that the only difference is that the log
prints [Trace - ...] and logLSP
prints [LSP - ...]. Since the client knows the log format could this be decided on the client side.
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.
Actually we should have a log method that takes an JSON object literal. So the JSON RPC code shouldn't even convert it to a strings. Then someone could plug in a tracer that writes the JSON objects to a file.
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.
Actually we should have a log method that takes an JSON object literal.
NVM, found a way to do that.
protocol/src/main.ts
Outdated
@@ -157,7 +157,7 @@ export interface ProtocolConnection { | |||
/** | |||
* Enables tracing mode for the connection. | |||
*/ | |||
trace(value: Trace, tracer: Tracer, sendNotification?: boolean): void; | |||
trace(value: Trace, traceFormat: TraceFormat, tracer: Tracer, sendNotification?: boolean): void; |
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 breaking as well. We should support this in a non breaking way by having two signatures. If the old one is used we do the old text tracing.
client/src/client.ts
Outdated
}); | ||
} | ||
|
||
public set traceFormat(value: TraceFormat) { |
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.
Would it make sense to fold that into trace as an optional param. If not provided it is text. I doubt that users set this independently.
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.
Sure, since trace
function already covers the format as an optional param. However I'm wondering if you mind adding traceFormat
as one of the LanguageClientOptions
? I feel this is something people want to configure on LS Client init but not setting it each time.
protocol/src/main.ts
Outdated
@@ -157,7 +157,7 @@ export interface ProtocolConnection { | |||
/** | |||
* Enables tracing mode for the connection. | |||
*/ | |||
trace(value: Trace, tracer: Tracer, sendNotification?: boolean): void; | |||
trace(value: Trace, traceFormat: TraceFormat, tracer: Tracer, sendNotification?: boolean): void; |
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.
Same as on the implementation side. This is breaking...
@octref provided by comments. |
@@ -2498,6 +2505,17 @@ export abstract class BaseLanguageClient { | |||
} | |||
} | |||
|
|||
private logObjectTrace(data: any): void { | |||
if (data.isLSPMessage && data.type) { |
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.
@dbaeumer Not sure if this is what you meant by "if the data is an object then log it by JSON stringify here". Also not sure if that isLSPMessage
is the best way to go. If you have better suggestions, let me know!
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.
No, in this case I would simply do
this.outputChannel.append(`[LSP - ${(new Date().toLocaleTimeString())}] `);
this.outputChannel.appendLine(`${JSON.stringify(data)}`);
Addressed comments, but left some questions too. |
client/src/client.ts
Outdated
@@ -161,7 +161,7 @@ function createConnection(input: any, output: any, errorHandler: ConnectionError | |||
sendNotification: (type: string | RPCMessageType, params?: any): void => connection.sendNotification(Is.string(type) ? type : type.method, params), | |||
onNotification: (type: string | RPCMessageType, handler: GenericNotificationHandler): void => connection.onNotification(Is.string(type) ? type : type.method, handler), | |||
|
|||
trace: (value: Trace, tracer: Tracer, sendNotification: boolean = false): void => connection.trace(value, tracer, sendNotification), | |||
trace: (value: Trace, tracer: Tracer, sendNotification: boolean = false, traceFormat: TraceFormat = TraceFormat.Text): void => connection.trace(value, tracer, sendNotification, traceFormat), |
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 know it is easier to implement if we simply add an optional arg at the endd but I would prefer to have to signatures like this:
trace: (value: Trace, tracer: Tracer, sendNotification: boolean = false)
trace: (value: Trace, traceFormat: TraceFormat, tracer: Tracer, sendNotification: boolean = false)
to keep the args together and may be deprecate the old signature.
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.
@dbaeumer Decided to have this:
trace(value: Trace, tracer: Tracer, sendNotification?: boolean): void;
trace(value: Trace, tracer: Tracer, traceOptions?: TraceOptions): void;
// In json-rpc
export interface TraceOptions {
sendNotification?: boolean;
traceFormat?: TraceFormat;
}
I initially had what you suggested, but later abandoned it in favor of traceFormat?
at the end, as
- I'd prefer to keep
traceFormat
optional - A call with three args can be of either signature.
With this new one it's easier to detect the params of the overloaded functions, and in the future it's easier to add more options without breaking backward compatibility.
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.
No, this is not what I meant. I was suggesting to have this:
trace: (value: Trace, tracer: Tracer, sendNotification: boolean = false)
trace: (value: Trace, traceFormat: TraceFormat, tracer: Tracer, sendNotification: boolean = false)
with one implementation overload like this:
function trace(arg0: Trace, arg1: Tracer | TraceFormat, arg2?: Tracer | boolean, arg3?: boolean)
There is enough information in the signatures to decide which on is meant.
protocol/src/main.ts
Outdated
@@ -158,6 +158,7 @@ export interface ProtocolConnection { | |||
* Enables tracing mode for the connection. | |||
*/ | |||
trace(value: Trace, tracer: Tracer, sendNotification?: boolean): void; | |||
trace(value: Trace, tracer: Tracer, sendNotification?: boolean, traceFormat?: TraceFormat): void; |
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.
Same as above
client/src/client.ts
Outdated
this.logTrace(message, data); | ||
} | ||
log: (...params: any[]) => { | ||
if (typeof params[0] === '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.
There is a Is.string() helper I consistently use.
client/src/client.ts
Outdated
log: (message: string, data?: string) => { | ||
this.logTrace(message, data); | ||
} | ||
log: (...params: any[]) => { |
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 this not still be message & data and message can be string | any. ...params makes it harder to understand what data can actually come.
Things I plan to do but haven't done yet:
verbosity
is set tomessage
, ignoreparams
on Request / Notification messagestraceFormat
to client's initialization paramsQuestions:
[langId].lsp.trace
?server
is misleading as the logs are actually logged from the client perspective. I'll write documentation for this too so I hope we can get this right.@dbaeumer Would like to get some high-level insight - let me know if this is the right direction, what more things you would want to me to add, etc.
More details are at microsoft/language-server-protocol-inspector#8