latest
This commit is contained in:
parent
92335ead98
commit
3aec504aa1
14
Makefile
14
Makefile
@ -9,16 +9,26 @@ BUILDARCH := $(shell uname -m)
|
|||||||
FN := fediverse-archive
|
FN := fediverse-archive
|
||||||
IMAGENAME := sneak/$(FN)
|
IMAGENAME := sneak/$(FN)
|
||||||
|
|
||||||
|
UNAME_S := $(shell uname -s)
|
||||||
|
|
||||||
GOLDFLAGS += -X main.Version=$(VERSION)
|
GOLDFLAGS += -X main.Version=$(VERSION)
|
||||||
GOLDFLAGS += -X main.Buildtime=$(BUILDTIME)
|
GOLDFLAGS += -X main.Buildtime=$(BUILDTIME)
|
||||||
GOLDFLAGS += -X main.Builduser=$(BUILDUSER)@$(BUILDHOST)
|
GOLDFLAGS += -X main.Builduser=$(BUILDUSER)@$(BUILDHOST)
|
||||||
GOLDFLAGS += -X main.Buildarch=$(BUILDARCH)
|
GOLDFLAGS += -X main.Buildarch=$(BUILDARCH)
|
||||||
GOFLAGS = -ldflags "-linkmode external -extldflags -static $(GOLDFLAGS)"
|
|
||||||
|
# osx can't statically link apparently?!
|
||||||
|
ifeq ($(UNAME_S),Darwin)
|
||||||
|
GOFLAGS := -ldflags "$(GOLDFLAGS)"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(UNAME_S),Darwin)
|
||||||
|
GOFLAGS = -ldflags "-linkmode external -extldflags -static $(GOLDFLAGS)"
|
||||||
|
endif
|
||||||
|
|
||||||
default: rundebug
|
default: rundebug
|
||||||
|
|
||||||
rundebug: build
|
rundebug: build
|
||||||
./$(FN) -debug
|
DEBUG=1 ./$(FN)
|
||||||
|
|
||||||
run: build
|
run: build
|
||||||
./$(FN)
|
./$(FN)
|
||||||
|
18
archiver.go
18
archiver.go
@ -1,31 +1,25 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "time"
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
//"github.com/bitly/go-simplejson"
|
|
||||||
)
|
|
||||||
|
|
||||||
type InstanceHostName string
|
type InstanceHostName string
|
||||||
|
|
||||||
type Archiver struct {
|
type TootArchiver struct {
|
||||||
locator *InstanceLocator
|
locator *InstanceLocator
|
||||||
instances map[InstanceHostName]*Instance
|
instances map[InstanceHostName]*Instance
|
||||||
startup *time.Time
|
startup *time.Time
|
||||||
ctx context.Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArchiver(ctx context.Context) *Archiver {
|
func NewTootArchiver() *TootArchiver {
|
||||||
a := new(Archiver)
|
a := new(TootArchiver)
|
||||||
a.ctx = ctx
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Archiver) Uptime() time.Duration {
|
func (a *TootArchiver) Uptime() time.Duration {
|
||||||
return time.Since(*a.startup)
|
return time.Since(*a.startup)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Archiver) RunForever() int {
|
func (a *TootArchiver) RunForever() int {
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
a.startup = &t
|
a.startup = &t
|
||||||
a.locator = NewInstanceLocator()
|
a.locator = NewInstanceLocator()
|
||||||
|
17
instance.go
17
instance.go
@ -1,17 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "encoding/json"
|
||||||
"encoding/json"
|
import "fmt"
|
||||||
"fmt"
|
import "net/http"
|
||||||
"github.com/rs/zerolog/log"
|
import "strings"
|
||||||
"net/http"
|
import "time"
|
||||||
"strings"
|
|
||||||
"time"
|
import "github.com/rs/zerolog/log"
|
||||||
)
|
|
||||||
|
|
||||||
const NodeInfoSchemaVersionTwoName = "http://nodeinfo.diaspora.software/ns/schema/2.0"
|
const NodeInfoSchemaVersionTwoName = "http://nodeinfo.diaspora.software/ns/schema/2.0"
|
||||||
|
|
||||||
const NODE_TIMEOUT = time.Second * 30
|
const NODE_TIMEOUT = time.Second * 10
|
||||||
|
|
||||||
type ServerImplementation int
|
type ServerImplementation int
|
||||||
|
|
||||||
|
69
locator.go
69
locator.go
@ -1,12 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "encoding/json"
|
||||||
"encoding/json"
|
import "fmt"
|
||||||
"github.com/rs/zerolog/log"
|
import "net/http"
|
||||||
"net/http"
|
import "sync"
|
||||||
"sync"
|
import "time"
|
||||||
"time"
|
|
||||||
)
|
import "github.com/rs/zerolog/log"
|
||||||
|
|
||||||
const mastodonIndexUrl = "https://instances.social/list.json?q%5Busers%5D=&q%5Bsearch%5D=&strict=false"
|
const mastodonIndexUrl = "https://instances.social/list.json?q%5Busers%5D=&q%5Bsearch%5D=&strict=false"
|
||||||
|
|
||||||
@ -104,43 +104,64 @@ func (i *InstanceLocator) addInstance(hostname string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *InstanceLocator) Locate() {
|
func (i *InstanceLocator) Locate() {
|
||||||
log.Debug().Str("lastmastodonupdate", i.mastodonIndexLastRefresh.Format(time.RFC3339)).Send()
|
log.Debug().
|
||||||
log.Debug().Str("lastpleromaupdate", i.pleromaIndexLastRefresh.Format(time.RFC3339)).Send()
|
Str("lastmastodonupdate", i.mastodonIndexLastRefresh.Format(time.RFC3339)).
|
||||||
|
Send()
|
||||||
|
|
||||||
|
log.Debug().
|
||||||
|
Str("lastpleromaupdate", i.pleromaIndexLastRefresh.Format(time.RFC3339)).
|
||||||
|
Send()
|
||||||
|
|
||||||
i.locateMastodon()
|
i.locateMastodon()
|
||||||
|
|
||||||
i.locatePleroma()
|
i.locatePleroma()
|
||||||
|
|
||||||
time.Sleep(120 * time.Second)
|
time.Sleep(120 * time.Second)
|
||||||
|
|
||||||
i.instanceReport()
|
i.instanceReport()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *InstanceLocator) instanceReport() {
|
type InstanceLocatorReport struct {
|
||||||
var upInstances int = 0
|
up uint
|
||||||
var identifiedInstances int = 0
|
identified uint
|
||||||
var totalInstances int = 0
|
total uint
|
||||||
|
}
|
||||||
|
|
||||||
totalInstances = len(i.instances)
|
func (r *InstanceLocatorReport) String() string {
|
||||||
|
return fmt.Sprintf("up=%d identified=%d total=%d", r.up, r.identified, r.total)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InstanceLocator) NumInstances() uint {
|
||||||
|
return i.instanceReport().total
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *InstanceLocator) instanceReport() *InstanceLocatorReport {
|
||||||
|
r := new(InstanceLocatorReport)
|
||||||
|
|
||||||
|
r.total = uint(len(i.instances))
|
||||||
|
|
||||||
for _, elem := range i.instances {
|
for _, elem := range i.instances {
|
||||||
if elem.identified == true {
|
if elem.identified == true {
|
||||||
identifiedInstances = identifiedInstances + 1
|
r.identified = r.identified + 1
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for _, elem := range i.instances {
|
|
||||||
if elem.up == true {
|
if elem.up == true {
|
||||||
upInstances = upInstances + 1
|
r.up = r.up + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().
|
log.Debug().
|
||||||
Int("up", upInstances).
|
Uint("up", r.up).
|
||||||
Int("total", totalInstances).
|
Uint("total", r.total).
|
||||||
Int("identified", identifiedInstances).
|
Uint("identified", r.identified).
|
||||||
Msg("instance report")
|
Msg("instance report")
|
||||||
|
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *InstanceLocator) locateMastodon() {
|
func (i *InstanceLocator) locateMastodon() {
|
||||||
var netClient = &http.Client{
|
var netClient = &http.Client{
|
||||||
Timeout: time.Second * 20,
|
Timeout: NODE_TIMEOUT,
|
||||||
}
|
}
|
||||||
resp, err := netClient.Get(mastodonIndexUrl)
|
resp, err := netClient.Get(mastodonIndexUrl)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
@ -168,7 +189,7 @@ func (i *InstanceLocator) locateMastodon() {
|
|||||||
|
|
||||||
func (i *InstanceLocator) locatePleroma() {
|
func (i *InstanceLocator) locatePleroma() {
|
||||||
var netClient = &http.Client{
|
var netClient = &http.Client{
|
||||||
Timeout: time.Second * 20,
|
Timeout: NODE_TIMEOUT,
|
||||||
}
|
}
|
||||||
resp, err := netClient.Get(pleromaIndexUrl)
|
resp, err := netClient.Get(pleromaIndexUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
43
main.go
43
main.go
@ -1,13 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "os"
|
||||||
"context"
|
import "sync"
|
||||||
"flag"
|
|
||||||
"github.com/rs/zerolog"
|
import "github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
import "github.com/rs/zerolog/log"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
import "golang.org/x/crypto/ssh/terminal"
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
os.Exit(app())
|
os.Exit(app())
|
||||||
@ -19,16 +17,33 @@ func app() int {
|
|||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
}
|
}
|
||||||
|
|
||||||
debug := flag.Bool("debug", false, "sets log level to debug")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
identify()
|
identify()
|
||||||
|
|
||||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||||
if *debug {
|
if os.Getenv("DEBUG") != "" {
|
||||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
mainContext := context.Background()
|
archiver := NewTootArchiver()
|
||||||
return NewArchiver(mainContext).RunForever()
|
|
||||||
|
api := new(TootArchiverAPIServer)
|
||||||
|
api.archiver = archiver
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
// start api webserver goroutine
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
api.Serve()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
archiver.RunForever()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
82
webserver.go
Normal file
82
webserver.go
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "os"
|
||||||
|
import "time"
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
import "github.com/rs/zerolog/log"
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
import "github.com/dn365/gin-zerolog"
|
||||||
|
|
||||||
|
type TootArchiverAPIServer struct {
|
||||||
|
archiver *TootArchiver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *TootArchiverAPIServer) Serve() {
|
||||||
|
if a.archiver == nil {
|
||||||
|
panic("must have archiver from which to serve stats")
|
||||||
|
}
|
||||||
|
s := a.getServer()
|
||||||
|
err := s.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Msg("webserver failure: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *TootArchiverAPIServer) getRouter() *gin.Engine {
|
||||||
|
if os.Getenv("DEBUG") == "" {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty router
|
||||||
|
r := gin.New()
|
||||||
|
|
||||||
|
// wrap panics:
|
||||||
|
r.Use(gin.Recovery())
|
||||||
|
|
||||||
|
// attach logger middleware
|
||||||
|
r.Use(ginzerolog.Logger("gin"))
|
||||||
|
|
||||||
|
r.GET("/.well-known/healthcheck.json", func(c *gin.Context) {
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
"status": "ok",
|
||||||
|
"now": time.Now().UTC().Format(time.RFC3339),
|
||||||
|
"uptime": a.archiver.Uptime().String(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
r.GET("/", func(c *gin.Context) {
|
||||||
|
c.JSON(200, gin.H{
|
||||||
|
// FIXME add more stuff here
|
||||||
|
"status": "ok",
|
||||||
|
"now": time.Now().UTC().Format(time.RFC3339),
|
||||||
|
"uptime": a.archiver.Uptime().String(),
|
||||||
|
"instances": a.archiver.locator.NumInstances(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// FIXME add more status routes here
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *TootArchiverAPIServer) getServer() *http.Server {
|
||||||
|
r := a.getRouter()
|
||||||
|
|
||||||
|
port := "8080"
|
||||||
|
if os.Getenv("PORT") != "" {
|
||||||
|
port = os.Getenv("PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Str("port", port).Msg("starting webserver")
|
||||||
|
|
||||||
|
s := &http.Server{
|
||||||
|
Addr: fmt.Sprintf(":%s", port),
|
||||||
|
Handler: r,
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
MaxHeaderBytes: 1 << 20,
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user