Initial commit

incorrect_closing_investigation
Evgeny Kovalev 2 years ago
parent ac53b8c101
commit 9ef34d9294
  1. 9
      .gitignore
  2. 4
      config.json
  3. 7
      go.mod
  4. 61
      internal/config/config.go
  5. 17
      internal/player/player.go
  6. 38
      internal/server/server.go
  7. 107
      internal/utils/jsonlog.go
  8. 52
      main.go

9
.gitignore vendored

@ -1,3 +1,4 @@
<<<<<<< HEAD
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
@ -360,4 +361,10 @@ MigrationBackup/
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd
# Project Specific
vendor/
shipsgs
go.sum
runlog.log

@ -0,0 +1,4 @@
{
"Address": ":8080",
"AdminSecret": "netadmin"
}

@ -0,0 +1,7 @@
module daydev.org/shipsgs
go 1.17
require github.com/xlab/closer v1.1.0
require github.com/cristalhq/aconfig v0.18.3 // indirect

@ -0,0 +1,61 @@
package config
import (
"encoding/json"
"io/ioutil"
"log"
"os"
)
const ConfigPath string = "config.json"
type S_Config struct {
Address string `json:"Address"`
AdminSecret string `json:"AdminSecret"`
}
var Config S_Config
func initialize() error {
configExists, err := os.Open(ConfigPath)
if err != nil {
log.Println("management.initialize: new deployment: building config")
configNew, err := os.OpenFile("config.json", os.O_CREATE|os.O_WRONLY, 0644)
if err == nil {
Config.Address = ":8080"
Config.AdminSecret = "netadmin"
configByte, err := json.MarshalIndent(Config, "", " ")
if err != nil {
log.Fatal("config.initialize: could not Marshall Settings: ", err)
return err
}
configNew.Write(configByte)
} else {
log.Fatal("config.initialize: could not create new config.json file: ", err)
return err
}
defer configNew.Close()
} else {
configByte, err := ioutil.ReadAll(configExists)
if err != nil {
log.Fatal("config.initialize: could not read config: ", err)
return err
}
json.Unmarshal(configByte, &Config)
defer configExists.Close()
}
return nil
}
func ReadConfig() {
// If doesnt exist, write default config
initialize()
}

@ -0,0 +1,17 @@
package player
type Player struct {
Name string `json:"Name"`
Password string `json:"Password"`
AuthString string `json:"AuthString"`
Level string `json:"Level"` // hidden from user, for balancing purposes
Kills int `json:"Kills"`
Killed int `json:"Killed"`
Won int `json:"Won"`
Lost int `json:"Lost"`
WinRate int `json:"WinRate"`
}

@ -0,0 +1,38 @@
package server
import (
"context"
"fmt"
"log"
"net/http"
)
func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "index")
}
func wsEndpoint(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello")
}
func setupRoutes() {
http.HandleFunc("/", index)
http.HandleFunc("/ws", wsEndpoint)
}
func SetupAndRun(port string, sighup *chan bool) {
setupRoutes()
srv := &http.Server{Addr: port}
go func() {
<-*sighup
log.Println("Shutting down the webserver")
srv.Shutdown(context.TODO())
}()
log.Fatal(srv.ListenAndServe())
}

@ -0,0 +1,107 @@
package utils
import (
"encoding/json"
"io"
"os"
"runtime/debug"
"sync"
"time"
)
// Define a Level type to represent the severity level for a log entry.
type Level int8
// Initialize constants which represent a specific severity level. We use the iota
// keyword as a shortcut to
const (
LevelInfo Level = iota
LevelError
LevelFatal
LevelOff
)
// assign successive integer values to the constants.
// Has the value 0. // Has the value 1. // Has the value 2. // Has the value 3.
// Return a human-friendly string for the severity level.
func (l Level) String() string {
switch l {
case LevelInfo:
return "INFO"
case LevelError:
return "ERROR"
case LevelFatal:
return "FATAL"
default:
return ""
}
}
// Define a custom Logger type. This holds the output destination that the log entries // will be written to, the minimum severity level that log entries will be written for, // plus a mutex for coordinating the writes.
type Logger struct {
out io.Writer
minLevel Level
mu sync.Mutex
}
// Return a new Logger instance which writes log entries at or above a minimum severity // level to a specific output destination.
func New(out io.Writer, minLevel Level) *Logger {
return &Logger{out: out,
minLevel: minLevel}
}
// Declare some helper methods for writing log entries at the different levels. Notice // that these all accept a map as the second parameter which can contain any arbitrary // 'properties' that you want to appear in the log entry.
func (l *Logger) PrintInfo(message string, properties map[string]string) {
l.print(LevelInfo, message, properties)
}
func (l *Logger) PrintError(err error, properties map[string]string) {
l.print(LevelError, err.Error(), properties)
}
func (l *Logger) PrintFatal(err error, properties map[string]string) {
l.print(LevelFatal, err.Error(), properties)
os.Exit(1) // For entries at the FATAL level, we also terminate the application.
}
// Print is an internal method for writing the log entry.
func (l *Logger) print(level Level, message string, properties map[string]string) (int, error) { // If the severity level of the log entry is below the minimum severity for the
// logger, then return with no further action.
if level < l.minLevel {
return 0, nil
}
// Declare an anonymous struct holding the data for the log entry.
aux := struct {
Level string `json:"level"`
Time string `json:"time"`
Message string `json:"message"`
Properties map[string]string `json:"properties,omitempty"`
Trace string `json:"trace,omitempty"`
}{
Level: level.String(),
Time: time.Now().UTC().Format(time.RFC3339), Message: message,
Properties: properties,
}
// Include a stack trace for entries at the ERROR and FATAL levels.
if level >= LevelError {
aux.Trace = string(debug.Stack())
}
// Declare a line variable for holding the actual log entry text.
var line []byte
// Marshal the anonymous struct to JSON and store it in the line variable. If there // was a problem creating the JSON, set the contents of the log entry to be that
// plain-text error message instead.
line, err := json.Marshal(aux)
if err != nil {
line = []byte(LevelError.String() + ": unable to marshal log message: " + err.Error())
}
// Lock the mutex so that no two writes to the output destination cannot happen // concurrently. If we don't do this, it's possible that the text for two or more // log entries will be intermingled in the output.
l.mu.Lock()
defer l.mu.Unlock()
// Write the log entry followed by a newline.
return l.out.Write(append(line, '\n'))
}
// We also implement a Write() method on our Logger type so that it satisfies the
// io.Writer interface. This writes a log entry at the ERROR level with no additional // properties.
func (l *Logger) Write(message []byte) (n int, err error) {
return l.print(LevelError, string(message), nil)
}

@ -0,0 +1,52 @@
package main
import (
"fmt"
"log"
"os"
"daydev.org/shipsgs/internal/config"
"daydev.org/shipsgs/internal/server"
"daydev.org/shipsgs/internal/utils"
"github.com/xlab/closer"
)
var Logger *utils.Logger
var ch_sighup *chan bool
func main() {
logFile, err := os.OpenFile("runlog.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println(err)
} else {
log.SetOutput(logFile)
}
defer logFile.Close()
closer.Bind(cleanup)
sighup := make(chan bool)
ch_sighup = &sighup
//If debug - fill Stdout too - LOG to use?
//Logger = utils.New(os.Stdout, utils.LevelInfo)
config.ReadConfig()
log.Println("Starting Healthy")
//closer.Hold()
server.SetupAndRun(":8080", ch_sighup)
}
func cleanup() {
fmt.Println("Shutting down ")
*ch_sighup <- true
Logger.PrintInfo("main", map[string]string{
"Info": "Closing Application Normally",
})
}
Loading…
Cancel
Save