Note that there are some explanatory texts on larger screens.

plurals
  1. POGrails filter stats insert performance
    primarykey
    data
    text
    <p>I have a filter in grails to capture all controller requests and insert a row into the database with the controllerName, actionName, userId, date, and guid. This works fine, but I would like to find a way to increase the performance. Right now it takes ~100 milliseconds to do all this with 70-80ms of that time creating a statement. I've used both a domain object insert, groovy Sql, and raw java connection/statement. Is there any faster way to improve the performance of inserting a single record within a filter? Alternatively, is there a different pattern that can be used for the inserts? Code (using groovy SQL) Below:</p> <pre><code>class StatsFilters { def grailsApplication def dataSource def filters = { logStats(controller:'*', action:'*') { before = { if(controllerName == null || actionName == null) { return true } def logValue = grailsApplication.config.statsLogging if(logValue.equalsIgnoreCase("on") &amp;&amp; session?.user?.uid != null &amp; session?.user?.uid != "") { try{ def start = System.currentTimeMillis() Sql sql = new Sql(dataSource) def userId = session.user.uid final String uuid = "I" + UUID.randomUUID().toString().replaceAll("-",""); String insert = "insert into STATS(ID, CONTROLLER, ACTION, MODIFIED_DATE, USER_ID) values ('${uuid}','${controllerName}','${actionName}',SYSDATE,'${userId}')" sql.execute(insert) sql.close() def end = System.currentTimeMillis() def total = end - start println("total " + total) } catch(e) { log.error("Stats failed to save with exception " + e.getStackTrace()) return true } } return true } } } </code></pre> <p>}</p> <p>And my current data source</p> <pre><code>dataSource { pooled = true dialect="org.hibernate.dialect.OracleDialect" properties { maxActive = 50 maxIdle = 10 initialSize = 10 minEvictableIdleTimeMillis = 1800000 timeBetweenEvictionRunsMillis = 1800000 maxWait = 10000 validationQuery = "select * from resource_check" testWhileIdle = true numTestsPerEvictionRun = 3 testOnBorrow = true testOnReturn = true } //loggingSql = true </code></pre> <p>}</p> <p>----------------------Solution-------------------------</p> <p>The solution was to simply spawn a thread and do the stats save. This way user response time isn't impacted, but the save is done in near real time. The number of users in this application (corporate internal, limited user group) doesn't merit anything more robust.</p> <pre><code>void saveStatData(def controllerName, def actionName, def userId) { Thread.start{ Sql sql = new Sql(dataSource) final String uuid = "I" + UUID.randomUUID().toString().replaceAll("-",""); String insert = "insert into STATS(ID, CONTROLLER, ACTION, MODIFIED_DATE, USER_ID) values ('${uuid}','${controllerName}','${actionName}',SYSDATE,'${userId}')" sql.execute(insert) sql.close() } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload