baseline
This commit is contained in:
commit
addbf6dbc5
|
@ -0,0 +1,73 @@
|
|||
You can stream and read files to a sentry DSN glitchtip or sentry itself I was fed up with how brittle sentry-cli was so I made this.
|
||||
|
||||
I might get around to making a whole CI/CD process for this which will upload the executables properly at some point and make this public.
|
||||
# Go Glitch
|
||||
|
||||
Go Glitch is a command-line utility that reads log messages from a file or stdin and sends them to Glitchtip, a self-hosted Sentry-compatible error tracking system.
|
||||
|
||||
## Installation
|
||||
|
||||
To install the binary locally, you can use the provided installation script. Run the following command in your terminal:
|
||||
|
||||
```sh
|
||||
curl -sSL https://git.nixc.us/Nixius/go-glitch/raw/branch/master/install.sh | bash
|
||||
```
|
||||
|
||||
This will download and install the Go Glitch binary to your local machine.
|
||||
|
||||
## Usage
|
||||
|
||||
You can use Go Glitch by specifying a log file as an argument or by piping input to it.
|
||||
|
||||
### Using a Log File
|
||||
|
||||
```sh
|
||||
go-glitch /path/to/logfile
|
||||
```
|
||||
|
||||
### Using Piped Input
|
||||
|
||||
```sh
|
||||
cat /path/to/logfile | go-glitch
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Go Glitch requires the `GLITCHTIP_DSN` environment variable to be set with your Glitchtip DSN. You can set this environment variable in your shell environment, Dockerfile, or `docker-compose.yml` file.
|
||||
|
||||
### Shell Environment
|
||||
|
||||
Add the following line to your `.zshrc` or `.bashrc` file:
|
||||
|
||||
```sh
|
||||
export GLITCHTIP_DSN="your-glitchtip-dsn"
|
||||
```
|
||||
|
||||
After adding the line, reload your shell configuration:
|
||||
|
||||
```sh
|
||||
source ~/.zshrc # for zsh users
|
||||
source ~/.bashrc # for bash users
|
||||
```
|
||||
|
||||
### Dockerfile
|
||||
|
||||
If you are using a Docker container, add the environment variable in your `Dockerfile`:
|
||||
|
||||
```Dockerfile
|
||||
ENV GLITCHTIP_DSN=your-glitchtip-dsn
|
||||
```
|
||||
|
||||
### docker-compose.yml
|
||||
|
||||
If you are using Docker Compose, add the environment variable in your `docker-compose.yml` file:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
go-glitch:
|
||||
image: your-docker-image
|
||||
environment:
|
||||
- GLITCHTIP_DSN=your-glitchtip-dsn
|
||||
```
|
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
|
||||
ARCHITECTURES=("linux/amd64" "linux/arm64" "darwin/amd64" "darwin/arm64" "windows/amd64")
|
||||
PROJECT_NAME=$(basename "$(pwd)")
|
||||
|
||||
prepare_build() {
|
||||
mkdir -p dist build_logs
|
||||
if [ ! -f go.mod ]; then
|
||||
go mod init "$PROJECT_NAME"
|
||||
fi
|
||||
go mod tidy
|
||||
}
|
||||
|
||||
build_binary() {
|
||||
local os=$1
|
||||
local arch=$2
|
||||
local output="dist/${PROJECT_NAME}_${os}_${arch}"
|
||||
env GOOS=$os GOARCH=$arch go build -o $output . &> "build_logs/${os}_${arch}.log"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Build failed for $os/$arch" >> "build_logs/error.log"
|
||||
else
|
||||
echo "Build succeeded for $os/$arch"
|
||||
fi
|
||||
if [ "$os" == "linux" ]; then
|
||||
env GOOS=$os GOARCH=$arch CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o "${output}_static" . &> "build_logs/${os}_${arch}_static.log"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Static build failed for $os/$arch" >> "build_logs/error.log"
|
||||
else
|
||||
echo "Static build succeeded for $os/$arch"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
prepare_build
|
||||
for arch in "${ARCHITECTURES[@]}"; do
|
||||
IFS="/" read -r os arch <<< "$arch"
|
||||
build_binary $os $arch
|
||||
done
|
||||
echo "Build process completed."
|
||||
}
|
||||
|
||||
main
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
|
@ -0,0 +1,7 @@
|
|||
Build failed for linux/amd64
|
||||
Static build failed for linux/amd64
|
||||
Build failed for linux/arm64
|
||||
Static build failed for linux/arm64
|
||||
Build failed for darwin/amd64
|
||||
Build failed for darwin/arm64
|
||||
Build failed for windows/amd64
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
|
@ -0,0 +1,2 @@
|
|||
# inotify-glitch
|
||||
./main.go:56:17: syntax error: cannot use _, logFile := listFiles(logFiles) as value
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,13 @@
|
|||
module inotify-glitch
|
||||
|
||||
go 1.21.1
|
||||
|
||||
require (
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/getsentry/sentry-go v0.28.1
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
)
|
|
@ -0,0 +1,24 @@
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/getsentry/sentry-go v0.28.1 h1:zzaSm/vHmGllRM6Tpx1492r0YDzauArdBfkJRtY6P5k=
|
||||
github.com/getsentry/sentry-go v0.28.1/go.mod h1:1fQZ+7l7eeJ3wYi82q5Hg8GqAPgefRq+FP/QhafYVgg=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -0,0 +1,34 @@
|
|||
#!/bin/bash
|
||||
|
||||
INSTALL_DIR="/usr/local/bin"
|
||||
BINARY_NAME="go-glitch"
|
||||
BASE_URL="https://git.nixc.us/Nixius/go-glitch/raw/branch/master/dist"
|
||||
|
||||
|
||||
# Supported architectures
|
||||
ARCHITECTURES=("linux/amd64" "linux/arm64" "linux/arm/v7" "darwin/amd64" "darwin/arm64")
|
||||
|
||||
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
||||
ARCH="$(uname -m)"
|
||||
|
||||
case $ARCH in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
arm64 | aarch64) ARCH="arm64" ;;
|
||||
arm*) ARCH="arm/v7" ;;
|
||||
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||
esac
|
||||
|
||||
BINARY_URL="${BASE_URL}/${BINARY_NAME}_${OS}_${ARCH}"
|
||||
|
||||
echo "Downloading and installing $BINARY_NAME from $BINARY_URL..."
|
||||
|
||||
# Check if we have write permission to the install directory
|
||||
if [ -w "${INSTALL_DIR}" ]; then
|
||||
curl -sSL "$BINARY_URL" -o "${INSTALL_DIR}/${BINARY_NAME}"
|
||||
chmod +x "${INSTALL_DIR}/${BINARY_NAME}"
|
||||
else
|
||||
sudo curl -sSL "$BINARY_URL" -o "${INSTALL_DIR}/${BINARY_NAME}"
|
||||
sudo chmod +x "${INSTALL_DIR}/${BINARY_NAME}"
|
||||
fi
|
||||
|
||||
echo "Installed $BINARY_NAME to $INSTALL_DIR"
|
|
@ -0,0 +1,139 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/getsentry/sentry-go"
|
||||
)
|
||||
|
||||
var debug bool
|
||||
|
||||
func main() {
|
||||
// Check if debug mode is enabled
|
||||
if os.Getenv("DEBUG") == "true" {
|
||||
debug = true
|
||||
}
|
||||
|
||||
// Get the DSN from the environment
|
||||
dsn := os.Getenv("GLITCHTIP_DSN")
|
||||
if dsn == "" {
|
||||
fmt.Fprintf(os.Stderr, "Error: GLITCHTIP_DSN environment variable is not set.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Initialize Sentry
|
||||
err := sentry.Init(sentry.ClientOptions{
|
||||
Dsn: dsn,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error initializing GlitchTip: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer sentry.Flush(2 * time.Second)
|
||||
|
||||
// Get the log files from the environment
|
||||
logFilesEnv := os.Getenv("LOG_FILES")
|
||||
if logFilesEnv == "" {
|
||||
fmt.Fprintf(os.Stderr, "Error: LOG_FILES environment variable is not set.\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
logFiles := strings.Split(logFilesEnv, ",")
|
||||
|
||||
// Create a new file watcher
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating watcher: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer watcher.Close()
|
||||
|
||||
// Add log files to the watcher
|
||||
for _, logFile := listFiles(logFiles) {
|
||||
if debug {
|
||||
fmt.Printf("Adding file to watcher: %s\n", logFile)
|
||||
}
|
||||
err = watcher.Add(logFile)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error adding file to watcher: %s\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Watch for file changes
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||
if debug {
|
||||
fmt.Printf("File modified: %s\n", event.Name)
|
||||
}
|
||||
processLogFile(event.Name)
|
||||
}
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Watcher error: %s\n", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Block forever
|
||||
select {}
|
||||
}
|
||||
|
||||
func processLogFile(filePath string) {
|
||||
if debug {
|
||||
fmt.Printf("Processing log file: %s\n", filePath)
|
||||
}
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error opening file: %s\n", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if debug {
|
||||
fmt.Printf("Read line: %s\n", line)
|
||||
}
|
||||
if strings.Contains(strings.ToLower(line), "error") {
|
||||
sendToSentry(line)
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error reading file: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func sendToSentry(message string) {
|
||||
if debug {
|
||||
fmt.Printf("Sending message to GlitchTip: %s\n", message)
|
||||
}
|
||||
sentry.CaptureMessage(message)
|
||||
}
|
||||
|
||||
// Utility function to list log files
|
||||
func listFiles(logFiles []string) []string {
|
||||
var validFiles []string
|
||||
for _, file := range logFiles {
|
||||
if _, err := os.Stat(file); err == nil {
|
||||
validFiles = append(validFiles, file)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Log file does not exist: %s\n", file)
|
||||
}
|
||||
}
|
||||
return validFiles
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#!/bin/bash
|
||||
|
||||
start_time=$(date +%s)
|
||||
|
||||
# Set environment variables
|
||||
export GLITCHTIP_DSN="https://d272afa8b4bd4308b3cf99ee74e1dc97@glitch.nixc.us/2"
|
||||
export LOG_FILES="test_log_1.log,test_log_2.log"
|
||||
|
||||
echo "Using Glitchtip DSN: $GLITCHTIP_DSN"
|
||||
echo "Monitoring log files: $LOG_FILES"
|
||||
|
||||
# Create test log files
|
||||
echo "Creating test log files..."
|
||||
echo "Initial log content" > test_log_1.log
|
||||
echo "Initial log content" > test_log_2.log
|
||||
|
||||
# Run the Go program in the background
|
||||
echo "Starting the Go program..."
|
||||
./dist/inotify-glitch_darwin_arm64 &
|
||||
|
||||
# Capture the PID of the Go program
|
||||
GO_PID=$!
|
||||
|
||||
# Give the program a moment to start
|
||||
sleep 2
|
||||
|
||||
# Append a line with an error to one of the log files
|
||||
echo "Appending error line to test_log_1.log..."
|
||||
echo "This is an error line" >> test_log_1.log
|
||||
|
||||
# Give the program some time to process the change
|
||||
sleep 2
|
||||
|
||||
# Check if the Go program detected the change (you can enhance this section with more specific checks)
|
||||
echo "Check the logs to verify the program detected the error line."
|
||||
|
||||
# Capture Go program logs for debugging
|
||||
ps -p $GO_PID > /dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "The Go program is running."
|
||||
else
|
||||
echo "The Go program has terminated unexpectedly."
|
||||
fi
|
||||
|
||||
# Cleanup: kill the Go program
|
||||
echo "Terminating the Go program..."
|
||||
kill $GO_PID
|
||||
|
||||
# Optionally: Remove test log files
|
||||
echo "Removing test log files..."
|
||||
rm test_log_1.log test_log_2.log
|
||||
|
||||
end_time=$(date +%s)
|
||||
execution_time=$((end_time - start_time))
|
||||
|
||||
# Fix for macOS date command
|
||||
execution_time_formatted=$(printf '%02d:%02d:%02d' $((execution_time/3600)) $((execution_time%3600/60)) $((execution_time%60)))
|
||||
|
||||
echo "Execution time: $execution_time_formatted"
|
Loading…
Reference in New Issue