import template code
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
*~
|
||||
path.go
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"helmet/pkg/client"
|
||||
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
const (
|
||||
configFilename = "minilbd.yaml"
|
||||
)
|
||||
|
||||
var (
|
||||
buildVersion = "NONE"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
Port uint32 `json:"port" yaml:"port"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
Username string `json:"username" yaml:"username"`
|
||||
Password string `json:"password" yaml:"password"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Service Service `json:"service" yaml:"service"`
|
||||
Auths []Auth `json:"auths" yaml:"auths"`
|
||||
Hostname string `json:"hostname" yaml:"hostname"`
|
||||
LogPath string `json:"logfile" yaml:"logfile"`
|
||||
RunPath string `json:"runfile" yaml:"runfile"`
|
||||
AsDaemon bool `json:"asDaemon" yaml:"asDaemon"`
|
||||
}
|
||||
|
||||
func NewConfig() (*Config, error) {
|
||||
conf := &Config{
|
||||
Service: Service{
|
||||
Port: client.DefaultServicePort,
|
||||
},
|
||||
AsDaemon: false,
|
||||
}
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return conf, err
|
||||
}
|
||||
conf.Hostname = hostname
|
||||
exeName := filepath.Base(os.Args[0])
|
||||
conf.LogPath = filepath.Join(logdirPath, fmt.Sprintf("%s.log", exeName))
|
||||
conf.RunPath = filepath.Join(rundirPath, fmt.Sprintf("%s.pid", exeName))
|
||||
return conf, err
|
||||
}
|
||||
|
||||
func (conf *Config) Read() error {
|
||||
var err error
|
||||
configPath := filepath.Join(confdirPath, configFilename)
|
||||
confBytes, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = yaml.Unmarshal(confBytes, conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (conf *Config) Validate() error {
|
||||
var err []error
|
||||
for i := range conf.Auths {
|
||||
if conf.Auths[i].Username == "" {
|
||||
err = append(err, errors.New("Username must be set"))
|
||||
}
|
||||
if conf.Auths[i].Password == "" {
|
||||
err = append(err, errors.New("Password must be set"))
|
||||
}
|
||||
}
|
||||
return errors.Join(err...)
|
||||
}
|
||||
|
||||
func (conf *Config) YAML() (string, error) {
|
||||
var err error
|
||||
var res string
|
||||
yamlBytes, err := yaml.Marshal(conf)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res = string(yamlBytes)
|
||||
return res, err
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package config
|
||||
|
||||
const (
|
||||
confdirPath = "@srv_confdir@"
|
||||
rundirPath = "@srv_rundir@"
|
||||
logdirPath = "@srv_logdir@"
|
||||
datadirPath = "@srv_datadir@"
|
||||
packageVersion = "@PACKAGE_VERSION@"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"helmet/app/logger"
|
||||
|
||||
"helmet/app/operator"
|
||||
"helmet/pkg/mlbctl"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type HandlerConfig struct {
|
||||
Operator *operator.Operator
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
mlbctl.UnimplementedControlServer
|
||||
lg *operator.Operator
|
||||
log *logger.Logger
|
||||
}
|
||||
|
||||
func NewHandler(conf *HandlerConfig) *Handler {
|
||||
hand := Handler{
|
||||
lg: conf.Operator,
|
||||
}
|
||||
hand.log = logger.NewLogger("handler")
|
||||
return &hand
|
||||
}
|
||||
|
||||
func (hand *Handler) Register(gsrv *grpc.Server) {
|
||||
mlbctl.RegisterControlServer(gsrv, hand)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"helmet/pkg/mlbctl"
|
||||
)
|
||||
|
||||
func (hand *Handler) GetHello(ctx context.Context, req *mlbctl.GetHelloParams) (*mlbctl.GetHelloResult, error) {
|
||||
var err error
|
||||
hand.log.Debugf("Handle getHello request")
|
||||
res, err := hand.lg.GetHello(ctx, req)
|
||||
return res, err
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
* This work is published and licensed under a Creative Commons
|
||||
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
||||
*
|
||||
* Distribution of this work is permitted, but commercial use and
|
||||
* modifications are strictly prohibited.
|
||||
*/
|
||||
package logger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
mtx sync.Mutex
|
||||
output io.WriteCloser = os.Stderr
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
subject string
|
||||
writer io.WriteCloser
|
||||
mtx *sync.Mutex
|
||||
}
|
||||
|
||||
func NewLogger(subj string) *Logger {
|
||||
return &Logger{
|
||||
subject: subj,
|
||||
writer: output,
|
||||
mtx: &mtx,
|
||||
}
|
||||
}
|
||||
|
||||
func xxxNewLogger() *Logger {
|
||||
return &Logger{
|
||||
writer: output,
|
||||
mtx: &mtx,
|
||||
}
|
||||
}
|
||||
|
||||
func SetWriter(newOut io.WriteCloser) {
|
||||
mtx.Lock()
|
||||
output = newOut
|
||||
mtx.Unlock()
|
||||
}
|
||||
|
||||
func (logg *Logger) SetWriter(newOut io.WriteCloser) {
|
||||
mtx.Lock()
|
||||
logg.writer = newOut
|
||||
var newMtx sync.Mutex
|
||||
logg.mtx = &newMtx
|
||||
mtx.Unlock()
|
||||
}
|
||||
|
||||
func (logg *Logger) Debugf(message string, args ...any) {
|
||||
logg.printf("debug", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) Infof(message string, args ...any) {
|
||||
logg.printf("info", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) Warningf(message string, args ...any) {
|
||||
logg.printf("warning", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) Errorf(message string, args ...any) {
|
||||
logg.printf("error", message, args...)
|
||||
}
|
||||
|
||||
func (logg *Logger) printf(level, message string, args ...any) {
|
||||
timestamp := time.Now().Format(time.RFC3339)
|
||||
buffer := bytes.NewBuffer([]byte{})
|
||||
if logg.subject != "" {
|
||||
fmt.Fprintf(buffer, "%s %s.%s: ", timestamp, logg.subject, level)
|
||||
} else {
|
||||
fmt.Fprintf(buffer, "%s %s: ", timestamp, level)
|
||||
}
|
||||
fmt.Fprintf(buffer, message, args...)
|
||||
fmt.Fprintf(buffer, "\n")
|
||||
logg.mtx.Lock()
|
||||
fmt.Fprint(output, buffer.String())
|
||||
logg.mtx.Unlock()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
||||
*
|
||||
* This work is published and licensed under a Creative Commons
|
||||
* Attribution-NonCommercial-NoDerivatives 4.0 International License.
|
||||
*
|
||||
* Distribution of this work is permitted, but commercial use and
|
||||
* modifications are strictly prohibited.
|
||||
*/
|
||||
package logger
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLogger(t *testing.T) {
|
||||
logg := NewLogger("test")
|
||||
logg.Debugf("foo: %s", "bar")
|
||||
}
|
||||
|
||||
func BenchmarkLoggerL(b *testing.B) {
|
||||
SetWriter(ioutil.Discard)
|
||||
logg := NewLogger("test")
|
||||
for i := 0; i < b.N; i++ {
|
||||
logg.Debugf("foo: %s", "bar")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLoggerP(b *testing.B) {
|
||||
SetWriter(ioutil.Discard)
|
||||
logg := NewLogger("test")
|
||||
b.ResetTimer()
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
logg.Debugf("foo: %s", "bar")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"helmet/pkg/passwd"
|
||||
)
|
||||
|
||||
func (oper *Operator) ValidateUser(username, password string) bool {
|
||||
for i := range oper.auths {
|
||||
if username == oper.auths[i].Username && passwd.PasswordMatchCompat([]byte(password), oper.auths[i].Password) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"helmet/pkg/mlbctl"
|
||||
)
|
||||
|
||||
func (lg *Operator) GetHello(ctx context.Context, req *mlbctl.GetHelloParams) (*mlbctl.GetHelloResult, error) {
|
||||
var err error
|
||||
res := &mlbctl.GetHelloResult{
|
||||
Message: "hello",
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package operator
|
||||
|
||||
import (
|
||||
"helmet/app/logger"
|
||||
|
||||
"helmet/app/config"
|
||||
)
|
||||
|
||||
type OperatorConfig struct {
|
||||
Auths []config.Auth
|
||||
}
|
||||
|
||||
type Operator struct {
|
||||
log *logger.Logger
|
||||
auths []config.Auth
|
||||
}
|
||||
|
||||
func NewOperator(conf *OperatorConfig) (*Operator, error) {
|
||||
var err error
|
||||
lg := &Operator{
|
||||
auths: conf.Auths,
|
||||
}
|
||||
lg.log = logger.NewLogger("operator")
|
||||
return lg, err
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"helmet/app/config"
|
||||
"helmet/app/handler"
|
||||
"helmet/app/logger"
|
||||
"helmet/app/operator"
|
||||
"helmet/app/service"
|
||||
"helmet/pkg/x509crt"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
conf *config.Config
|
||||
oper *operator.Operator
|
||||
svc *service.Service
|
||||
hand *handler.Handler
|
||||
log *logger.Logger
|
||||
x509cert []byte
|
||||
x509key []byte
|
||||
}
|
||||
|
||||
func NewServer() (*Server, error) {
|
||||
var err error
|
||||
srv := &Server{}
|
||||
srv.log = logger.NewLogger("server")
|
||||
return srv, err
|
||||
}
|
||||
|
||||
func (srv *Server) Config() *config.Config {
|
||||
return srv.conf
|
||||
}
|
||||
|
||||
func (srv *Server) Configure() error {
|
||||
var err error
|
||||
srv.conf, err = config.NewConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = srv.conf.Read()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = srv.conf.Validate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Build() error {
|
||||
var err error
|
||||
srv.log.Infof("Build server")
|
||||
|
||||
if srv.conf.AsDaemon {
|
||||
logDir := filepath.Dir(srv.conf.LogPath)
|
||||
srv.log.Infof("Create %s dir", logDir)
|
||||
err = os.MkdirAll(logDir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runDir := filepath.Dir(srv.conf.RunPath)
|
||||
srv.log.Infof("Create %s dir", runDir)
|
||||
err = os.MkdirAll(runDir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Create X509 certs
|
||||
srv.x509cert, srv.x509key, err = x509crt.CreateX509SelfSignedCert(srv.conf.Hostname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Create operator
|
||||
operatorConfig := &operator.OperatorConfig{
|
||||
Auths: srv.conf.Auths,
|
||||
//Database: srv.db,
|
||||
}
|
||||
srv.oper, err = operator.NewOperator(operatorConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Create ghandler
|
||||
handlerConfig := &handler.HandlerConfig{
|
||||
Operator: srv.oper,
|
||||
}
|
||||
srv.hand = handler.NewHandler(handlerConfig)
|
||||
|
||||
// Create gservice
|
||||
serviceConfig := &service.ServiceConfig{
|
||||
PortNum: srv.conf.Service.Port,
|
||||
Hostname: srv.conf.Hostname,
|
||||
Handler: srv.hand,
|
||||
Operator: srv.oper,
|
||||
X509Cert: srv.x509cert,
|
||||
X509Key: srv.x509key,
|
||||
}
|
||||
srv.svc = service.NewService(serviceConfig)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Run() error {
|
||||
var err error
|
||||
|
||||
yamlConfig, err := srv.conf.YAML()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.log.Debugf("Server configuration:\n%s\n", yamlConfig)
|
||||
|
||||
currUser, err := user.Current()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv.log.Infof("Running server as user %s", currUser.Username)
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
done := make(chan error, 1)
|
||||
|
||||
// Run service
|
||||
startService := func(svc *service.Service, done chan error) {
|
||||
err = svc.Run()
|
||||
if err != nil {
|
||||
srv.log.Errorf("Service error: %v", err)
|
||||
done <- err
|
||||
}
|
||||
}
|
||||
go startService(srv.svc, done)
|
||||
|
||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
||||
var signal os.Signal
|
||||
select {
|
||||
case signal = <-sigs:
|
||||
srv.log.Infof("Services stopped by signal: %v", signal)
|
||||
srv.svc.Stop()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) PseudoFork() error {
|
||||
const successExit int = 0
|
||||
var keyEnv string = "IMX0LTSELMRF8K"
|
||||
var err error
|
||||
|
||||
_, isChild := os.LookupEnv(keyEnv)
|
||||
switch {
|
||||
case !isChild:
|
||||
os.Setenv(keyEnv, "TRUE")
|
||||
|
||||
procAttr := syscall.ProcAttr{}
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var sysFiles = make([]uintptr, 3)
|
||||
sysFiles[0] = uintptr(syscall.Stdin)
|
||||
sysFiles[1] = uintptr(syscall.Stdout)
|
||||
sysFiles[2] = uintptr(syscall.Stderr)
|
||||
|
||||
procAttr.Files = sysFiles
|
||||
procAttr.Env = os.Environ()
|
||||
procAttr.Dir = cwd
|
||||
|
||||
_, err = syscall.ForkExec(os.Args[0], os.Args, &procAttr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Exit(successExit)
|
||||
case isChild:
|
||||
_, err = syscall.Setsid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
os.Unsetenv(keyEnv)
|
||||
return err
|
||||
}
|
||||
|
||||
func (srv *Server) Daemonize() error {
|
||||
var err error
|
||||
if srv.conf.AsDaemon {
|
||||
// Restart process process
|
||||
err = srv.PseudoFork()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Redirect stdin
|
||||
nullFile, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stdin.Fd()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Redirect stderr and stout
|
||||
logdir := filepath.Dir(srv.conf.LogPath)
|
||||
err = os.MkdirAll(logdir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logFile, err := os.OpenFile(srv.conf.LogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = syscall.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Write process ID
|
||||
rundir := filepath.Dir(srv.conf.RunPath)
|
||||
err = os.MkdirAll(rundir, 0750)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pidFile, err := os.OpenFile(srv.conf.RunPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0640)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pidFile.Close()
|
||||
currPid := os.Getpid()
|
||||
_, err = pidFile.WriteString(strconv.Itoa(currPid))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"helmet/app/logger"
|
||||
|
||||
"helmet/app/handler"
|
||||
"helmet/app/operator"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type ServiceConfig struct {
|
||||
Handler *handler.Handler
|
||||
Operator *operator.Operator
|
||||
PortNum uint32
|
||||
Hostname string
|
||||
X509Cert []byte
|
||||
X509Key []byte
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
gsrv *grpc.Server
|
||||
hand *handler.Handler
|
||||
oper *operator.Operator
|
||||
log *logger.Logger
|
||||
portnum uint32
|
||||
hostname string
|
||||
|
||||
username string
|
||||
password string
|
||||
x509Cert []byte
|
||||
x509Key []byte
|
||||
}
|
||||
|
||||
func NewService(conf *ServiceConfig) *Service {
|
||||
svc := Service{
|
||||
hand: conf.Handler,
|
||||
oper: conf.Operator,
|
||||
portnum: conf.PortNum,
|
||||
hostname: conf.Hostname,
|
||||
x509Cert: conf.X509Cert,
|
||||
x509Key: conf.X509Key,
|
||||
}
|
||||
svc.log = logger.NewLogger("service")
|
||||
|
||||
return &svc
|
||||
}
|
||||
|
||||
func (svc *Service) Run() error {
|
||||
var err error
|
||||
svc.log.Infof("Service run")
|
||||
|
||||
listenSpec := fmt.Sprintf(":%d", svc.portnum)
|
||||
listener, err := net.Listen("tcp", listenSpec)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tlsCert, err := tls.X509KeyPair(svc.x509Cert, svc.x509Key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tlsConfig := tls.Config{
|
||||
Certificates: []tls.Certificate{tlsCert},
|
||||
ClientAuth: tls.NoClientCert,
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
tlsCredentials := credentials.NewTLS(&tlsConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
interceptors := []grpc.UnaryServerInterceptor{
|
||||
svc.authInterceptor,
|
||||
svc.logInterceptor,
|
||||
}
|
||||
gsrvOpts := []grpc.ServerOption{
|
||||
grpc.Creds(tlsCredentials),
|
||||
grpc.ChainUnaryInterceptor(interceptors...),
|
||||
//grpc.UnaryInterceptor(svc.authInterceptor),
|
||||
}
|
||||
svc.gsrv = grpc.NewServer(gsrvOpts...)
|
||||
|
||||
svc.hand.Register(svc.gsrv)
|
||||
|
||||
svc.log.Infof("Service listening at %v", listener.Addr())
|
||||
err = svc.gsrv.Serve(listener)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (svc *Service) authInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
meta, _ := metadata.FromIncomingContext(ctx)
|
||||
usernameArr := meta["username"]
|
||||
passwordArr := meta["password"]
|
||||
if len(usernameArr) == 0 || len(passwordArr) == 0 {
|
||||
err := status.Errorf(codes.PermissionDenied, "Empty auth data")
|
||||
return nil, err
|
||||
}
|
||||
username := meta["username"][0]
|
||||
password := meta["password"][0]
|
||||
if !svc.oper.ValidateUser(username, password) {
|
||||
err := status.Errorf(codes.PermissionDenied, "Incorrect auth data")
|
||||
return nil, err
|
||||
}
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
func (svc *Service) logInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
|
||||
var err error
|
||||
svc.log.Debugf("Called method: %v", info.FullMethod)
|
||||
reqData, err := json.Marshal(req)
|
||||
if err == nil {
|
||||
svc.log.Debugf("Request: %s", string(reqData))
|
||||
}
|
||||
return handler(ctx, req)
|
||||
}
|
||||
|
||||
func (svc *Service) Stop() {
|
||||
svc.log.Infof("Stopping service")
|
||||
svc.gsrv.GracefulStop()
|
||||
}
|
||||
Reference in New Issue
Block a user