アクセスログ解析

JavaScriptで音を鳴らすページを作ったところ、Gigazineでも取り上げていただいて、アクセス数が伸びているみたいだ。毎時のアクセス数をグラフにしてみよう。

Apache httpdであれば /var/log/httpd/ssl_access_log に例えば次のような形でログが記録される。頭の XXX.XXX.XXX.XXX はIPアドレスである。

XXX.XXX.XXX.XXX - - [25/Aug/2024:15:11:42 +0900] "GET /~okumura/javascript/sound.html HTTP/1.1" 200 3238 "https://okumuralab.org/~okumura/javascript/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15"

これを読んで該当の時刻だけ抜き出し、ヒストグラムにすればよい。

import re
import numpy as np
from datetime import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from collections import defaultdict

log_pattern = re.compile(r'\[(.*?) .*?\] "GET /~okumura/javascript/sound.html')

log = []

with open("ssl_access_log", "r") as file:
    for line in file:
        match = log_pattern.search(line)
        if match:
            timestamp = match.group(1)
            log.append(datetime.strptime(timestamp, "%d/%b/%Y:%H:%M:%S"))

b = np.arange(min(log).replace(minute=0, second=0),
              max(log).replace(minute=0, second=0) + np.timedelta64(1, "h"),
              np.timedelta64(1, "h"))

locator = mdates.AutoDateLocator()
formatter = mdates.ConciseDateFormatter(locator)

fig, ax = plt.subplots(figsize=(10, 4.8)) # default 6.4, 4.8
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.hist(log, bins=b)

ある時点までのアクセス数の推移:

JavaScriptで音を鳴らすページのアクセス数の推移

なお、二つある np.timedelta64(1, "h") の一つめは本当は np.timedelta64(2, "h") であるべきだが、最後のビンは1時間に満たないことが多いので、急に減ったと勘違いされないように、最後のビンを表示しないためにこのようにした。