Skip to content

Commit

Permalink
Add logs commands via github.com/TylerBrock/saw
Browse files Browse the repository at this point in the history
  • Loading branch information
ipmb committed Dec 12, 2020
1 parent c3f8fc9 commit 8e5d0bd
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 0 deletions.
5 changes: 5 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package app
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"strings"
Expand Down Expand Up @@ -65,6 +67,9 @@ type Settings struct {
S3Bucket string `json:"s3_bucket"`
DumpLoadTaskFamily string `json:"dumpload_task_family"`
} `json:"dbutils"`
LogGroup struct {
Name string `json:"name"`
} `json:"log_group"`
}

type appItem struct {
Expand Down
142 changes: 142 additions & 0 deletions cmd/logs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
Copyright © 2020 NAME HERE <EMAIL ADDRESS>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd

import (
"fmt"
"net/url"
"reflect"
"strings"
"unsafe"

"github.com/TylerBrock/saw/blade"
sawconfig "github.com/TylerBrock/saw/config"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
"github.com/lincolnloop/apppack/app"
"github.com/pkg/browser"
"github.com/spf13/cobra"
)

var sawConfig sawconfig.Configuration
var sawOutputConfig sawconfig.OutputConfiguration

// newBlade is a hack to get a Blade instance with our AWS session
func newBlade(session *session.Session) *blade.Blade {
b := blade.Blade{}
setField := func(name string, value interface{}) {
field := reflect.ValueOf(&b).Elem().FieldByName(name)
reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Set(reflect.ValueOf(value))
}
setField("cwl", cloudwatchlogs.New(session))
setField("config", &sawConfig)
setField("output", &sawOutputConfig)
return &b
}

// logsCmd represents the logs command
var logsCmd = &cobra.Command{
Use: "logs",
Short: "Access application logs from Cloudwatch Logs",
Long: `Access application logs from Cloudwatch Logs`,
}

// logsCmd represents the logs command
var logsViewCmd = &cobra.Command{
Use: "view",
Short: "Print application logs to terminal",
Long: `Print application logs to terminal`,
Run: func(cmd *cobra.Command, args []string) {
Spinner.Start()
a, err := app.Init(AppName)
checkErr(err)
a.LoadSettings()
sawConfig.Group = a.Settings.LogGroup.Name
sawOutputConfig.Pretty = !sawOutputConfig.Raw
// convert to format saw eexpects
sawConfig.Start = fmt.Sprintf("-%s", sawConfig.Start)
if sawConfig.End != "" && sawConfig.End != "now" {
sawConfig.End = fmt.Sprintf("-%s", sawConfig.Start)
}
b := newBlade(a.Session)
if sawConfig.Prefix != "" {
streams := b.GetLogStreams()
if len(streams) == 0 {
checkErr(fmt.Errorf("no streams found in %s with prefix %s", sawConfig.Group, sawConfig.Prefix))
}
sawConfig.Streams = streams
}
Spinner.Stop()
if cmd.Flags().Lookup("follow").Value.String() == "true" {
b.StreamEvents()
} else {
b.GetEvents()
}
},
}

// logsCmd represents the logs command
var logsConsoleCmd = &cobra.Command{
Use: "console",
Short: "View logs in the AWS web console",
Long: `View logs in the AWS web console`,
Run: func(cmd *cobra.Command, args []string) {
a, err := app.Init(AppName)
a.LoadSettings()
checkErr(err)
logGroupParam := strings.ReplaceAll(url.QueryEscape(a.Settings.LogGroup.Name), "%", "*")
queryParam := strings.ReplaceAll(url.QueryEscape("fields @timestamp, @message\n| sort @timestamp desc\n| limit 200"), "%", "*")
// TODO remove hard-coded region
region := "us-east-1"
destinationURL := fmt.Sprintf("https://console.aws.amazon.com/cloudwatch/home?region=%s#logsV2:logs-insights$3FqueryDetail$3D~(editorString~'%s~source~(~'%s))", region, queryParam, logGroupParam)
signinURL, err := a.GetConsoleURL(destinationURL)
checkErr(err)
browser.OpenURL(*signinURL)
},
}

func init() {
rootCmd.AddCommand(logsCmd)
logsCmd.PersistentFlags().StringVarP(&AppName, "app-name", "a", "", "App name (required)")
logsCmd.MarkPersistentFlagRequired("app-name")

logsCmd.AddCommand(logsConsoleCmd)
logsCmd.AddCommand(logsViewCmd)
logsViewCmd.Flags().StringVar(&sawConfig.Prefix, "prefix", "", `log group prefix filter
Use this to filter logs for specific services, e.g. "web", "worker"`)
logsViewCmd.Flags().StringVar(
&sawConfig.Start,
"start",
"5m",
`start getting the logs from this point
Takes an absolute timestamp in RFC3339 format, or a relative time (eg. 2h).
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`,
)
logsViewCmd.Flags().StringVar(
&sawConfig.End,
"stop",
"now",
`stop getting the logs at this point
Takes an absolute timestamp in RFC3339 format, or a relative time (eg. 2h).
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`,
)
logsViewCmd.Flags().StringVar(&sawConfig.Filter, "filter", "", "event filter pattern")
logsViewCmd.Flags().BoolVar(&sawOutputConfig.Raw, "raw", false, "No timestamp, log group or colors")
logsViewCmd.Flags().BoolVar(&sawOutputConfig.Expand, "expand", false, "indent JSON log messages")
logsViewCmd.Flags().BoolVar(&sawOutputConfig.Invert, "invert", false, "invert colors for light terminal themes")
logsViewCmd.Flags().BoolVar(&sawOutputConfig.RawString, "rawString", false, "print JSON strings without escaping")
logsViewCmd.Flags().BoolP("follow", "f", false, "Stream logs to console")
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ go 1.15

require (
github.com/AlecAivazis/survey/v2 v2.2.4
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 // indirect
github.com/TylerBrock/saw v0.2.2
github.com/aws/aws-sdk-go v1.35.35
github.com/briandowns/spinner v1.12.0
github.com/google/uuid v1.1.2
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4=
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w=
github.com/TylerBrock/saw v0.2.2 h1:X1nP3yH+HO5zJPxx8i2oWev08vTy1ho2M9F/iBJfqr4=
github.com/TylerBrock/saw v0.2.2/go.mod h1:k/53BhafoXlHfH39jHLPoiRH32ksrLKAWxwUSF4zvKI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
Expand Down

0 comments on commit 8e5d0bd

Please sign in to comment.