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

Side by Side Diff: common/cloudlogging/client.go

Issue 2937693003: Make luci-go compile again after deps.lock roll. (Closed)
Patch Set: Created 3 years, 6 months 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/cloudlogging/buffer_test.go ('k') | common/cloudlogging/client_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package cloudlogging
6
7 import (
8 "errors"
9 "flag"
10 "fmt"
11 "net/http"
12 "os"
13
14 "cloud.google.com/go/compute/metadata"
15 cloudlog "google.golang.org/api/logging/v1beta3"
16 )
17
18 // DefaultResourceType is used by NewClient if ClientOptions doesn't specify
19 // ResourceType.
20 const (
21 // GCEService is service name for GCE instances.
22 GCEService = "compute.googleapis.com"
23
24 // DefaultResourceType is used as the ResourceType value if Options does n't
25 // specify a ResourceType.
26 DefaultResourceType = "machine"
27
28 // WriteScope is the cloud logging OAuth write scope.
29 WriteScope = cloudlog.LoggingWriteScope
30 )
31
32 // CloudLoggingScopes is the set of OAuth scopes that are required to
33 // publish cloud logs via this package.
34 var CloudLoggingScopes = []string{
35 WriteScope,
36 }
37
38 // Labels is a set of key/value data that is transmitted alongside a log entry.
39 type Labels map[string]string
40
41 // ClientOptions is passed to NewClient.
42 type ClientOptions struct {
43 // ProjectID is Cloud project to sends logs to. Must be set.
44 ProjectID string
45 // LogID identifies what sort of log this is. Must be set.
46 LogID string
47
48 // Zone is the service name that the log will be registered under. Defau lt is
49 // GCEService.
50 ServiceName string
51 // Zone is the zone to attribute the log to. This can be empty.
52 Zone string
53 // ResourceType identifies a kind of entity that produces this log (e.g.
54 // 'machine', 'master'). Default is DefaultResourceType.
55 ResourceType string
56 // ResourceID identifies exact instance of provided resource type (e.g
57 // 'vm12-m4', 'master.chromium.fyi'). Default is machine hostname.
58 ResourceID string
59 // Region is the region to attribute the log to. This can be empty.
60 Region string
61 // Region is the user ID to attribute the log to. This can be empty.
62 UserID string
63
64 // UserAgent is an optional string appended to User-Agent HTTP header.
65 UserAgent string
66
67 // CommonLabels is a list of key/value labels that will be included with each
68 // log message that is sent.
69 CommonLabels Labels
70
71 // ErrorWriter, if not nil, will be called when an error is encountered in
72 // the Client iself. This is used to report errors because the client ma y
73 // send messages asynchronously, so they will not be returned immediatel y,
74 // as is the go convention.
75 ErrorWriter func(string)
76 }
77
78 // Populate fills the Config with default values derived from the environment.
79 // Missing values will not be set.
80 //
81 // This includes:
82 // - GCE metadata querying.
83 func (o *ClientOptions) Populate() {
84 if metadata.OnGCE() {
85 get := func(f func() (string, error), val *string) {
86 if v, err := f(); err == nil {
87 *val = v
88 }
89 }
90
91 o.ServiceName = GCEService
92 get(metadata.ProjectID, &o.ProjectID)
93 get(metadata.InstanceName, &o.ResourceType)
94 get(metadata.InstanceID, &o.ResourceID)
95 get(metadata.Zone, &o.Zone)
96 }
97 if o.ErrorWriter == nil {
98 o.ErrorWriter = func(s string) {
99 fmt.Fprintln(os.Stderr, s)
100 }
101 }
102 }
103
104 // Validate evaluates a Config and returns an error if it is invalid or
105 // incomplete.
106 func (o *ClientOptions) Validate() error {
107 if o.ProjectID == "" {
108 return errors.New("cloudlogging: You must supply a project name" )
109 }
110 if o.LogID == "" {
111 return errors.New("cloudlogging: You must supply a logs ID")
112 }
113 if o.ResourceType == "" {
114 return errors.New("cloudlogging: You must supply a resource type ")
115 }
116 return nil
117 }
118
119 // AddFlags adds logging flags to the supplied FlagSet.
120 func (o *ClientOptions) AddFlags(fs *flag.FlagSet) {
121 fs.StringVar(&o.LogID, "cloud-logging-logs-id", o.LogID,
122 "For cloud logging, the log stream ID.")
123 fs.StringVar(&o.ServiceName, "cloud-logging-service", o.ServiceName,
124 "For cloud logging, the service name.")
125 fs.StringVar(&o.ProjectID, "cloud-logging-project-name", o.ProjectID,
126 "For cloud logging, the project name.")
127 fs.StringVar(&o.ResourceType, "cloud-logging-resource-type", o.ResourceT ype,
128 "For cloud logging, the instance name.")
129 fs.StringVar(&o.ResourceID, "cloud-logging-resource-id", o.ResourceID,
130 "For cloud logging, the instance ID.")
131 fs.StringVar(&o.Region, "cloud-logging-region", o.Region,
132 "For cloud logging, the region.")
133 fs.StringVar(&o.UserID, "cloud-logging-user", o.UserID,
134 "For cloud logging, the user ID.")
135 fs.StringVar(&o.Zone, "cloud-logging-zone", o.Zone,
136 "For cloud logging, the zone.")
137 }
138
139 // Client knows how to send entries to Cloud Logging log.
140 type Client interface {
141 // PushEntries sends entries to Cloud Logging. No retries.
142 PushEntries(entries []*Entry) error
143 }
144
145 // NewClient returns new object that knows how to push log entries to a single
146 // log in Cloud Logging.
147 func NewClient(opts ClientOptions, client *http.Client) (Client, error) {
148 if err := opts.Validate(); err != nil {
149 return nil, err
150 }
151
152 if opts.ResourceType == "" {
153 opts.ResourceType = DefaultResourceType
154 }
155 if opts.ResourceID == "" {
156 var err error
157 hostname, err := os.Hostname()
158 if err != nil {
159 return nil, err
160 }
161 opts.ResourceID = hostname
162 }
163 if opts.LogID == "" {
164 return nil, errors.New("cloudlogging: no LogID is provided")
165 }
166
167 service, err := cloudlog.New(client)
168 if err != nil {
169 return nil, err
170 }
171 if opts.UserAgent != "" {
172 service.UserAgent = opts.UserAgent
173 }
174
175 c := clientImpl{
176 ClientOptions: &opts,
177 service: cloudlog.NewProjectsLogsEntriesService(service),
178 commonLabels: make(map[string]string, len(opts.CommonLabels)),
179 }
180 for k, v := range opts.CommonLabels {
181 c.commonLabels[k] = v
182 }
183 if c.ResourceType != "" {
184 c.commonLabels["compute.googleapis.com/resource_type"] = c.Resou rceType
185 }
186 if c.ResourceID != "" {
187 c.commonLabels["compute.googleapis.com/resource_id"] = c.Resourc eID
188 }
189 return &c, nil
190 }
191
192 type clientImpl struct {
193 *ClientOptions
194
195 service *cloudlog.ProjectsLogsEntriesService
196 // These are passed to Cloud Logging API as is.
197 commonLabels map[string]string
198 }
199
200 func (c *clientImpl) PushEntries(entries []*Entry) error {
201 req := cloudlog.WriteLogEntriesRequest{
202 CommonLabels: c.commonLabels,
203 Entries: make([]*cloudlog.LogEntry, 0, len(entries)),
204 }
205 for i, e := range entries {
206 entry, err := e.cloudLogEntry(c.ClientOptions)
207 if err != nil {
208 c.writeError("Failed to build log for entry #%d: %v", i, err)
209 return err
210 }
211 req.Entries = append(req.Entries, entry)
212 }
213
214 _, err := c.service.Write(c.ProjectID, c.LogID, &req).Do()
215 if err != nil {
216 c.writeError(err.Error())
217 }
218 return err
219 }
220
221 func (c *clientImpl) writeError(f string, args ...interface{}) {
222 if c.ErrorWriter != nil {
223 c.ErrorWriter(fmt.Sprintf(f, args...))
224 }
225 }
OLDNEW
« no previous file with comments | « common/cloudlogging/buffer_test.go ('k') | common/cloudlogging/client_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698