1
1
package blade
2
2
3
3
import (
4
+ "context"
4
5
"encoding/json"
5
6
"errors"
6
7
"fmt"
@@ -9,10 +10,9 @@ import (
9
10
10
11
"github.com/TylerBrock/colorjson"
11
12
"github.com/TylerBrock/saw/config"
12
- "github.com/aws/aws-sdk-go/aws"
13
- "github.com/aws/aws-sdk-go/aws/credentials/stscreds"
14
- "github.com/aws/aws-sdk-go/aws/session"
15
- "github.com/aws/aws-sdk-go/service/cloudwatchlogs"
13
+ awsconfig "github.com/aws/aws-sdk-go-v2/config"
14
+ "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs"
15
+ "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
16
16
"github.com/fatih/color"
17
17
)
18
18
@@ -21,70 +21,62 @@ type Blade struct {
21
21
config * config.Configuration
22
22
aws * config.AWSConfiguration
23
23
output * config.OutputConfiguration
24
- cwl * cloudwatchlogs.CloudWatchLogs
24
+ cwl * cloudwatchlogs.Client
25
25
}
26
26
27
27
// NewBlade creates a new Blade with CloudWatchLogs instance from provided config
28
28
func NewBlade (
29
+ ctx context.Context ,
29
30
config * config.Configuration ,
30
31
awsConfig * config.AWSConfiguration ,
31
32
outputConfig * config.OutputConfiguration ,
32
- ) * Blade {
33
+ ) ( * Blade , error ) {
33
34
blade := Blade {}
34
- awsCfg := aws.Config {}
35
-
36
- if awsConfig .Region != "" {
37
- awsCfg .Region = & awsConfig .Region
38
- }
39
-
40
- awsSessionOpts := session.Options {
41
- Config : awsCfg ,
42
- AssumeRoleTokenProvider : stscreds .StdinTokenProvider ,
43
- SharedConfigState : session .SharedConfigEnable ,
44
- }
45
35
36
+ var opts []func (* awsconfig.LoadOptions ) error
46
37
if awsConfig .Profile != "" {
47
- awsSessionOpts . Profile = awsConfig .Profile
38
+ opts = append ( opts , awsconfig . WithSharedConfigProfile ( awsConfig .Profile ))
48
39
}
40
+ if awsConfig .Region != "" {
41
+ opts = append (opts , awsconfig .WithRegion (awsConfig .Region ))
42
+ }
43
+ awsCfg , err := awsconfig .LoadDefaultConfig (ctx , opts ... )
49
44
50
- sess := session .Must (session .NewSessionWithOptions (awsSessionOpts ))
51
-
52
- blade .cwl = cloudwatchlogs .New (sess )
45
+ blade .cwl = cloudwatchlogs .NewFromConfig (awsCfg )
53
46
blade .config = config
54
47
blade .output = outputConfig
55
48
56
- return & blade
49
+ return & blade , err
57
50
}
58
51
59
52
// GetLogGroups gets the log groups from AWS given the blade configuration
60
- func (b * Blade ) GetLogGroups () [] * cloudwatchlogs .LogGroup {
53
+ func (b * Blade ) GetLogGroups (ctx context. Context ) ( groups []types .LogGroup , err error ) {
61
54
input := b .config .DescribeLogGroupsInput ()
62
- groups := make ([]* cloudwatchlogs.LogGroup , 0 )
63
- b .cwl .DescribeLogGroupsPages (input , func (
64
- out * cloudwatchlogs.DescribeLogGroupsOutput ,
65
- lastPage bool ,
66
- ) bool {
67
- for _ , group := range out .LogGroups {
68
- if b .config .Fuzzy && ! groupNameMatches (* group .LogGroupName , b .config .Group ) {
69
- continue
70
- }
71
- groups = append (groups , group )
55
+ logGroupsPaginator := cloudwatchlogs .NewDescribeLogGroupsPaginator (b .cwl , input )
56
+ var page * cloudwatchlogs.DescribeLogGroupsOutput
57
+ for logGroupsPaginator .HasMorePages () {
58
+ page , err = logGroupsPaginator .NextPage (ctx )
59
+ if err != nil {
60
+ return
72
61
}
73
- return ! lastPage
74
- })
75
- return groups
62
+ groups = append ( groups , page . LogGroups ... )
63
+ }
64
+ return
76
65
}
77
66
78
67
func groupNameMatches (s , substr string ) bool {
79
68
return strings .Contains (s , substr )
80
69
}
81
70
82
- func (b * Blade ) ResolveFuzzyGroupName () (err error ) {
71
+ func (b * Blade ) ResolveFuzzyGroupName (ctx context. Context ) (err error ) {
83
72
if ! b .config .Fuzzy {
84
73
return
85
74
}
86
75
b .config .Fuzzy = false
87
- groups := b .GetLogGroups ()
76
+ groups , err := b .GetLogGroups (ctx )
77
+ if err != nil {
78
+ return
79
+ }
88
80
if len (groups ) == 0 {
89
81
return errors .New ("no log groups found" )
90
82
}
@@ -99,15 +91,15 @@ func (b *Blade) ResolveFuzzyGroupName() (err error) {
99
91
return
100
92
}
101
93
102
- func getGroupNames (groups []* cloudwatchlogs .LogGroup ) (op []string ) {
94
+ func getGroupNames (groups []types .LogGroup ) (op []string ) {
103
95
op = make ([]string , len (groups ))
104
96
for i := 0 ; i < len (groups ); i ++ {
105
97
op [i ] = * groups [i ].LogGroupName
106
98
}
107
99
return
108
100
}
109
101
110
- func filterGroupNames (groups []* cloudwatchlogs .LogGroup , group string ) (op []string ) {
102
+ func filterGroupNames (groups []types .LogGroup , group string ) (op []string ) {
111
103
for i := 0 ; i < len (groups ); i ++ {
112
104
if groupNameMatches (* groups [i ].LogGroupName , group ) {
113
105
op = append (op , * groups [i ].LogGroupName )
@@ -117,46 +109,50 @@ func filterGroupNames(groups []*cloudwatchlogs.LogGroup, group string) (op []str
117
109
}
118
110
119
111
// GetLogStreams gets the log streams from AWS given the blade configuration
120
- func (b * Blade ) GetLogStreams () (streams []* cloudwatchlogs .LogStream , err error ) {
121
- if err := b .ResolveFuzzyGroupName (); err != nil {
112
+ func (b * Blade ) GetLogStreams (ctx context. Context ) (streams []types .LogStream , err error ) {
113
+ if err := b .ResolveFuzzyGroupName (ctx ); err != nil {
122
114
return nil , err
123
115
}
124
116
input := b .config .DescribeLogStreamsInput ()
125
- b .cwl . DescribeLogStreamsPages ( input , func (
126
- out * cloudwatchlogs.DescribeLogStreamsOutput ,
127
- lastPage bool ,
128
- ) bool {
129
- for _ , stream := range out . LogStreams {
130
- streams = append ( streams , stream )
117
+ logStreamsPaginator := cloudwatchlogs . NewDescribeLogStreamsPaginator ( b .cwl , input )
118
+ var page * cloudwatchlogs.DescribeLogStreamsOutput
119
+ for logStreamsPaginator . HasMorePages () {
120
+ page , err = logStreamsPaginator . NextPage ( ctx )
121
+ if err != nil {
122
+ return
131
123
}
132
- return ! lastPage
133
- })
134
- return streams , err
124
+ streams = append ( streams , page . LogStreams ... )
125
+ }
126
+ return
135
127
}
136
128
137
129
// GetEvents gets events from AWS given the blade configuration
138
- func (b * Blade ) GetEvents () (err error ) {
139
- if err := b .ResolveFuzzyGroupName (); err != nil {
130
+ func (b * Blade ) GetEvents (ctx context. Context ) (err error ) {
131
+ if err := b .ResolveFuzzyGroupName (ctx ); err != nil {
140
132
return err
141
133
}
142
134
formatter := b .output .Formatter ()
143
135
input := b .config .FilterLogEventsInput ()
144
-
145
- handlePage := func (page * cloudwatchlogs.FilterLogEventsOutput , lastPage bool ) bool {
136
+ logEventsPaginator := cloudwatchlogs .NewFilterLogEventsPaginator (b .cwl , input )
137
+ var page * cloudwatchlogs.FilterLogEventsOutput
138
+ for logEventsPaginator .HasMorePages () {
139
+ page , err = logEventsPaginator .NextPage (ctx )
140
+ if err != nil {
141
+ return
142
+ }
146
143
for _ , event := range page .Events {
147
144
if b .output .Pretty {
148
145
fmt .Println (strings .TrimRight (formatEvent (formatter , event ), "\n " ))
149
146
} else {
150
147
fmt .Println (strings .TrimRight (* event .Message , "\n " ))
151
148
}
152
149
}
153
- return ! lastPage
154
150
}
155
- return b . cwl . FilterLogEventsPages ( input , handlePage )
151
+ return
156
152
}
157
153
158
154
// StreamEvents continuously prints log events to the console
159
- func (b * Blade ) StreamEvents () (err error ) {
155
+ func (b * Blade ) StreamEvents (ctx context. Context ) (err error ) {
160
156
var lastSeenTime * int64
161
157
var seenEventIDs map [string ]bool
162
158
formatter := b .output .Formatter ()
@@ -177,46 +173,45 @@ func (b *Blade) StreamEvents() (err error) {
177
173
}
178
174
}
179
175
180
- handlePage := func (page * cloudwatchlogs.FilterLogEventsOutput , lastPage bool ) bool {
181
- for _ , event := range page .Events {
182
- updateLastSeenTime (event .Timestamp )
183
- if _ , seen := seenEventIDs [* event .EventId ]; ! seen {
184
- var message string
185
- if b .output .Raw {
186
- message = * event .Message
187
- } else {
188
- message = formatEvent (formatter , event )
176
+ for {
177
+ logEventsPaginator := cloudwatchlogs .NewFilterLogEventsPaginator (b .cwl , input )
178
+ var page * cloudwatchlogs.FilterLogEventsOutput
179
+ for logEventsPaginator .HasMorePages () {
180
+ page , err = logEventsPaginator .NextPage (ctx )
181
+ if err != nil {
182
+ return
183
+ }
184
+ for _ , event := range page .Events {
185
+ updateLastSeenTime (event .Timestamp )
186
+ if _ , seen := seenEventIDs [* event .EventId ]; ! seen {
187
+ var message string
188
+ if b .output .Raw {
189
+ message = * event .Message
190
+ } else {
191
+ message = formatEvent (formatter , event )
192
+ }
193
+ message = strings .TrimRight (message , "\n " )
194
+ fmt .Println (message )
195
+ addSeenEventIDs (event .EventId )
189
196
}
190
- message = strings .TrimRight (message , "\n " )
191
- fmt .Println (message )
192
- addSeenEventIDs (event .EventId )
193
197
}
194
198
}
195
- return ! lastPage
196
- }
197
-
198
- for {
199
- err = b .cwl .FilterLogEventsPages (input , handlePage )
200
- if err != nil {
201
- return
202
- }
203
199
if lastSeenTime != nil {
204
- input .SetStartTime ( * lastSeenTime )
200
+ input .StartTime = lastSeenTime
205
201
}
206
202
time .Sleep (1 * time .Second )
207
203
}
208
204
}
209
205
210
206
// formatEvent returns a CloudWatch log event as a formatted string using the provided formatter
211
- func formatEvent (formatter * colorjson.Formatter , event * cloudwatchlogs .FilteredLogEvent ) string {
207
+ func formatEvent (formatter * colorjson.Formatter , event types .FilteredLogEvent ) string {
212
208
red := color .New (color .FgRed ).SprintFunc ()
213
209
white := color .New (color .FgWhite ).SprintFunc ()
214
210
215
- str := aws .StringValue (event .Message )
216
- bytes := []byte (str )
217
- date := aws .MillisecondsTimeValue (event .Timestamp )
218
- dateStr := date .Format (time .RFC3339 )
219
- streamStr := aws .StringValue (event .LogStreamName )
211
+ str := * event .Message
212
+ bytes := []byte (* event .Message )
213
+ dateStr := time .UnixMilli (* event .Timestamp ).Format (time .RFC3339 )
214
+ streamStr := * event .LogStreamName
220
215
jl := map [string ]interface {}{}
221
216
222
217
if err := json .Unmarshal (bytes , & jl ); err != nil {
0 commit comments