-
Notifications
You must be signed in to change notification settings - Fork 7
sqlite: add optional ConnLogger #111
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
c5f7361 to
7572674
Compare
sqlite.go
Outdated
| // ConnLogger is implemented by the caller to support statement-level logging for | ||
| // write transactions. Only Exec calls are logged, not Query calls, as this is | ||
| // intended as a mechanism to replay failed transactions. | ||
| type ConnLogger interface { | ||
| // Begin is called when a writable transaction is opened. | ||
| Begin() | ||
|
|
||
| // Statement is called with evaluated SQL when a statement is executed. | ||
| Statement(sql string) | ||
|
|
||
| // Commit is called when a transaction successfully commits. | ||
| Commit() | ||
|
|
||
| // Rollback is called when a transaction is rolled back. | ||
| Rollback() | ||
| } |
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 not sure this gives us enough information for what we'd want to log.
I want to see separate log events for beginning to commit vs commit done and its result, possibly including the WAL growth. Well, we track that per-Tx WAL growth already in cfgdb, so I guess we have enough to stich that in, but I think we'd at least need here for the Commit method above to take an error parameter for what we returned to the caller, and then update the docs to say it's not just about successful commits. Or Rollback needs an error perhaps, where a nil error means it was an explicit Rollback from user code, as opposed to a failed commit resulting in a rollback?
Other misc thought: maybe Begin should return some comparable TxID that the other 3 methods also receive, for lining stuff up. (but maybe not needed if we in practice serialize all writes... but maybe we're not?)
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 am not against having more debugging data, but I don't think I understand why this API is insufficient for logging all committed write transactions? If a logger resets its state on Begin and only logs accumulated statements upon receiving Commit, do we care about unsuccessful commits or rollbacks at all? For the task at hand, I am not sure we even need the Rollback callback.
Same thoughts about TxID - I don't mind more details, but if a single conn can only have one transaction at a time, the logger itself can assign an id when Begin is called, and attribute all subsequent statements to that ID, right?
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 added an error parameter to Commit.
| // ConnLogger is implemented by the caller to support statement-level logging for | ||
| // write transactions. Only Exec calls are logged, not Query calls, as this is | ||
| // intended as a mechanism to replay failed transactions. | ||
| type ConnLogger interface { |
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 probably want some kind of Close() method to ensure the file is flushed to disk when we exit.
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 don't think we want Close here, although of course you're right that we need to flush the logs to disk on exit. In the corresponding PR, I've added a Close handler which is attached to the database shutdown process. Thanks for spotting it!
sqlite.go
Outdated
| // ConnLogger is implemented by the caller to support statement-level logging for | ||
| // write transactions. Only Exec calls are logged, not Query calls, as this 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.
As implemented, I think this would log read transactions too? I took a stab at skipping the logger for readonly transactions: 112a07d
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.
Thanks! Merged your commit into mine.
sqlite.go
Outdated
| // ConnLogger is implemented by the caller to support statement-level logging for | ||
| // write transactions. Only Exec calls are logged, not Query calls, as this is | ||
| // intended as a mechanism to replay failed transactions. | ||
| type ConnLogger interface { | ||
| // Begin is called when a writable transaction is opened. | ||
| Begin() | ||
|
|
||
| // Statement is called with evaluated SQL when a statement is executed. | ||
| Statement(sql string) | ||
|
|
||
| // Commit is called when a transaction successfully commits. | ||
| Commit() | ||
|
|
||
| // Rollback is called when a transaction is rolled back. | ||
| Rollback() | ||
| } |
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 am not against having more debugging data, but I don't think I understand why this API is insufficient for logging all committed write transactions? If a logger resets its state on Begin and only logs accumulated statements upon receiving Commit, do we care about unsuccessful commits or rollbacks at all? For the task at hand, I am not sure we even need the Rollback callback.
Same thoughts about TxID - I don't mind more details, but if a single conn can only have one transaction at a time, the logger itself can assign an id when Begin is called, and attribute all subsequent statements to that ID, right?
2ebf665 to
b07a594
Compare
sqlite.go
Outdated
| type connector struct { | ||
| name string | ||
| tracer sqliteh.Tracer | ||
| makeLogger func() ConnLogger |
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.
// or nil
| if tx.conn.tracer != nil { | ||
| tx.conn.tracer.Commit(tx.conn.id, err) | ||
| } |
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 Tracer interface is what I was remembering with its type TraceConnID it plumbs through.
It's kinda weird having both Tracer and Logger that are such overlaps. Oh well.
I guess Tracer has the SQL with placeholders and Logger has it without? Might be worth documenting on both the relationship between the two.
b07a594 to
94eb142
Compare
| } | ||
| } | ||
|
|
||
| func ConnectorWithLogger(sqliteURI string, connInitFunc ConnInitFunc, tracer sqliteh.Tracer, makeLogger func() ConnLogger) driver.Connector { |
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.
Document when makeLogger is called (i.e., "when Connect is called")?
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.
ConnLogger can be used to log executed statements for a connection. The interface captures events for Begin, Exec, Commit, and Rollback calls. Updates tailscale/corp#33577 Co-authored-by: Anton Tolchanov <[email protected]>
94eb142 to
731f626
Compare
ConnLogger can be used to log executed statements for a connection. The interface captures events for Begin, Exec, Commit, and Rollback calls.
Updates tailscale/corp#33577