Example #1
1
// FormatTimestamp formats t into Postgres' text format for timestamps.
func FormatTimestamp(t time.Time) []byte {
	// Need to send dates before 0001 A.D. with " BC" suffix, instead of the
	// minus sign preferred by Go.
	// Beware, "0000" in ISO is "1 BC", "-0001" is "2 BC" and so on
	bc := false
	if t.Year() <= 0 {
		// flip year sign, and add 1, e.g: "0" will be "1", and "-10" will be "11"
		t = t.AddDate((-t.Year())*2+1, 0, 0)
		bc = true
	}
	b := []byte(t.Format(time.RFC3339Nano))

	_, offset := t.Zone()
	offset = offset % 60
	if offset != 0 {
		// RFC3339Nano already printed the minus sign
		if offset < 0 {
			offset = -offset
		}

		b = append(b, ':')
		if offset < 10 {
			b = append(b, '0')
		}
		b = strconv.AppendInt(b, int64(offset), 10)
	}

	if bc {
		b = append(b, " BC"...)
	}
	return b
}
Example #2
0
func getTouchCmd(path string, mtime time.Time) string {
	return fmt.Sprintf(
		`call touch -d "%s" "%s"`,
		mtime.Format(mtimeFormat),
		path,
	)
}
Example #3
0
// buildCommonLogLine builds a log entry for req in Apache Common Log Format.
// ts is the timestamp with which the entry should be logged.
// status and size are used to provide the response HTTP status and size.
func buildCommonLogLine(req *http.Request, url url.URL, ts time.Time, status int, size int) []byte {
	username := "******"
	if url.User != nil {
		if name := url.User.Username(); name != "" {
			username = name
		}
	}

	host, _, err := net.SplitHostPort(req.RemoteAddr)

	if err != nil {
		host = req.RemoteAddr
	}

	uri := url.RequestURI()

	buf := make([]byte, 0, 3*(len(host)+len(username)+len(req.Method)+len(uri)+len(req.Proto)+50)/2)
	buf = append(buf, host...)
	buf = append(buf, " - "...)
	buf = append(buf, username...)
	buf = append(buf, " ["...)
	buf = append(buf, ts.Format("02/Jan/2006:15:04:05 -0700")...)
	buf = append(buf, `] "`...)
	buf = append(buf, req.Method...)
	buf = append(buf, " "...)
	buf = appendQuoted(buf, uri)
	buf = append(buf, " "...)
	buf = append(buf, req.Proto...)
	buf = append(buf, `" `...)
	buf = append(buf, strconv.Itoa(status)...)
	buf = append(buf, " "...)
	buf = append(buf, strconv.Itoa(size)...)
	return buf
}
Example #4
0
func (fs *fileStorage) printDay(t time.Time) {
	if fs.day == t.Day() {
		return
	}
	fs.day = t.Day()
	fs.logw.Write([]byte("=============== " + t.Format("Jan 2, 2006 (MST)") + " ===============\n"))
}
Example #5
0
func (k *Keys) sign(s *Service, t time.Time) []byte {
	h := ghmac([]byte("AWS4"+k.SecretKey), []byte(t.Format(iSO8601BasicFormatShort)))
	h = ghmac(h, []byte(s.Region))
	h = ghmac(h, []byte(s.Name))
	h = ghmac(h, []byte("aws4_request"))
	return h
}
Example #6
0
func (t *traceWriter) Trace(traceId []byte) {
	var (
		coordinator string
		duration    int
	)
	t.session.Query(`SELECT coordinator, duration
			FROM system_traces.sessions
			WHERE session_id = ?`, traceId).
		Consistency(One).Scan(&coordinator, &duration)

	iter := t.session.Query(`SELECT event_id, activity, source, source_elapsed
			FROM system_traces.events
			WHERE session_id = ?`, traceId).
		Consistency(One).Iter()
	var (
		timestamp time.Time
		activity  string
		source    string
		elapsed   int
	)
	t.mu.Lock()
	defer t.mu.Unlock()
	fmt.Fprintf(t.w, "Tracing session %016x (coordinator: %s, duration: %v):\n",
		traceId, coordinator, time.Duration(duration)*time.Microsecond)
	for iter.Scan(&timestamp, &activity, &source, &elapsed) {
		fmt.Fprintf(t.w, "%s: %s (source: %s, elapsed: %d)\n",
			timestamp.Format("2006/01/02 15:04:05.999999"), activity, source, elapsed)
	}
	if err := iter.Close(); err != nil {
		fmt.Fprintln(t.w, "Error:", err)
	}
}
Example #7
0
func (p *InMemoryDataStore) retrieveChangeSets(dsocialId string, after time.Time) ([]*dm.ChangeSet, bc.NextToken, error) {
	l := list.New()
	var afterString string
	if !after.IsZero() {
		afterString = after.Format(dm.UTC_DATETIME_FORMAT)
	}
	for _, v := range p.retrieveChangesetCollection().Data {
		if cs, ok := v.(*dm.ChangeSet); ok {
			if cs.RecordId == dsocialId {
				if after.IsZero() || cs.CreatedAt > afterString {
					cs2 := new(dm.ChangeSet)
					*cs2 = *cs
					l.PushBack(cs2)
				}
			}
		}
	}
	rc := make([]*dm.ChangeSet, l.Len())
	for i, iter := 0, l.Front(); iter != nil; i, iter = i+1, iter.Next() {
		if iter.Value != nil {
			rc[i] = iter.Value.(*dm.ChangeSet)
		}
	}
	return rc, nil, nil
}
Example #8
0
// GetStats returns a basic set of statistics for different events.
// Events start at the given start date, if one is provided.
// If not, this function will consider all stated events dating to the creation of the sending domain.
func (m *MailgunImpl) GetStats(limit int, skip int, startDate *time.Time, event ...string) (int, []Stat, error) {
	r := simplehttp.NewHTTPRequest(generateApiUrl(m, statsEndpoint))

	if limit != -1 {
		r.AddParameter("limit", strconv.Itoa(limit))
	}
	if skip != -1 {
		r.AddParameter("skip", strconv.Itoa(skip))
	}

	if startDate != nil {
		r.AddParameter("start-date", startDate.Format(time.RFC3339))
	}

	for _, e := range event {
		r.AddParameter("event", e)
	}
	r.SetBasicAuth(basicAuthUser, m.ApiKey())

	var res statsEnvelope
	err := getResponseFromJSON(r, &res)
	if err != nil {
		return -1, nil, err
	} else {
		return res.TotalCount, res.Items, nil
	}
}
Example #9
0
File: db.go Project: puma007/Tasks
func GetTasks(status string) []types.Task {
	var task []types.Task
	var TaskId int
	var TaskTitle string
	var TaskContent string
	var TaskCreated time.Time
	var getTasksql string
	if status == "pending" {
		getTasksql = "select id, title, content, created_date from task where finish_date is null and is_deleted='N' order by created_date asc"
	} else if status == "trashed" {
		getTasksql = "select id, title, content, created_date from task where is_deleted='Y' order by created_date asc"
	} else if status == "complete" {
		getTasksql = "select id, title, content, created_date from task where finish_date is not null order by created_date asc"
	}

	rows, err := database.Query(getTasksql)
	if err != nil {
		fmt.Println(err)
	}
	defer rows.Close()
	for rows.Next() {
		err := rows.Scan(&TaskId, &TaskTitle, &TaskContent, &TaskCreated)
		if err != nil {
			fmt.Println(err)
		}
		TaskCreated = TaskCreated.Local()
		a := types.Task{Id: TaskId, Title: TaskTitle, Content: TaskContent, Created: TaskCreated.Format(time.UnixDate)[0:20]}
		task = append(task, a)
	}

	return task
}
Example #10
0
func formatTime(t time.Time) string {
	s := time.Since(t)
	switch {
	case s.Seconds() < 60:
		f := "second"
		if math.Floor(s.Seconds()) > 1 {
			f += "s"
		}
		return fmt.Sprintf("%d "+f+" ago", int(s.Seconds()))
	case s.Minutes() < 60:
		f := "minute"
		if math.Floor(s.Minutes()) > 1 {
			f += "s"
		}
		return fmt.Sprintf("%d "+f+" ago", int(s.Minutes()))
	case s.Hours() < 24:
		f := "hour"
		if math.Floor(s.Hours()) > 1 {
			f += "s"
		}
		return fmt.Sprintf("%d "+f+" ago", int(s.Hours()))
	default:
		layout := "Jan 2, 2006 at 3:04pm (MST)"
		return t.Format(layout)
	}
}
Example #11
0
// Export expvars to Cube right now. Use the provided timestamp for the
// submitted event. This function sends variables once and returns.
//
// You shouldn't need this function under normal circumstances. Use Run()
// instead.
func ExportVariablesWithTimestamp(collectionType string, putUrl string, timestamp time.Time) error {
	variables := make([]string, 0)
	expvar.Do(func(entry expvar.KeyValue) {
		variables = append(variables, fmt.Sprintf("%q: %s", entry.Key, entry.Value))
	})
	request := fmt.Sprintf(
		`[
		{
			"type": "%s",
			"time": "%s",
			"data": { %s }
		}
		]`,
		collectionType,
		timestamp.Format(time.ANSIC),
		strings.Join(variables, ","))

	response, err := http.Post(putUrl, "application/json", bytes.NewBufferString(request))
	if err != nil {
		log.Printf("Error POSTing events to Cube collector: %v", err)
		log.Printf("The request we tried to post: %v", request)
		return err
	}
	defer response.Body.Close()
	return nil
}
Example #12
0
// rotateFile closes the syncBuffer's file and starts a new one.
func (sb *syncBuffer) rotateFile(now time.Time) error {
	if sb.file != nil {
		if err := sb.Flush(); err != nil {
			return err
		}
		if err := sb.file.Close(); err != nil {
			return err
		}
	}
	var err error
	sb.file, _, err = create(sb.sev, now)
	sb.nbytes = 0
	if err != nil {
		return err
	}

	sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)

	// Write header.
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
	fmt.Fprintf(&buf, "Running on machine: %s\n", host)
	fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
	fmt.Fprintf(&buf, "Log line format: [IWEF]yymmdd hh:mm:ss.uuuuuu file:line msg\n")
	var n int
	n, err = sb.file.Write(buf.Bytes())
	sb.nbytes += uint64(n)
	return err
}
Example #13
0
// buildLogLine creates a common log format
// in addition to the common fields, we also append referrer, user agent,
// request ID and response time (microseconds)
//  ie, in apache mod_log_config terms:
//     %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" %L %D
func buildLogLine(l *responseLogger, r *http.Request, start time.Time) string {

	redactPassword(r)

	username := parseUsername(r)

	host, _, err := net.SplitHostPort(r.RemoteAddr)

	if err != nil {
		host = r.RemoteAddr
	}

	uri := r.URL.RequestURI()

	referer := r.Referer()

	userAgent := r.UserAgent()

	return fmt.Sprintf(`%s - %s [%s] "%s %s %s" %s %s "%s" "%s" %s %d`,
		host,
		detect(username, "-"),
		start.Format("02/Jan/2006:15:04:05 -0700"),
		r.Method,
		uri,
		r.Proto,
		detect(strconv.Itoa(l.Status()), "-"),
		strconv.Itoa(l.Size()),
		detect(referer, "-"),
		detect(userAgent, "-"),
		r.Header.Get("Request-Id"),
		// response time, report in microseconds because this is consistent
		// with apache's %D parameter in mod_log_config
		int64(time.Since(start)/time.Microsecond))
}
Example #14
0
// adds the time <t> plus the string <url> to the url-file
func (q *AltPlugin) addToFile(url string, t time.Time) {
	line := fmt.Sprintf("%v %v", t.Format(q.ic.GetStringOption("Altbot", "timeformat")), url)
	err := q.writeLine(q.ic.GetStringOption("Altbot", "file"), line)
	if err != nil {
		log.Println(err)
	}
}
Example #15
0
File: file.go Project: kdada/tinygo
// createLogFile 创建日志文件
func (this *FileWriter) createLogFile(date time.Time) error {
	var day = date.Day()
	if day == this.day {
		//文件无需更新
		return nil
	}
	//关闭原来的日志文件,并创建新的日志文件
	if this.file != nil {
		err := this.file.Close()
		if err != nil {
			return err
		}
	}
	//创建新的日志文件
	var dir = date.Format("200601")
	var path = filepath.Join(this.path, dir)
	var err = os.MkdirAll(path, 0770)
	if err != nil {
		return err
	}
	var fileName = date.Format("20060102") + ".log"
	var filePath = filepath.Join(path, fileName)
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0660)
	if err != nil && !os.IsExist(err) {
		return err
	}
	this.file = file
	this.writer = bufio.NewWriter(file)
	return nil
}
Example #16
0
// Update the already existing object
//
// Copy the reader into the object updating modTime and size
//
// The new object may have been created if an error is returned
func (o *FsObjectDrive) Update(in io.Reader, modTime time.Time, size int64) error {
	updateInfo := &drive.File{
		Id:           o.id,
		ModifiedDate: modTime.Format(timeFormatOut),
	}

	// Make the API request to upload metadata and file data.
	var err error
	var info *drive.File
	if size == 0 || size < int64(driveUploadCutoff) {
		// Don't retry, return a retry error instead
		err = o.drive.pacer.CallNoRetry(func() (bool, error) {
			info, err = o.drive.svc.Files.Update(updateInfo.Id, updateInfo).SetModifiedDate(true).Media(in).Do()
			return shouldRetry(err)
		})
		if err != nil {
			return err
		}
	} else {
		// Upload the file in chunks
		info, err = o.drive.Upload(in, size, fs.MimeType(o), updateInfo, o.remote)
		if err != nil {
			return err
		}
	}
	o.setMetaData(info)
	return nil
}
Example #17
0
func strftime(t time.Time, cfmt string) string {
	sc := newFlagScanner('%', "", "", cfmt)
	for c, eos := sc.Next(); !eos; c, eos = sc.Next() {
		if !sc.ChangeFlag {
			if sc.HasFlag {
				if v, ok := cDateFlagToGo[c]; ok {
					sc.AppendString(t.Format(v))
				} else {
					switch c {
					case 'w':
						sc.AppendString(fmt.Sprint(int(t.Weekday())))
					default:
						sc.AppendChar('%')
						sc.AppendChar(c)
					}
				}
				sc.HasFlag = false
			} else {
				sc.AppendChar(c)
			}
		}
	}

	return sc.String()
}
Example #18
0
func (c Profile) getHistory(account *models.Account, startDate time.Time) []*models.History {
	if account == nil {
		return nil
	}

	duration, _ := time.ParseDuration(fmt.Sprintf("%dh", 1*24))
	oneDayAhead := time.Now().Add(duration)
	results, err := c.Transaction.Select(
		models.History{},
		`select * from History where AccountId = ? and (Date between ? and ?) order by Date desc`,
		account.Id,
		startDate.Format(formatSmallDate),
		oneDayAhead.Format(formatSmallDate))

	if err != nil {
		return nil
	}

	rows := len(results)
	if rows == 0 {
		return nil
	}

	history := make([]*models.History, 0)
	for i := 0; i < rows; i++ {
		history = append(history, results[i].(*models.History))
	}

	return history
}
Example #19
0
// Sign signs an HTTP request with the given AWS keys for use on service s.
func (s *Service) Sign(keys *Keys, r *http.Request) error {
	var t time.Time

	date := r.Header.Get("Date")
	if date == "" {
		return ErrNoDate
	}

	t, err := time.Parse(http.TimeFormat, date)
	if err != nil {
		return err
	}

	r.Header.Set("Date", t.Format(iSO8601BasicFormat))

	k := keys.sign(s, t)
	h := hmac.New(sha256.New, k)
	s.writeStringToSign(h, t, r)

	auth := bytes.NewBufferString("AWS4-HMAC-SHA256 ")
	auth.Write([]byte("Credential=" + keys.AccessKey + "/" + s.creds(t)))
	auth.Write([]byte{',', ' '})
	auth.Write([]byte("SignedHeaders="))
	s.writeHeaderList(auth, r)
	auth.Write([]byte{',', ' '})
	auth.Write([]byte("Signature=" + fmt.Sprintf("%x", h.Sum(nil))))

	r.Header.Set("Authorization", auth.String())

	return nil
}
Example #20
0
func webTime(t *time.Time) string {
	gmt := t.Format(time.RFC1123)
	if strings.HasSuffix(gmt, "UTC") {
		gmt = gmt[0:len(gmt)-3] + "GMT"
	}
	return gmt
}
Example #21
0
/*
derivedKey method derives a signing key to be used for signing a request.

	kSecret = Your AWS Secret Access Key
    kDate = HMAC("AWS4" + kSecret, Date)
    kRegion = HMAC(kDate, Region)
    kService = HMAC(kRegion, Service)
    kSigning = HMAC(kService, "aws4_request")
*/
func (s *V4Signer) derivedKey(t time.Time) []byte {
	h := s.hmac([]byte("AWS4"+s.auth.SecretKey), []byte(t.Format(ISO8601BasicFormatShort)))
	h = s.hmac(h, []byte(s.region.Name))
	h = s.hmac(h, []byte(s.serviceName))
	h = s.hmac(h, []byte("aws4_request"))
	return h
}
Example #22
0
func getSummary(db *sql.DB) (summary, error) {
	s := newSummary()

	rows, err := db.Query(`SELECT Day, Version, Count FROM VersionSummary WHERE Day > now() - '1 year'::INTERVAL;`)
	if err != nil {
		return summary{}, err
	}
	defer rows.Close()

	for rows.Next() {
		var day time.Time
		var ver string
		var num int
		err := rows.Scan(&day, &ver, &num)
		if err != nil {
			return summary{}, err
		}

		if ver == "v0.0" {
			// ?
			continue
		}

		// SUPER UGLY HACK to avoid having to do sorting properly
		if len(ver) == 4 { // v0.x
			ver = ver[:3] + "0" + ver[3:] // now v0.0x
		}

		s.setCount(day.Format("2006-01-02"), ver, num)
	}

	return s, nil
}
Example #23
0
// PostFormArgs returns the action and input fields needed to allow anonymous
// uploads to a bucket within the expiration limit
func (b *Bucket) PostFormArgs(path string, expires time.Time, redirect string) (action string, fields map[string]string) {
	conditions := make([]string, 0)
	fields = map[string]string{
		"AWSAccessKeyId": b.Auth.AccessKey,
		"key":            path,
	}

	conditions = append(conditions, fmt.Sprintf("{\"key\": \"%s\"}", path))
	conditions = append(conditions, fmt.Sprintf("{\"bucket\": \"%s\"}", b.Name))
	if redirect != "" {
		conditions = append(conditions, fmt.Sprintf("{\"success_action_redirect\": \"%s\"}", redirect))
		fields["success_action_redirect"] = redirect
	}

	vExpiration := expires.Format("2006-01-02T15:04:05Z")
	vConditions := strings.Join(conditions, ",")
	policy := fmt.Sprintf("{\"expiration\": \"%s\", \"conditions\": [%s]}", vExpiration, vConditions)
	policy64 := base64.StdEncoding.EncodeToString([]byte(policy))
	fields["policy"] = policy64

	signer := hmac.New(sha1.New, []byte(b.Auth.SecretKey))
	signer.Write([]byte(policy64))
	fields["signature"] = base64.StdEncoding.EncodeToString(signer.Sum(nil))

	action = fmt.Sprintf("%s/%s/", b.S3.Region.S3Endpoint, b.Name)
	return
}
Example #24
0
func getMovement(db *sql.DB) ([][]interface{}, error) {
	rows, err := db.Query(`SELECT Day, Added, Removed, Bounced FROM UserMovement WHERE Day > now() - '1 year'::INTERVAL ORDER BY Day`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	res := [][]interface{}{
		{"Day", "Joined", "Left", "Bounced"},
	}

	for rows.Next() {
		var day time.Time
		var added, removed, bounced int
		err := rows.Scan(&day, &added, &removed, &bounced)
		if err != nil {
			return nil, err
		}

		row := []interface{}{day.Format("2006-01-02"), added, -removed, bounced}
		if removed == 0 {
			row[2] = nil
		}
		if bounced == 0 {
			row[3] = nil
		}

		res = append(res, row)
	}

	return res, nil
}
Example #25
0
// buildLogLine creates a common log format
// in addittion to the common fields, we also append referrer, user agent and request ID
func buildLogLine(l *responseLogger, r *http.Request, start time.Time) string {
	username := parseUsername(r)

	host, _, err := net.SplitHostPort(r.RemoteAddr)

	if err != nil {
		host = r.RemoteAddr
	}

	uri := r.URL.RequestURI()

	referer := r.Referer()

	userAgent := r.UserAgent()

	fields := []string{
		host,
		"-",
		detect(username, "-"),
		fmt.Sprintf("[%s]", start.Format("02/Jan/2006:15:04:05 -0700")),
		r.Method,
		uri,
		r.Proto,
		detect(strconv.Itoa(l.Status()), "-"),
		strconv.Itoa(l.Size()),
		detect(referer, "-"),
		detect(userAgent, "-"),
		r.Header.Get("Request-Id"),
	}

	return strings.Join(fields, " ")
}
Example #26
0
func FirstComic(db *sql.DB) (c *Comic, err error) {
	rows, err := db.Query(
		`select id, title, image_url, description, date from comic
		order by id limit 1`,
	)
	if checkError(err) {
		return nil, err
	}

	for rows.Next() {
		var id int64
		var title string
		var imageURL string
		var description string
		var date time.Time
		err = rows.Scan(&id, &title, &imageURL, &description, &date)
		if checkError(err) {
			return nil, err
		}
		c = &Comic{
			ID:          id,
			Title:       title,
			ImageURL:    imageURL,
			Description: description,
			Date:        date.Format("2006-01-02"),
			db:          db,
		}
		return
	}
	return
}
Example #27
0
func webTime(t time.Time) string {
	ftime := t.Format(time.RFC1123)
	if strings.HasSuffix(ftime, "UTC") {
		ftime = ftime[0:len(ftime)-3] + "GMT"
	}
	return ftime
}
Example #28
0
func (bs *BoltStore) WalkPendingMsgId(st *time.Time, ed *time.Time,
	walkFunc func(ts *time.Time, id MessageID) error) error {
	err := bs.db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket(bucket_pending_ids)
		c := b.Cursor()

		b_st := []byte(st.Format(time.RFC3339))
		b_ed := []byte(ed.Format(time.RFC3339))

		for k, v := c.Seek(b_st); k != nil && bytes.Compare(k, b_ed) <= 0; k, v = c.Next() {

			ts, err := time.Parse(time.RFC3339, string(k))

			var id MessageID
			copy(id[:], v)
			err = walkFunc(&ts, id)
			if err != nil {
				return err
			}
		}

		return nil
	})
	return err
}
Example #29
0
// Sets the modification time of the drive fs object
func (o *FsObjectDrive) SetModTime(modTime time.Time) {
	err := o.readMetaData()
	if err != nil {
		fs.Stats.Error()
		fs.ErrorLog(o, "Failed to read metadata: %s", err)
		return
	}
	// New metadata
	updateInfo := &drive.File{
		ModifiedDate: modTime.Format(timeFormatOut),
	}
	// Set modified date
	var info *drive.File
	err = o.drive.pacer.Call(func() (bool, error) {
		info, err = o.drive.svc.Files.Update(o.id, updateInfo).SetModifiedDate(true).Do()
		return shouldRetry(err)
	})
	if err != nil {
		fs.Stats.Error()
		fs.ErrorLog(o, "Failed to update remote mtime: %s", err)
		return
	}
	// Update info from read data
	o.setMetaData(info)
}
Example #30
0
// Write an CLF formatted access log to 'logger'
func AccessLog(logger *log.Logger) Pipe {
	return func(conn *Conn, req *http.Request) bool {
		var remoteHost = req.RemoteAddr // FIXME
		var ident string = "-"
		var authuser string = "-"
		var now *time.Time = time.UTC()
		var timestamp string = now.Format("[07/Jan/2006:15:04:05 -0700]")
		var request string = fmt.Sprintf("%s %s %s", req.Method, req.RawURL, req.Proto)
		var status int = conn.status
		var size int64 = conn.written
		var referer string = "-"
		var userAgent string = "-"

		if len(req.Referer()) > 0 {
			referer = req.Referer()
		}

		if len(req.UserAgent()) > 0 {
			userAgent = req.UserAgent()
		}

		// Spawn a new goroutine to perform the actual print to the logfile
		// instead of making the pipeline wait.

		go func() {
			logger.Printf("%s %s %s %s \"%s\" %d %d \"%s\" \"%s\"\n",
				remoteHost, ident, authuser, timestamp, request, status, size,
				referer, userAgent)
		}()
		return true
	}
}