pings record to sqlite
This commit is contained in:
Binary file not shown.
+140
-5
@@ -2,12 +2,17 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.bel.blue/bel/with"
|
"gitea.bel.blue/bel/with"
|
||||||
"github.com/digineo/go-ping"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -16,18 +21,148 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type S struct {
|
||||||
|
*sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
func run(ctx context.Context) error {
|
func run(ctx context.Context) error {
|
||||||
|
return with.Sqlite(ctx, "/tmp/pinger.db", func(db *sql.DB) error {
|
||||||
|
s := S{
|
||||||
|
DB: db,
|
||||||
|
}
|
||||||
|
if err := s.init(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
defer wg.Wait()
|
||||||
|
for _, foo := range []func(context.Context) error{
|
||||||
|
s.pingAndRecord,
|
||||||
|
s.listen,
|
||||||
|
} {
|
||||||
|
foo := foo
|
||||||
|
wg.Go(func() {
|
||||||
|
if err := foo(ctx); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ctx.Err()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s S) init(ctx context.Context) error {
|
||||||
|
for _, q := range []string{
|
||||||
|
`CREATE TABLE IF NOT EXISTS "pinger_to" (
|
||||||
|
id NUMBER NOT NULL UNIQUE
|
||||||
|
, addr TEXT NOT NULL UNIQUE
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE IF NOT EXISTS "pinger_pings" (
|
||||||
|
start TIMESTAMP NOT NULL
|
||||||
|
, ms NUMBER NOT NULL
|
||||||
|
, ok BOOLEAN NOT NULL DEFAULT false
|
||||||
|
, to_id NUMBER
|
||||||
|
, FOREIGN KEY (to_id) REFERENCES "pinger_to"(id)
|
||||||
|
)`,
|
||||||
|
//`ALTER TABLE "pinger_pings" SET UNLOGGED`,
|
||||||
|
} {
|
||||||
|
if _, err := s.ExecContext(ctx, q); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (S) listen(ctx context.Context) error {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s S) pingAndRecord(ctx context.Context) error {
|
||||||
|
ctx, can := context.WithCancel(ctx)
|
||||||
|
defer can()
|
||||||
|
|
||||||
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)
|
||||||
|
target := fs.String("t", "google.com", "target")
|
||||||
|
port := fs.String("p", "80", "target port")
|
||||||
|
interval := fs.Duration("i", time.Second, "between conns")
|
||||||
if err := fs.Parse(os.Args[1:]); err != nil {
|
if err := fs.Parse(os.Args[1:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pinger, err := ping.New("", "::")
|
addr := fmt.Sprintf("%s:%s", *target, *port)
|
||||||
if err != nil {
|
if _, err := s.ExecContext(ctx, `
|
||||||
|
INSERT INTO "pinger_to" (id, addr)
|
||||||
|
VALUES ($1, $2)
|
||||||
|
ON CONFLICT (addr) DO NOTHING
|
||||||
|
`, rand.Int(), addr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer pinger.Close()
|
|
||||||
|
|
||||||
log.Fatal("RUN")
|
var toId int
|
||||||
|
if row := s.QueryRowContext(ctx, `
|
||||||
|
SELECT id
|
||||||
|
FROM "pinger_to"
|
||||||
|
WHERE addr=$1
|
||||||
|
`, addr); row.Err() != nil {
|
||||||
|
return row.Err()
|
||||||
|
} else if err := row.Scan(&toId); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type record struct {
|
||||||
|
start time.Time
|
||||||
|
ms time.Duration
|
||||||
|
ok bool
|
||||||
|
}
|
||||||
|
records := make(chan record, 100)
|
||||||
|
defer close(records)
|
||||||
|
go func() {
|
||||||
|
for record := range records {
|
||||||
|
if _, err := s.ExecContext(ctx, `
|
||||||
|
INSERT INTO "pinger_pings"
|
||||||
|
(start, ms, ok, to_id)
|
||||||
|
VALUES
|
||||||
|
($1, $2, $3, $4)
|
||||||
|
`, record.start, record.ms.Milliseconds(), record.ok, toId); err != nil {
|
||||||
|
log.Println("!", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
c := time.NewTicker(*interval)
|
||||||
|
go func() {
|
||||||
|
<-ctx.Done()
|
||||||
|
c.Stop()
|
||||||
|
}()
|
||||||
|
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
Timeout: time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c.C:
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func() {
|
||||||
|
ctx, can := context.WithTimeout(ctx, *interval)
|
||||||
|
defer can()
|
||||||
|
start := time.Now()
|
||||||
|
conn, err := dialer.DialContext(ctx, "tcp", addr)
|
||||||
|
select {
|
||||||
|
case records <- record{
|
||||||
|
start: start,
|
||||||
|
ms: time.Since(start),
|
||||||
|
ok: err == nil,
|
||||||
|
}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e // indirect
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect
|
||||||
golang.org/x/net v0.43.0 // indirect
|
golang.org/x/net v0.43.0 // indirect
|
||||||
golang.org/x/sys v0.43.0 // indirect
|
golang.org/x/sys v0.43.0 // indirect
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOF
|
|||||||
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e h1:nt2877sKfojlHCTOBXbpWjBkuWKritFaGIfgQwbQUls=
|
||||||
|
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e/go.mod h1:B4+Kq1u5FlULTjFSM707Q6e/cOHFv0z/6QRoxubDIQ8=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY=
|
||||||
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||||
|
|||||||
Reference in New Issue
Block a user