OSDN Git Service

Merge pull request #4 from Bytom/develop
[bytom/bytom.git] / log / splunk / splunk.go
1 // Package splunk sends log data to a splunk server.
2 package splunk
3
4 import (
5         "io"
6         "net"
7         "time"
8 )
9
10 const (
11         // DialTimeout limits how long a write will block
12         // while dialing the splunk server. Assuming the
13         // connection stays open for a long time, this will
14         // happen only rarely.
15         DialTimeout = 50 * time.Millisecond
16
17         // WriteTimeout limits how long a write will block
18         // sending data on the network. It is deliberately
19         // very small, so that writes can only be satisfied
20         // by the local network buffers. It should never
21         // block waiting for a TCP ACK for an appreciable
22         // amount of time.
23         WriteTimeout = 100 * time.Microsecond
24 )
25
26 type splunk struct {
27         addr    string
28         conn    net.Conn
29         dropmsg []byte
30         err     error // last write error
31 }
32
33 // New creates a new writer that sends data
34 // to the given TCP address.
35 // It connects on the first call to Write,
36 // and attempts to reconnect when necessary,
37 // with a timeout of DialTimeout.
38 //
39 // Every write has a timeout of WriteTimeout.
40 // If the write doesn't complete in that time,
41 // the writer drops the unwritten data.
42 // For every contiguous run of dropped data,
43 // it writes dropmsg before resuming ordinary writes.
44 // As long as the remote endpoint can keep up
45 // with the averate data rate and the local
46 // network buffers in the kernel and NIC are
47 // big enough to hold traffic bursts, no data
48 // will be lost.
49 func New(addr string, dropmsg []byte) io.Writer {
50         return &splunk{
51                 addr:    addr,
52                 dropmsg: dropmsg,
53         }
54 }
55
56 func (s *splunk) Write(p []byte) (n int, err error) {
57         if s.conn == nil {
58                 s.conn, err = net.DialTimeout("tcp", s.addr, DialTimeout)
59                 if err != nil {
60                         return 0, err
61                 }
62         }
63
64         if s.err != nil {
65                 s.conn.SetDeadline(time.Now().Add(WriteTimeout))
66                 _, s.err = s.conn.Write(s.dropmsg)
67         }
68         if s.err == nil {
69                 s.conn.SetDeadline(time.Now().Add(WriteTimeout))
70                 n, s.err = s.conn.Write(p)
71         }
72
73         if t, ok := s.err.(net.Error); s.err != nil && (!ok || !t.Temporary()) {
74                 s.conn.Close()
75                 s.conn = nil
76         }
77         return n, s.err
78 }