The GitHub Actions job "CodeQL" on grails-core.git/feat/sql-tail-command has 
succeeded.
Run started by GitHub user jdaugherty (triggered by jdaugherty).

Head commit for run:
0b4b5862b0b1a82fd47e49665d55303b21631d76 / James Daugherty 
<[email protected]>
Add the query-tail command to find query-heavy pages

A page that is slow because it runs hundreds of queries is easy to miss
in a log: logSql prints every statement, but not which page ran it or
how many a request added up to. query-tail shows the pages of a running
application ranked by the statements they run per request, and for each
page the statement that repeats most within one request, which is what
an N+1 looks like. It covers every store GORM runs statements on: SQL
through Hibernate 5 and 7, Cypher through Neo4j and commands through
MongoDB.

Capture is on only when grails.gorm.queryTail.enabled is set at startup
(grails run-app --query-tail, ./gradlew bootRun
-Pgrails.gorm.queryTail.enabled, or configuration); an application
started without it carries nothing that records. The Hibernate
connection source factories install a statement inspector, the Neo4j
factory wraps the driver, and the MongoDB factory registers a command
listener, each recording on the thread that runs the statement, so a
QueryTailRequestAttribution can attribute it to the controller and
action Grails resolved for the request. The writer, record format,
settings and redaction live in grails-datamapping-core, in
org.apache.grails.datamapping.core.querytail; the command is a script command
in the grails-datamapping-core-cli companion, so the shell runs it
without booting the application. The Grails Gradle plugin hands the
-Pgrails.gorm.queryTail.* properties to forked application and test
JVMs.

Statements are captured without their values. Every literal is recorded
as ? and every comment is dropped by a redactor that scans the statement
under the lexical rules of its database, each a QueryTailSyntax verified
against the database itself: H2, PostgreSQL, CockroachDB, Oracle, Db2,
HSQLDB, Informix, MySQL and MariaDB, SQL Server and Sybase, GoogleSQL,
SAP HANA from its documentation, and Cypher against Neo4j 5 and 3.5. A
rule that depends on a server setting the capture cannot see is read
every way the setting allows, and a statement is recorded only when
every reading finds the same values; one that fails that, or whose
literal or comment never ends, is withheld, as is one that gives a
password, which Oracle and SAP HANA take as a name rather than a
literal, and one that runs a SQL Server or Sybase procedure, which takes
a bare word as a string. A MongoDB command is a document, so its values are 
replaced
field by field, and a key below the top of a document is kept only where
the mapping knows it as a field, so that the keys of a map property
never reach the capture. The request a statement is attributed to is
recorded as its method and path with the values in the path replaced,
those of its mapped parameters and any number, UUID or hexadecimal token
among them.

The capture file is written a line at a time, and a lock file beside it
tells the JVMs that run at the same time with the flag, such as the
parallel forks of a test task, which of them starts the run and which
join it, with their requests numbered apart.

The guide gains a section under The DataSource, the command reference a
query-tail page and the --query-tail flag on run-app, and the
configuration metadata the two settings.

Report URL: https://github.com/apache/grails-core/actions/runs/40543816156

With regards,
GitHub Actions via GitBox

Reply via email to