challenge アクセスログのIPアドレスを逆引き

アクセスログのIPアドレスを逆引きするフィルタを作成してください.

アクセスログの各行の先頭にIPアドレスがあります.そのIPアドレスを逆引き結果のFQDNで置き換えてください.

逆引きが出来なかった場合は,IPアドレスのまま残します. IPアドレス以外の部分は,そのまま加工せずに残してください.

----

例)192.168.7.1 が逆引きできない場合

210.166.209.71 - - [26/Jul/2007:22:32:47 +0900] "GET / HTTP/1.1" 403 283 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5"
192.168.7.1 - - [26/Jul/2007:22:32:48 +0900] "GET /favicon.ico HTTP/1.1" 404 290 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5"

mikage.to - - [26/Jul/2007:22:32:47 +0900] "GET / HTTP/1.1" 403 283 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5"
192.168.7.1 - - [26/Jul/2007:22:32:48 +0900] "GET /favicon.ico HTTP/1.1" 404 290 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.5) Gecko/20070713 Firefox/2.0.0.5"

----

アクセスログは膨大な量があるため,現実的な時間で処理できるよう,以下の条件をつけます.

・メモリに入りきらないような巨大なログも処理できるようにしてください.(ファイル全体をメモリに読み込むのはNG)

・十分な速度で処理できるよう,並列化する等の工夫をしてください.

・DNSサーバに大量のリクエストが行かないよう,結果をキャッシュしてDNSサーバへのアクセスを削減してください.  なお,DNSのTTLは無視して結果をキャッシュしてかまいません.  (ログの記録された時間の逆引きするタイミングがずれているため,正確な逆引きは元々無理なので)

名前解決はgethostbyaddrを利用しても良いですし,再帰的に名前解決が出来るDNSサーバと直接通信してもかまいません.

ログを順次読み取り処理する部分を,データを共有しつついかに並列化するか,という部分を問うのが目的です.

このお題は沢渡みかげさんの投稿です。ご投稿ありがとうございます。

Posted feedbacks - Scala

ScalaといえばActorです。というわけでActor使ってます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import java.net.{InetAddress, UnknownHostException}
import scala.collection.mutable.{HashMap, Queue}
import scala.io._
import java.io._
import scala.actors._
import scala.actors.Actor._

class Log(in:String, out:String, n:int){
  val outio = new BufferedWriter(new FileWriter(out))
  val inio  = new BufferedReader(new FileReader(in))
  var resolved = new HashMap[int, String]
  var writeQueue  = new Queue[int]
  val readers = (for(i <- 0 to n-1) yield new reader(i)).toArray
  var done = false

  val lookupCahce = new HashMap[String, String]
  def lookup(ip:String) = lookupCahce.getOrElseUpdate(ip, (try {
    InetAddress.getByName(ip).getHostName
  }catch {
    case _ => ip
  }))

  def process() = {
    done = false
    readers.foreach(x => {
      x.link(writer)
      x.trapExit = true
      x.start
      x ! 'resolve
    })
  }

  val writer:Actor = actor {
    loop {
      react {
        case 'write =>
          if(writeQueue.size > 0) {
            if(resolved.contains(writeQueue.front)) {
              val i = writeQueue.dequeue
              val line = resolved(i)
              resolved -= i 
              readers(i) ! 'resolve
              outio.write(line+"\n")
            }
            writer ! 'write
          }
          if(done && writeQueue.size == 1){
            outio.close; 
            exit
          }
      }
    }
  }

  class reader(i:int) extends Actor {
    def act() = loop {
      react {
        case 'resolve => 
          if(!done) {
            writeQueue += i
            val line = inio.readLine
            if(line != null) {
              val (ip::rest) = line.split(" ").toList
              resolved(i) = (lookup(ip)::rest).mkString(" ")
            }else {
              done = true
            }
            writer ! 'write
          }
        case Exit(_, _) => exit
      }
    }
  }
}

new Log("test.log", "testout.log", 20) process

Index

Feed

Other

Link

Pathtraq

loading...