谁在那儿? - 跟踪网站访问

Who's There? - Tracking Site Visits

我正在用 sinatra 和 heroku 编写一个网站,我想找到一种方法来跟踪对我网站的每次访问。我看过实际的分析程序(例如 google analytics)并选择不使用它们,因为我想自己学习如何做。

我对访问的定义:

A visit happens when someone or something (robot) visits your site. It consists of one or more page views/ hits. One visitor can make multiple visits to your site.

来源:http://www.opentracker.net/article/hits-or-pageviews

对于每次访问,我想跟踪:

  1. 访客IP地址
  2. 访问开始时间(页面打开)
  3. 访问结束时间(页面关闭)

这个网站不常被浏览,所以我想将每次访问记录在使用 activerecord 访问的 postgres 数据库中。 日志记录的工作方式是这样的:

  1. 用户访问页面
  2. 会话已启动,ipmac_addresstimeview_id 已登录 Visit
  3. 浏览的每个页面都已登录PageView
  4. 用户关闭页面
  5. 会话已清除,timeview_id 已登录 Visit

数据库格式

示例迁移文件:

class Main < ActiveRecord::Migration
  def change
    create_table :visits do |item|
        item.string :ip
        item.string :mac_address
        item.datetime :time
        item.int :visit_id
    end
    create_table :pageviews do |item|
        item.int :visit_id
        item.string :page
        item.datetime :time
  end
end

For each visit, I would like to track:

  1. Visitor IP address
  2. Time visit began (page was opened)
  3. Time visit ended (page was closed)

您之前在列表中也有 MAC 个地址,但重申一下 - 它们不用于路由 Internet,仅用于本地网络,因此保存该信息几乎毫无意义,即使你可以得到它。

HTTP 是一种无状态协议,这意味着 #3 无法通过 HTTP 方法实现,但可以通过 javascript 实现。可能最简单的方法是以可接受的间隔进行轮询,更新时间。

#1 和#2 已经被您的基本服务器日志捕获,我会使用它们 - 为什么要重复工作? - 但我将添加如何使用 Sinatra 通过模型来完成它。

如果您使用 before 过滤器,您可以轻松捕获 #1 和 #2。 Request object 有一些你想要的东西,你需要时间,并确保它是该 ip 的唯一用户:

before do
  # this is pseudo code, Sequel style, you can work this bit out
  # for ActiveRecord
  user =
    if user_id = session[:user]
      User[user_id]
    else
      User.create
    end

  # you may want to check if there's an existing session for this page
  # as refreshes would run this again. It's up to you.
  user.add_visit Visit.create(page: request.path,ip: request.ip, start: Time.now.rfc2822])
  session[:analytics] = visit.id
  session[:user] = user.session_id # *don't* just bung the
                                   # user id in there
end

您需要一条路线将结束时间记录到

patch "/analytics", :provides => :json do
  visit_id = session[:analytics]
  user = User[ :session_id => session[:user] ]
  visit = user.visits.find(:id => visit_id)
  visit.end = Rack::Utils.rfc2822(params[:end])
  visit.save
  halt 204 # take your pick of success numbers
           # you should also check for errors
           # and check the input is valid
           # and you may want to return some JSON to the
           # calling javascript.
  # Also think about how to restrict access to this
  # route to only authorised callers. Since you're providing the
  # javascript, you can place variables in them by generating
  # parts on the fly and serving it via a Sinatra route etc.
end

我不打算写javascript,那应该很简单。

请注意,我基本上是从我的背后提取这段代码的,所以请考虑其中的任何一个或所有部分可能会崩溃和不稳定,但这就是让您明白这个想法。就像我上面提到的,我可能会削减大部分内容并使用日志和一些明智的正则表达式。