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

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

Issue 2557593002: Add batch logging support to eventlog. (Closed)
Patch Set: 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
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 eventlog provides a client which can be used to to collect and send b atches of ChromeInfraEvent logs to the eventlog service. 5 // Package eventlog provides a client which can be used to to collect and send b atches of ChromeInfraEvent logs to the eventlog service.
6 package eventlog 6 package eventlog
7 7
8 import ( 8 import (
9 "net/http" 9 "net/http"
10 "time" 10 "time"
11 11
12 "golang.org/x/net/context" 12 "golang.org/x/net/context"
13 13
14 "github.com/golang/protobuf/proto" 14 "github.com/golang/protobuf/proto"
15 "github.com/luci/luci-go/common/eventlog/internal/logservice" 15 "github.com/luci/luci-go/common/eventlog/internal/logservice"
16 logpb "github.com/luci/luci-go/common/eventlog/proto" 16 logpb "github.com/luci/luci-go/common/eventlog/proto"
17 ) 17 )
18 18
19 // TestEndpoint is the server address for test logs. 19 // TestEndpoint is the server address for test logs.
20 const TestEndpoint = "https://jmt17.google.com/log" 20 const TestEndpoint = "https://jmt17.google.com/log"
21 21
22 // ProdEndpoint is the server address for production logs. 22 // ProdEndpoint is the server address for production logs.
23 const ProdEndpoint = "https://play.googleapis.com/log" 23 const ProdEndpoint = "https://play.googleapis.com/log"
24 24
25 // Client may be used to send ChromeInfraEvent logs to the eventlog service. 25 // Client may be used to send ChromeInfraEvent logs to the eventlog service.
26 type Client struct { 26 type Client struct {
27 » c *logservice.Client 27 » sl *logservice.Logger // synchronous logger.
28 » bl *logservice.BatchLogger
29 » ticker *time.Ticker
28 30
29 // EventSource identifies the log producer. It may be configured before sending logs. 31 // EventSource identifies the log producer. It may be configured before sending logs.
30 EventSource *logpb.InfraEventSource 32 EventSource *logpb.InfraEventSource
31 } 33 }
32 34
33 // NewClient constructs a Client which can be used to send ChromeInfraEvent logs to the eventlog service. 35 // NewClient constructs a Client which can be used to send ChromeInfraEvent logs to the eventlog service.
34 // Users must call Close when the Client is no longer needed. 36 // Users must call Close when the Client is no longer needed.
35 func NewClient(serverAddr string, opts ...ClientOption) *Client { 37 // ctx is the context to use for batch log uploads.
38 func NewClient(ctx context.Context, serverAddr string, opts ...ClientOption) *Cl ient {
36 // TODO(mcgreevy): help users to set EventSource? 39 // TODO(mcgreevy): help users to set EventSource?
37 40
38 settings := &clientSettings{ 41 settings := &clientSettings{
39 HTTPClient: http.DefaultClient, 42 HTTPClient: http.DefaultClient,
40 } 43 }
41 for _, o := range opts { 44 for _, o := range opts {
42 o.apply(settings) 45 o.apply(settings)
43 } 46 }
44 47
45 » serviceClient := logservice.NewClient(serverAddr, "CHROME_INFRA") 48 » syncLogger := logservice.NewLogger(serverAddr, "CHROME_INFRA")
46 » serviceClient.HTTPClient = settings.HTTPClient 49 » syncLogger.HTTPClient = settings.HTTPClient
47 » return &Client{c: serviceClient} 50 » ticker := time.NewTicker(time.Minute)
51 » return &Client{
52 » » sl: syncLogger,
53 » » bl: logservice.NewBatchLogger(ctx, syncLogger, ticker.C),
54 » » ticker: ticker,
55 » }
48 } 56 }
49 57
50 // LogSync synchronously logs events to the eventlog service. 58 // LogSync synchronously logs events to the eventlog service.
51 // Use NewLogEvent to assist with constructing a well-formed log event. 59 // Use NewLogEvent to assist with constructing a well-formed log event.
52 // LogSync takes ownership of events. 60 // LogSync takes ownership of events.
53 func (c *Client) LogSync(ctx context.Context, events ...*ChromeInfraLogEvent) er ror { 61 func (c *Client) LogSync(ctx context.Context, events ...*ChromeInfraLogEvent) er ror {
62 logEvents, err := c.prepareLogs(events)
63 if err != nil {
64 return err
65 }
66 return c.sl.LogSync(ctx, logEvents...)
67 }
68
69 // Log stages events to be logged to the eventlog service.
70 // Use NewLogEvent to assist with constructing a well-formed log event.
71 // Log returns immediately, and batches of events will be sent to the eventlog s erver periodically.
72 // Log takes ownership of events.
73 func (c *Client) Log(events ...*ChromeInfraLogEvent) error {
74 logEvents, err := c.prepareLogs(events)
75 if err != nil {
djd-OOO-Apr2017 2016/12/06 06:31:27 It would be nice if we could guarantee that (err =
mcgreevy 2016/12/06 23:57:36 There's nothing stopping the user making aribtrary
76 return err
77 }
78 c.bl.Log(logEvents...)
79 return nil
80 }
81
82 func (c *Client) prepareLogs(events []*ChromeInfraLogEvent) ([]*logpb.LogRequest Lite_LogEventLite, error) {
54 var logEvents []*logpb.LogRequestLite_LogEventLite 83 var logEvents []*logpb.LogRequestLite_LogEventLite
55 84
56 for _, event := range events { 85 for _, event := range events {
57 sourceExt, err := proto.Marshal(event.InfraEvent) 86 sourceExt, err := proto.Marshal(event.InfraEvent)
58 if err != nil { 87 if err != nil {
59 » » » return err 88 » » » return nil, err
60 } 89 }
61 event.LogEvent.SourceExtension = sourceExt 90 event.LogEvent.SourceExtension = sourceExt
62 logEvents = append(logEvents, event.LogEvent) 91 logEvents = append(logEvents, event.LogEvent)
63 } 92 }
64 93 » return logEvents, nil
65 » return c.c.LogSync(ctx, logEvents)
66 } 94 }
67 95
68 // NewLogEvent constructs a well-formed log event. 96 // NewLogEvent constructs a well-formed log event.
69 // eventTime is the time that the event occurred, typically obtained by calling 97 // eventTime is the time that the event occurred, typically obtained by calling
70 // one of Point, Begin or End. 98 // one of Point, Begin or End.
71 func (c *Client) NewLogEvent(ctx context.Context, eventTime TypedTime) *ChromeIn fraLogEvent { 99 func (c *Client) NewLogEvent(ctx context.Context, eventTime TypedTime) *ChromeIn fraLogEvent {
72 // TODO(mcgreevy): look into whether we can populate TraceID, SpanId, Pa rentId from the context. 100 // TODO(mcgreevy): look into whether we can populate TraceID, SpanId, Pa rentId from the context.
73 // TODO(mcgreevy): support event_code, event_flow_id. 101 // TODO(mcgreevy): support event_code, event_flow_id.
74 return &ChromeInfraLogEvent{ 102 return &ChromeInfraLogEvent{
75 LogEvent: &logpb.LogRequestLite_LogEventLite{ 103 LogEvent: &logpb.LogRequestLite_LogEventLite{
76 EventTimeMs: proto.Int64(eventTime.Time.UnixNano() / 1e6 ), 104 EventTimeMs: proto.Int64(eventTime.Time.UnixNano() / 1e6 ),
77 }, 105 },
78 InfraEvent: &logpb.ChromeInfraEvent{ 106 InfraEvent: &logpb.ChromeInfraEvent{
79 TimestampKind: &eventTime.Kind, 107 TimestampKind: &eventTime.Kind,
80 EventSource: c.EventSource, 108 EventSource: c.EventSource,
81 }, 109 },
82 } 110 }
83 } 111 }
84 112
85 // Close flushes any pending logs and releases any resources held by the client. 113 // Close flushes any pending logs and releases any resources held by the client.
86 // Close should be called when the client is no longer needed. 114 // Close should be called when the client is no longer needed.
87 func (c *Client) Close() error { 115 func (c *Client) Close() {
88 » return c.c.Close() 116 » c.bl.Close()
117 » c.ticker.Stop()
89 } 118 }
90 119
91 // ChromeInfraLogEvent stores a pending LogEvent, and the proto used to populate its SourceExtension field. 120 // ChromeInfraLogEvent stores a pending LogEvent, and the proto used to populate its SourceExtension field.
92 type ChromeInfraLogEvent struct { 121 type ChromeInfraLogEvent struct {
93 // LogEvent is the event to be sent to the server. The LogEvent's Source Extension 122 // LogEvent is the event to be sent to the server. The LogEvent's Source Extension
94 // field will be overwritten with the serialized contents of InfraEvent 123 // field will be overwritten with the serialized contents of InfraEvent
95 // when the log event is sent to the server. 124 // when the log event is sent to the server.
96 LogEvent *logpb.LogRequestLite_LogEventLite 125 LogEvent *logpb.LogRequestLite_LogEventLite
97 InfraEvent *logpb.ChromeInfraEvent 126 InfraEvent *logpb.ChromeInfraEvent
98 } 127 }
(...skipping 12 matching lines...) Expand all
111 140
112 // Begin returns the current time for use when logging the beginning of an event . 141 // Begin returns the current time for use when logging the beginning of an event .
113 func Begin() TypedTime { 142 func Begin() TypedTime {
114 return TypedTime{time.Now(), logpb.ChromeInfraEvent_BEGIN} 143 return TypedTime{time.Now(), logpb.ChromeInfraEvent_BEGIN}
115 } 144 }
116 145
117 // End returns the current time for use when logging the end of an event. 146 // End returns the current time for use when logging the end of an event.
118 func End() TypedTime { 147 func End() TypedTime {
119 return TypedTime{time.Now(), logpb.ChromeInfraEvent_END} 148 return TypedTime{time.Now(), logpb.ChromeInfraEvent_END}
120 } 149 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698