Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(309)

Side by Side Diff: common/eventlog/internal/logservice/logservice.go

Issue 2557593002: Add batch logging support to eventlog. (Closed)
Patch Set: Fix race in test. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/eventlog/internal/logservice/batch_logger_test.go ('k') | examples/eventlog/main.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The LUCI Authors. All rights reserved. 1 // Copyright 2016 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // Package logservice provides a client which can be used to to collect and send batches of logs to the eventlog service. 5 // Package logservice provides a client which can be used to to collect and send batches of logs to the eventlog service.
6 package logservice 6 package logservice
7 7
8 import ( 8 import (
9 "bytes" 9 "bytes"
10 "context"
11 "fmt"
10 "net/http" 12 "net/http"
11 "time" 13 "time"
12 14
13 "github.com/golang/protobuf/proto" 15 "github.com/golang/protobuf/proto"
14 16
15 logpb "github.com/luci/luci-go/common/eventlog/proto" 17 logpb "github.com/luci/luci-go/common/eventlog/proto"
16 "golang.org/x/net/context"
17 ) 18 )
18 19
19 // Client sends event logs to the eventlog service. 20 // Logger sends event logs to the eventlog service.
20 type Client struct { 21 type Logger struct {
21 HTTPClient *http.Client 22 HTTPClient *http.Client
23
22 serverAddr string 24 serverAddr string
23 logSource string 25 logSource string
24 } 26 }
25 27
26 // NewClient constructs a new Client. 28 // NewLogger constructs a new Client.
27 // Users must call Close when the Client is no longer needed. 29 // Users must call Close when the Client is no longer needed.
28 func NewClient(serverAddr, logSourceName string) *Client { 30 func NewLogger(serverAddr, logSourceName string) *Logger {
29 » return &Client{ 31 » return &Logger{
30 serverAddr: serverAddr, 32 serverAddr: serverAddr,
31 logSource: logSourceName, 33 logSource: logSourceName,
32 } 34 }
33 } 35 }
34 36
35 // TODO(mcgreevy): support bundling log requests. 37 // retryError is an error for an operation that should be retried.
38 type retryError struct {
39 » error
40 }
36 41
37 // LogSync synchronously logs events to the eventlog service. 42 // LogSync synchronously logs events to the eventlog service.
38 // The EventTime in each event must have been obtained from time.Now. 43 // The EventTime in each event must have been obtained from time.Now.
39 func (c *Client) LogSync(ctx context.Context, events []*logpb.LogRequestLite_Log EventLite) error { 44 // The returned error can be supplied to ShouldRetry to determine whether the op eration should be retried.
45 func (l *Logger) LogSync(ctx context.Context, events ...*logpb.LogRequestLite_Lo gEventLite) error {
40 // TODO(mcgreevy): consider supporting custom clocks. 46 // TODO(mcgreevy): consider supporting custom clocks.
41 log := &logpb.LogRequestLite{ 47 log := &logpb.LogRequestLite{
42 RequestTimeMs: proto.Int64(time.Now().UnixNano() / 1e6), 48 RequestTimeMs: proto.Int64(time.Now().UnixNano() / 1e6),
43 » » LogSourceName: &c.logSource, 49 » » LogSourceName: &l.logSource,
44 LogEvent: events, 50 LogEvent: events,
45 } 51 }
46 52
47 buf, err := proto.Marshal(log) 53 buf, err := proto.Marshal(log)
48 if err != nil { 54 if err != nil {
49 return err 55 return err
50 } 56 }
51 57
52 » req, err := http.NewRequest("POST", c.serverAddr, bytes.NewReader(buf)) 58 » req, err := http.NewRequest("POST", l.serverAddr, bytes.NewReader(buf))
53 if err != nil { 59 if err != nil {
54 return err 60 return err
55 } 61 }
56 62
57 req.Header.Set("Content-Type", "application/octet-stream") 63 req.Header.Set("Content-Type", "application/octet-stream")
58 req = req.WithContext(ctx) 64 req = req.WithContext(ctx)
59 » resp, err := c.HTTPClient.Do(req) 65 » resp, err := l.HTTPClient.Do(req)
60 if err != nil { 66 if err != nil {
61 » » return err 67 » » return retryError{err}
62 } 68 }
63 » resp.Body.Close() 69 » defer resp.Body.Close()
64 70
65 » return nil 71 » sc := resp.StatusCode
72 » switch {
73 » case sc == 200:
74 » » return nil
75 » case sc == 400:
76 » » // malformed; this should not happen.
77 » » return fmt.Errorf("eventlog: malformed request: %v", req)
78 » case sc == 401:
79 » » return retryError{fmt.Errorf("eventlog: auth failed: %v", req)}
80 » case sc >= 500 && sc < 600:
81 » » return retryError{fmt.Errorf("eventlog: req failed: %v", req)}
82 » default:
83 » » return fmt.Errorf("eventlog: unexpected status code: %v for requ est: %v", sc, req)
84 » }
66 } 85 }
67 86
68 // Close flushes any pending logs and releases any resources held by the client. 87 // ShouldRetry reports whether a LogSync call (which returned err) should be ret ried.
69 // Close should be called when the client is no longer needed. 88 func ShouldRetry(err error) bool {
70 func (c *Client) Close() error { 89 » _, ok := err.(retryError)
71 » // We will need this later, but for now it's a no-op. 90 » return ok
72 » return nil
73 } 91 }
OLDNEW
« no previous file with comments | « common/eventlog/internal/logservice/batch_logger_test.go ('k') | examples/eventlog/main.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698