Skip to content

Commit

Permalink
Initial code commit
Browse files Browse the repository at this point in the history
  • Loading branch information
danielunderwood committed Feb 26, 2022
1 parent d753a03 commit 28f106b
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@

# Dependency directories (remove the comment below to include it)
# vendor/
result
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,36 @@
# log2http
Matches log lines to trigger HTTP requests

Matches log lines to trigger HTTP requests. A super hacky alternative to ELK or loki.

## Supported HTTP Targets
- Discord

## Usage

### Binary

```shell
$ log2http -file FILENAME -expression "^[Rr]egex$" -url https://discordapp.com/...
$ # Or supply URL via environment
$ export URL="https://discordapp.com/..."
$ log2http -file FILENAME -expression "^[Rr]egex$
```
## Development
The development environment is currently set up with nix flakes.
### Development Environment
```shell
$ nix develop
```
### Build Binary
```shell
$ nix build
```
### Build and Run Binary
```shell
$ nix run .#log2http -- -file filename
```
26 changes: 26 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
description = "A simple Go package";

# Nixpkgs / NixOS version to use.
inputs.nixpkgs.url = "nixpkgs/nixos-21.11";

outputs = { self, nixpkgs }:
let

# Generate a user-friendly version number.
version = builtins.substring 0 8 self.lastModifiedDate;

# System types to support.
supportedSystems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];

# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;

# Nixpkgs instantiated for supported system types.
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });

in
{

# Provide some binary packages for selected system types.
packages = forAllSystems (system:
let
pkgs = nixpkgsFor.${system};
in
{
log2http = pkgs.buildGoModule {
pname = "log2http";
inherit version;
# In 'nix develop', we don't need a copy of the source tree
# in the Nix store.
src = ./.;

# This hash locks the dependencies of this package. It is
# necessary because of how Go requires network access to resolve
# VCS. See https://www.tweag.io/blog/2021-03-04-gomod2nix/ for
# details. Normally one can build with a fake sha256 and rely on native Go
# mechanisms to tell you what the hash should be or determine what
# it should be "out-of-band" with other tooling (eg. gomod2nix).
# To begin with it is recommended to set this, but one must
# remeber to bump this hash when your dependencies change.
# vendorSha256 = pkgs.lib.fakeSha256;

vendorSha256 = "sha256-wGEAgmClq+RNhCn7TIcIB5N4hf8uK6hu4KRXqTeooY4=";
};
});

# The default package for 'nix build'. This makes sense if the
# flake provides only one package or there is a clear "main"
# package.
defaultPackage = forAllSystems (system: self.packages.${system}.log2http);

devShell = forAllSystems (system:
let pkgs = nixpkgsFor.${system};
in pkgs.mkShell {
buildInputs = with pkgs; [
go
gopls
goimports
go-tools
];
});

};
}
10 changes: 10 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/danielunderwood/log2http

go 1.16

require (
github.com/hpcloud/tail v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 // indirect
gopkg.in/fsnotify.v1 v1.4.7 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
75 changes: 75 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"regexp"

"github.com/hpcloud/tail"
)

type DiscordMessage struct {
Content string `json:"content"`
}

func main() {
var file, expression, url string
flag.StringVar(&file, "file", "", "File to read. Required")
flag.StringVar(&url, "url", "", "URL to POST to. Must be supplied or in environment")
flag.StringVar(&expression, "regexp", ".*", "Expression to match, defaults to `.*`")

flag.Parse()

if len(file) == 0 {
fmt.Println("Usage: -file FILENAME -regexp EXPRESSION")
os.Exit(1)
}
if len(url) == 0 {
url = os.Getenv("URL")
}
if len(url) == 0 {
fmt.Println("ERROR: URL must be supplied as -url or in URL environment")
os.Exit(1)
}

t, err := tail.TailFile(file, tail.Config{Follow: true})
if err != nil {
panic(err)
}
for line := range t.Lines {
matched, err := regexp.MatchString(expression, line.Text)
if err != nil {
fmt.Println("ERROR", err)
continue
}
if matched {
fmt.Println("Matched", line.Text)
message := DiscordMessage{Content: fmt.Sprintf("[%s] matched line: %s", file, line.Text)}
body, err := json.Marshal(message)
if err != nil {
fmt.Print("Failed to marshal JSON", err)
continue
}
// TODO This should be an option
resp, err := http.Post(
url,
"application/json",
bytes.NewReader(body),
)
defer resp.Body.Close()
if err != nil {
fmt.Println("ERROR", err)
continue
}
if resp.StatusCode != 204 {
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("Request failed", resp.StatusCode, string(body))
}
}
}
}

0 comments on commit 28f106b

Please sign in to comment.