@@ -32,6 +32,7 @@ import (
32
32
"contrib.go.opencensus.io/exporter/prometheus"
33
33
"contrib.go.opencensus.io/exporter/stackdriver"
34
34
"github.com/GoogleCloudPlatform/alloydb-auth-proxy/alloydb"
35
+ "github.com/GoogleCloudPlatform/alloydb-auth-proxy/internal/log"
35
36
"github.com/GoogleCloudPlatform/alloydb-auth-proxy/internal/proxy"
36
37
"github.com/spf13/cobra"
37
38
"go.opencensus.io/trace"
@@ -76,8 +77,11 @@ func Execute() {
76
77
// Command represents an invocation of the AlloyDB Auth Proxy.
77
78
type Command struct {
78
79
* cobra.Command
79
- conf * proxy.Config
80
+ conf * proxy.Config
81
+ logger alloydb.Logger
82
+ dialer alloydb.Dialer
80
83
84
+ cleanup func () error
81
85
disableTraces bool
82
86
telemetryTracingSampleRate int
83
87
disableMetrics bool
@@ -88,25 +92,25 @@ type Command struct {
88
92
}
89
93
90
94
// Option is a function that configures a Command.
91
- type Option func (* proxy.Config )
95
+ type Option func (* Command )
96
+
97
+ // WithLogger overrides the default logger.
98
+ func WithLogger (l alloydb.Logger ) Option {
99
+ return func (c * Command ) {
100
+ c .logger = l
101
+ }
102
+ }
92
103
93
104
// WithDialer configures the Command to use the provided dialer to connect to
94
105
// AlloyDB instances.
95
106
func WithDialer (d alloydb.Dialer ) Option {
96
- return func (c * proxy. Config ) {
97
- c .Dialer = d
107
+ return func (c * Command ) {
108
+ c .dialer = d
98
109
}
99
110
}
100
111
101
112
// NewCommand returns a Command object representing an invocation of the proxy.
102
113
func NewCommand (opts ... Option ) * Command {
103
- c := & Command {
104
- conf : & proxy.Config {},
105
- }
106
- for _ , o := range opts {
107
- o (c .conf )
108
- }
109
-
110
114
cmd := & cobra.Command {
111
115
Use : "alloydb-auth-proxy instance_uri..." ,
112
116
Version : versionString ,
@@ -115,19 +119,38 @@ func NewCommand(opts ...Option) *Command {
115
119
connecting to AlloyDB instances. It listens on a local port and forwards
116
120
connections to your instance's IP address, providing a secure connection
117
121
without having to manage any client SSL certificates.` ,
118
- Args : func (cmd * cobra.Command , args []string ) error {
119
- err := parseConfig (cmd , c .conf , args )
120
- if err != nil {
121
- return err
122
- }
123
- // The arguments are parsed. Usage is no longer needed.
124
- cmd .SilenceUsage = true
125
- return nil
126
- },
127
- RunE : func (* cobra.Command , []string ) error {
128
- return runSignalWrapper (c )
122
+ }
123
+
124
+ logger := log .NewStdLogger (os .Stdout , os .Stderr )
125
+ c := & Command {
126
+ Command : cmd ,
127
+ logger : logger ,
128
+ cleanup : func () error { return nil },
129
+ conf : & proxy.Config {
130
+ UserAgent : userAgent ,
129
131
},
130
132
}
133
+ for _ , o := range opts {
134
+ o (c )
135
+ }
136
+
137
+ cmd .Args = func (cmd * cobra.Command , args []string ) error {
138
+ // Handle logger separately from config
139
+ if c .conf .StructuredLogs {
140
+ c .logger , c .cleanup = log .NewStructuredLogger ()
141
+ }
142
+ err := parseConfig (c , c .conf , args )
143
+ if err != nil {
144
+ return err
145
+ }
146
+ // The arguments are parsed. Usage is no longer needed.
147
+ cmd .SilenceUsage = true
148
+ // Errors will be handled by logging from here on.
149
+ cmd .SilenceErrors = true
150
+ return nil
151
+ }
152
+
153
+ cmd .RunE = func (* cobra.Command , []string ) error { return runSignalWrapper (c ) }
131
154
132
155
// Global-only flags
133
156
cmd .PersistentFlags ().StringVarP (& c .conf .Token , "token" , "t" , "" ,
@@ -136,6 +159,8 @@ without having to manage any client SSL certificates.`,
136
159
"Path to a service account key to use for authentication." )
137
160
cmd .PersistentFlags ().BoolVarP (& c .conf .GcloudAuth , "gcloud-auth" , "g" , false ,
138
161
"Use gcloud's user configuration to retrieve a token for authentication." )
162
+ cmd .PersistentFlags ().BoolVarP (& c .conf .StructuredLogs , "structured-logs" , "l" , false ,
163
+ "Enable structured logs using the LogEntry format" )
139
164
cmd .PersistentFlags ().Uint64Var (& c .conf .MaxConnections , "max-connections" , 0 ,
140
165
`Limits the number of connections by refusing any additional connections.
141
166
When this flag is not set, there is no limit.` )
@@ -168,18 +193,15 @@ the maximum time has passed. Defaults to 0s.`)
168
193
cmd .PersistentFlags ().StringVarP (& c .conf .UnixSocket , "unix-socket" , "u" , "" ,
169
194
`Enables Unix sockets for all listeners using the provided directory.` )
170
195
171
- c .Command = cmd
172
196
return c
173
197
}
174
198
175
- func parseConfig (cmd * cobra. Command , conf * proxy.Config , args []string ) error {
199
+ func parseConfig (cmd * Command , conf * proxy.Config , args []string ) error {
176
200
// If no instance connection names were provided, error.
177
201
if len (args ) == 0 {
178
202
return newBadCommandError ("missing instance uri (e.g., /projects/$PROJECTS/locations/$LOCTION/clusters/$CLUSTER/instances/$INSTANCES)" )
179
203
}
180
204
181
- conf .UserAgent = userAgent
182
-
183
205
userHasSet := func (f string ) bool {
184
206
return cmd .PersistentFlags ().Lookup (f ).Changed
185
207
}
@@ -210,13 +232,13 @@ func parseConfig(cmd *cobra.Command, conf *proxy.Config, args []string) error {
210
232
}
211
233
212
234
if ! userHasSet ("telemetry-project" ) && userHasSet ("telemetry-prefix" ) {
213
- cmd .Println ("Ignoring telementry-prefix as telemetry-project was not set" )
235
+ cmd .logger . Infof ("Ignoring telementry-prefix as telemetry-project was not set" )
214
236
}
215
237
if ! userHasSet ("telemetry-project" ) && userHasSet ("disable-metrics" ) {
216
- cmd .Println ("Ignoring disable-metrics as telemetry-project was not set" )
238
+ cmd .logger . Infof ("Ignoring disable-metrics as telemetry-project was not set" )
217
239
}
218
240
if ! userHasSet ("telemetry-project" ) && userHasSet ("disable-traces" ) {
219
- cmd .Println ("Ignoring disable-traces as telemetry-project was not set" )
241
+ cmd .logger . Infof ("Ignoring disable-traces as telemetry-project was not set" )
220
242
}
221
243
222
244
var ics []proxy.InstanceConnConfig
@@ -288,6 +310,7 @@ func parseConfig(cmd *cobra.Command, conf *proxy.Config, args []string) error {
288
310
289
311
// runSignalWrapper watches for SIGTERM and SIGINT and interupts execution if necessary.
290
312
func runSignalWrapper (cmd * Command ) error {
313
+ defer cmd .cleanup ()
291
314
ctx , cancel := context .WithCancel (cmd .Context ())
292
315
defer cancel ()
293
316
@@ -340,7 +363,7 @@ func runSignalWrapper(cmd *Command) error {
340
363
// Give the HTTP server a second to shutdown cleanly.
341
364
ctx2 , _ := context .WithTimeout (context .Background (), time .Second )
342
365
if err := server .Shutdown (ctx2 ); err != nil {
343
- cmd .Printf ("failed to shutdown Prometheus HTTP server: %v\n " , err )
366
+ cmd .logger . Errorf ("failed to shutdown Prometheus HTTP server: %v\n " , err )
344
367
}
345
368
}
346
369
}()
@@ -378,7 +401,7 @@ func runSignalWrapper(cmd *Command) error {
378
401
startCh := make (chan * proxy.Client )
379
402
go func () {
380
403
defer close (startCh )
381
- p , err := proxy .NewClient (ctx , cmd .Command , cmd .conf )
404
+ p , err := proxy .NewClient (ctx , cmd .dialer , cmd . logger , cmd .conf )
382
405
if err != nil {
383
406
shutdownCh <- fmt .Errorf ("unable to start: %v" , err )
384
407
return
@@ -389,13 +412,15 @@ func runSignalWrapper(cmd *Command) error {
389
412
var p * proxy.Client
390
413
select {
391
414
case err := <- shutdownCh :
415
+ cmd .logger .Errorf ("The proxy has encountered a terminal error: %v" , err )
392
416
return err
393
417
case p = <- startCh :
394
418
}
395
- cmd .Println ("The proxy has started successfully and is ready for new connections!" )
419
+ cmd .logger .Infof ("The proxy has started successfully and is ready for new connections!" )
420
+ defer p .Close ()
396
421
defer func () {
397
422
if cErr := p .Close (); cErr != nil {
398
- cmd .PrintErrf ( "The proxy failed to close cleanly : %v\n " , cErr )
423
+ cmd .logger . Errorf ( "error during shutdown : %v" , cErr )
399
424
}
400
425
}()
401
426
@@ -406,11 +431,11 @@ func runSignalWrapper(cmd *Command) error {
406
431
err := <- shutdownCh
407
432
switch {
408
433
case errors .Is (err , errSigInt ):
409
- cmd .PrintErrln ("SIGINT signal received. Shutting down..." )
434
+ cmd .logger . Errorf ("SIGINT signal received. Shutting down..." )
410
435
case errors .Is (err , errSigTerm ):
411
- cmd .PrintErrln ("SIGTERM signal received. Shutting down..." )
436
+ cmd .logger . Errorf ("SIGTERM signal received. Shutting down..." )
412
437
default :
413
- cmd .PrintErrf ("The proxy has encountered a terminal error: %v\n " , err )
438
+ cmd .logger . Errorf ("The proxy has encountered a terminal error: %v" , err )
414
439
}
415
440
return err
416
441
}
0 commit comments