diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..aec3fa8 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,34 @@ +version: 2.0 +jobs: + build: + docker: + - image: circleci/golang:1.12 + steps: + - checkout + - run: ./build.sh + deploy: + docker: + - image: circleci/golang:1.14 + steps: + - checkout + - run: | + mkdir dist/ + go get github.com/mitchellh/gox + go get github.com/tcnksm/ghr + gox -output="dist/{{.Dir}}_{{.OS}}_{{.Arch}}" -os="linux darwin" -arch="386 amd64" ./paperlog + gox -output="dist/{{.Dir}}_{{.OS}}_{{.Arch}}" -os="linux windows darwin" -arch="386 amd64" ./slack + gox -output="dist/{{.Dir}}_{{.OS}}_{{.Arch}}" -os="linux windows darwin" -arch="386 amd64" ./get_secret + gox -output="dist/{{.Dir}}_{{.OS}}_{{.Arch}}" -os="linux windows darwin" -arch="386 amd64" ./active_conn + ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${CIRCLE_TAG} ./dist/ + +workflows: + version: 2 + release: + jobs: + - build + - deploy: + filters: + tags: + only: /v[0-9]+(\.[0-9]+)*(-.*)*/ + branches: + ignore: /.*/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1ecfd1f..05ec31a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.exe dist/ -*.log \ No newline at end of file +*.log +.env \ No newline at end of file diff --git a/README.md b/README.md index ff64211..115d52a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ A suite CLI tools & utilities - [slack](./slack) - send slack notifications - [get_secret](./get_secret) - fetch AWS Secrets Manager Secrets - [dumb_daemon](./dumb_daemon) - A useless daemon that just appends to a log file +- [active_conn](./active_conn) - Print number of active Mysql connections every x seconds ## Basic Usage diff --git a/active_conn/.env.sample b/active_conn/.env.sample new file mode 100644 index 0000000..48b284e --- /dev/null +++ b/active_conn/.env.sample @@ -0,0 +1,4 @@ +DB_HOST=localhost +DB_USER= +DB_PASS= +DB_NAME= diff --git a/active_conn/.gitignore b/active_conn/.gitignore new file mode 100644 index 0000000..089ce49 --- /dev/null +++ b/active_conn/.gitignore @@ -0,0 +1 @@ +active_conn \ No newline at end of file diff --git a/active_conn/README.md b/active_conn/README.md new file mode 100644 index 0000000..11a3b57 --- /dev/null +++ b/active_conn/README.md @@ -0,0 +1,8 @@ +# active_conn + +Prints the number of active MySQL connections to a database at a desired interval (default: 5seconds) + +``` +./active_conn -interval 10s +``` +- Print number of active connections every 10 seconds diff --git a/active_conn/go.mod b/active_conn/go.mod new file mode 100644 index 0000000..51b98fd --- /dev/null +++ b/active_conn/go.mod @@ -0,0 +1,8 @@ +module github.com/peteretelej/tools/active_conn + +go 1.14 + +require ( + github.com/go-sql-driver/mysql v1.5.0 + github.com/joho/godotenv v1.3.0 +) diff --git a/active_conn/go.sum b/active_conn/go.sum new file mode 100644 index 0000000..157a6a3 --- /dev/null +++ b/active_conn/go.sum @@ -0,0 +1,4 @@ +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= diff --git a/active_conn/main.go b/active_conn/main.go new file mode 100644 index 0000000..3b74ede --- /dev/null +++ b/active_conn/main.go @@ -0,0 +1,102 @@ +package main + +import ( + "database/sql" + "flag" + "fmt" + "log" + "os" + "os/signal" + "time" + + _ "github.com/go-sql-driver/mysql" + "github.com/joho/godotenv" +) + +var db *sql.DB + +func main() { + var ( + interval = flag.Duration("interval", time.Second*5, "Interval between active connections checks") + ) + flag.Parse() + log.SetPrefix("[active_conn] ") + if _, err := os.Stat(".env"); err == nil { + err := godotenv.Load() + if err != nil { + log.Fatal("Error loading .env file") + } + } + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + go func() { + select { + case _ = <-c: + log.Printf("Shutting down..") + if err := cleanup(); err != nil { + log.Fatalf("cleanup failed: %v", err) + } + os.Exit(0) + } + }() + if err := dbconn(); err != nil { + log.Fatalf("failed to connect to db: %v", err) + } + + if err := checks(*interval); err != nil { + log.Printf("checks failed: %v", err) + if err := cleanup(); err != nil { + log.Fatal(err) + } + } +} + +func dbconn() error { + for _, env := range []string{"DB_HOST", "DB_USER", "DB_PASS"} { + if v := os.Getenv(env); v == "" { + return fmt.Errorf("Missing environment variable: %s (please see .env.sample)", env) + } + } + var err error + db, err = sql.Open("mysql", + fmt.Sprintf("%s:%s@tcp(%s:3306)/%s", + os.Getenv("DB_USER"), os.Getenv("DB_PASS"), + os.Getenv("DB_HOST"), os.Getenv("DB_NAME")), + ) + if err != nil { + return err + } + return db.Ping() +} + +func cleanup() error { + if err := db.Close(); err != nil { + log.Printf("Failed to close db conn: %v", err) + } + return nil +} + +func countConns() (int, error) { + var count int + var a string + err := db.QueryRow("show status where `variable_name` = 'Threads_connected' ").Scan(&a, &count) + if err != nil { + return 0, err + } + return count, nil + +} + +func checks(interval time.Duration) error { + if interval < time.Second { + return fmt.Errorf("interval can't be less than 1 second") + } + for { + c, err := countConns() + if err != nil { + return err + } + log.Printf("DB connections: %d", c) + time.Sleep(interval) + } +} diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 index 8932210..deb988d --- a/build.sh +++ b/build.sh @@ -3,7 +3,7 @@ set -e echo "Vetting, testing & building all Go binaries" -names=(paperlog get_secret slack) +names=(paperlog get_secret slack active_conn) for n in "${names[@]}" do