Reputation: 2060
I'd like to initiate some logging of requests and, more importantly, queries within my application. Lucee makes this pretty easy, and I'm able to log all queries within any given page run with a few lines of code within the onRequestEnd function:
<cfset getQueries = getPageContext().variablesScope()>
<cfset queryArr = ArrayNew(2)>
<cfset x = 0>
<cfloop collection="#getQueries#" item="key">
<cfif IsQuery(getQueries[key])>
<cftry>
<cfset thisQ = getQueries[key]>
<cfset thisQT = thisQ.getExecutionTime() / 1000000>
<cfset thisSQL = thisQ.getSQL().getSQLString()>
<cfset x = x + 1>
<cfset queryArr[x][1] = thisQT>
<cfset queryArr[x][2] = thisSQL>
<cfcatch>
</cfcatch>
</cftry>
</cfif>
</cfloop>
This gives me an array with each query's SQL (with bind variables represented with ?) and the execution time. I can insert this into a logging database and have all kinds of fun with it.
The problem is that I have many pages that call CFCs, which run queries and then return data:
<cfset someVar = createObject("component","cfc.test").getSomeData(ID=7)>
After I wrote my logging code I realized that the queries within CFCs (the bulk of my data processing) were not being recorded as, of course, they run in their own scope. I'm looking for an easy way to record queries within CFCs as well.
I had never heard of onCFCRequest before a few minutes ago (when Google enlightened me), and I cannot find much information on its use. I was hoping it may work like onRequest, and I could do something like this:
<cffunction name="onCFCRequest">
<cfargument type="String" name="cfcName" required=true/>
<cfargument type="String" name="methodName" required=true/>
<cfargument type="struct" name="args" required=true/>
<cfset caller.getLog = getLog>
</cffunction>
However, that does not work, nor do any of the other variations I tried. In fact, this function doesn't appear to work at all, as this code did not insert anything into my test table:
<cffunction name="onCFCRequest">
<cfargument type="String" name="cfcName" required=true/>
<cfargument type="String" name="methodName" required=true/>
<cfargument type="struct" name="args" required=true/>
<cfquery>
insert into testTable (f1, f2)
values (<cfqueryparam cfsqltype="cf_sql_varchar" value="test1">,
<cfqueryparam cfsqltype="cf_sql_varchar" value="test2">)
</cfquery>
</cffunction>
What is the proper way to use onCFCRequest, and can it be used to write data from a cfc's local scope to the parent/caller request scope? If not, is there another function (like an onCFCRequestEnd) that can be used to do so? I do not want to have to make largescale changes to every cfQuery or cfc file in my application to accomplish this goal.
I am aware there are some commercial applications designed to do this far better that I can with just a few hours of coding. However, this is for a personal site that I can't afford to spend money on, and the experience of doing it myself is enlightening.
Upvotes: 6
Views: 214
Reputation: 20125
As your actual question is how to log all query executions no matter where they happened, I think there are two approaches to do that.
Whenever a query is executed, you can write the SQL string and the parameters into a log.
You can set up the logging to a database table of your wish within the Lucee Admin.
Once that's set up, you need to call <cflog>
and use the name of the specified log within the file
attribute.
Downside to this approach is that you have to manually place a <cflog>
whenever you execute a query. This might be mitigated by centralizing all database communication in a function which also does the logging. So you whenever you want to query something, you'd call that function instead of calling <cfquery>
manually.
Lucee's debugging functionality allows you to output all queries executed within a page run besides other useful information.
You first need to add a debugging template:
Important note: The predefined templates only output the data to the generated HTML of your website. Though you have the possibility to create your own debugging template. In order to do that you need to create your own template CFC within lucee-server/context/context/admin/debug/
and provide it with a unique name. There's also a slide show of how to create your own debugging template of the head behind Lucee, Gert Franz, which explains in more detail how to do that.
When done correctly, you should see the name of your template listed in the template types drop-down list.
Then, all you need to do is to enable debugging of database activity:
Upvotes: 0