开发者

Creating a hit counter using the cache or application scope

I would like to create a hit counter for my ColdFusion app. I don't want the database hits table to be updated on each page hit. Ideally, I would like to aggregate the hits in the app scope, or the cache in some type of struct, then save them intermittently.

I have to ideas so far:.

Idea 1

  1. Create an app or cache struct to store pageId and pageHits key value pair.
  2. On each page hit, check for the existence of pageId/ip address cookie.
  3. a. If it exists, do nothing.
  4. b. If it does not, set it and update the hits struct in the app or cache.

Problem: I don't know how to get the struct data into the database intermittently/after a certain time has elapsed. Scheduled event?

Idea 2

No cookies; save pageId/ip address in their own cache/app struct.

Problem I'm not sure how to structure the data structs/arrays to store the info. Seems complicated with array loops and struct finds. And I still have the same problem as idea one.

Any advice, ideas, criticism? In particular, I need some help figuring out the data structures for idea 2. I'm more interested in performance than data integrity and happy with CF9 only solution. I should add I'm looking to denormalize data into a page h开发者_JS百科its column for every page id. I don't need normalized data tables.


Trying to capture this data in the ways you've describe introduces scaling problems with cache expiration to avoid OOM or long iteration times as the number of entries grows when you ultimately want to persist to a database. The information you want to aggregate is already captured in web server logs. Parsing these is a straightforward activity, you just need to write an algorithm that's aware of how and when these rollover.

Use log = fileRead('log.txt', 'read') and iterate over line fileReadLine(log) on a periodic basis via <cfschedule/>. For each batch you can in the fashion you've already described and then use whatever database approach for INSERT/UPDATE (usually uses the MERGE keyword, but MySQL is different) based on IP address if that's what you're after. If it's a very high traffic site, consider altering the data type of the IP address column to an integer datatype to speed index lookups.

Update

Use the following code to setup a file object reference:

<cflock name="logparser" type="exclusive" timeout="1" throwontimeout="false">
    <cfif NOT structKeyExists(application, "logFile")>
        <cfset application.logFile =
            fileOpen('/path/to/log.txt', 'read')>
    </cfif>
    <cfloop condition="NOT FileisEOF(application.logFile)">
        <!--- replace with an appropriate algorithm --->
        <cfoutput>
            #fileReadLine(application.logFile)#
            <br />
        </cfoutput>
    </cfloop>
</cflock>

Doing this sets up the reference once (i.e. fileOpen()), which keeps track of what line it's on. Then when <cfschedule/> hits this code again it uses the existing reference if present and iterates forward from there. The lock ensures only one thread executes the algorithm - so you don't need to to worry about a time constraint just let it keep on going as long as it needs to.


Idea 1: yes, <cfschedule> is your friend

Idea 2: save pageId/ip address? I guess this is better to use Set from Java, but struct would work too if you assign it an empty value...

pageIDs["1"]["192.0.0.1"] = "";
hitsOfPage1 = structCount(pageIDs[1]));

However, if I visit the page again tmr, I won't be counted?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜