This commit is contained in:
netscrawler
2024-06-30 20:44:53 +03:00
parent 61d2be39f1
commit c99f477e35
15 changed files with 468 additions and 0 deletions
+23
View File
@@ -0,0 +1,23 @@
package app
import (
grpcapp "converter/internal/app/grpc"
"log/slog"
"time"
)
type App struct {
GRPCSrv *grpcapp.App
}
func New(
log *slog.Logger,
grpcPort int,
tokenTTl time.Duration) *App {
//TODO: инициализировать хранилище
//TODO: init convert service
grpcApp := grpcapp.New(log, grpcPort)
return &App{
GRPCSrv: grpcApp,
}
}
+62
View File
@@ -0,0 +1,62 @@
package grpcapp
import (
convertgrpc "converter/internal/grpc/cnvrt"
"fmt"
"google.golang.org/grpc"
"log/slog"
"net"
)
type App struct {
log *slog.Logger
gRPCServer *grpc.Server
port int
}
func New(
log *slog.Logger,
port int) *App {
gRPCServer := grpc.NewServer()
convertgrpc.Register(gRPCServer)
return &App{
log: log,
gRPCServer: gRPCServer,
port: port,
}
}
func (a *App) MustRun() {
if err := a.Run(); err != nil {
panic(err)
}
}
func (a *App) Run() error {
const op = "grpcapp.Run"
log := a.log.With(
slog.String("op", op),
slog.Int("port", a.port))
l, err := net.Listen("tcp", fmt.Sprintf(":%d", a.port))
if err != nil {
return fmt.Errorf("%s: %w", op, err)
}
log.Info("gRPC server is running", slog.String("addr", l.Addr().String()))
if err := a.gRPCServer.Serve(l); err != nil {
return fmt.Errorf("%s: %w", op, err)
}
return nil
}
func (a *App) Stop() {
const op = "grpcapp.Stop"
a.log.With(slog.String("op", op)).
Info("stopping gRPC server", slog.Int("port", a.port))
a.gRPCServer.GracefulStop()
}
+52
View File
@@ -0,0 +1,52 @@
package config
import (
"flag"
"github.com/ilyakaznacheev/cleanenv"
"os"
"time"
)
type Config struct {
Env string `yaml:"env" env-default:"local"`
TokenTTL time.Duration `yaml:"token_ttl" env-required:"true"`
GRPC GRPCConfig `yaml:"grpc"`
}
type GRPCConfig struct {
Port int `yaml:"port"`
Timeout time.Duration `yaml:"timeout"`
}
func MustLoad() *Config {
path := fetchConfigPath()
if path == "" {
panic("config path is empty")
}
if _, err := os.Stat(path); os.IsNotExist(err) {
panic("config file not found" + path)
}
var cfg Config
if err := cleanenv.ReadConfig(path, &cfg); err != nil {
panic("failed to read config" + err.Error())
}
return &cfg
}
func fetchConfigPath() string {
var res string
flag.StringVar(&res, "config", "", "path to config file")
flag.Parse()
if res == "" {
res = os.Getenv("CONFIG_PATH")
}
return res
}
+22
View File
@@ -0,0 +1,22 @@
package cnvrt
import (
"context"
cnvrtv1 "github.com/netscrawler/protos/gen/go/changeAPI"
"google.golang.org/grpc"
)
type serverAPI struct {
cnvrtv1.UnimplementedConverterServer
}
func Register(gRPC *grpc.Server) {
cnvrtv1.RegisterConverterServer(gRPC, &serverAPI{})
}
func (s serverAPI) Convert(
ctx context.Context,
req *cnvrtv1.ConvertRequest) (
*cnvrtv1.ConvertResponse, error) {
panic("implement me")
}
@@ -0,0 +1,36 @@
package slogdiscard
import (
"context"
"golang.org/x/exp/slog"
)
func NewDiscardLogger() *slog.Logger {
return slog.New(NewDiscardHandler())
}
type DiscardHandler struct{}
func NewDiscardHandler() *DiscardHandler {
return &DiscardHandler{}
}
func (h *DiscardHandler) Handle(_ context.Context, _ slog.Record) error {
// Просто игнорируем запись журнала
return nil
}
func (h *DiscardHandler) WithAttrs(_ []slog.Attr) slog.Handler {
// Возвращает тот же обработчик, так как нет атрибутов для сохранения
return h
}
func (h *DiscardHandler) WithGroup(_ string) slog.Handler {
// Возвращает тот же обработчик, так как нет группы для сохранения
return h
}
func (h *DiscardHandler) Enabled(_ context.Context, _ slog.Level) bool {
// Всегда возвращает false, так как запись журнала игнорируется
return false
}
@@ -0,0 +1,98 @@
package slogpretty
import (
"context"
"encoding/json"
"io"
stdLog "log"
"log/slog"
"github.com/fatih/color"
)
type PrettyHandlerOptions struct {
SlogOpts *slog.HandlerOptions
}
type PrettyHandler struct {
opts PrettyHandlerOptions
slog.Handler
l *stdLog.Logger
attrs []slog.Attr
}
func (opts PrettyHandlerOptions) NewPrettyHandler(
out io.Writer,
) *PrettyHandler {
h := &PrettyHandler{
Handler: slog.NewJSONHandler(out, opts.SlogOpts),
l: stdLog.New(out, "", 0),
}
return h
}
func (h *PrettyHandler) Handle(_ context.Context, r slog.Record) error {
level := r.Level.String() + ":"
switch r.Level {
case slog.LevelDebug:
level = color.MagentaString(level)
case slog.LevelInfo:
level = color.BlueString(level)
case slog.LevelWarn:
level = color.YellowString(level)
case slog.LevelError:
level = color.RedString(level)
}
fields := make(map[string]interface{}, r.NumAttrs())
r.Attrs(func(a slog.Attr) bool {
fields[a.Key] = a.Value.Any()
return true
})
for _, a := range h.attrs {
fields[a.Key] = a.Value.Any()
}
var b []byte
var err error
if len(fields) > 0 {
b, err = json.MarshalIndent(fields, "", " ")
if err != nil {
return err
}
}
timeStr := r.Time.Format("[15:05:05.000]")
msg := color.CyanString(r.Message)
h.l.Println(
timeStr,
level,
msg,
color.WhiteString(string(b)),
)
return nil
}
func (h *PrettyHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
return &PrettyHandler{
Handler: h.Handler,
l: h.l,
attrs: attrs,
}
}
func (h *PrettyHandler) WithGroup(name string) slog.Handler {
// TODO: implement
return &PrettyHandler{
Handler: h.Handler.WithGroup(name),
l: h.l,
}
}
+12
View File
@@ -0,0 +1,12 @@
package sl
import (
"log/slog"
)
func Err(err error) slog.Attr {
return slog.Attr{
Key: "error",
Value: slog.StringValue(err.Error()),
}
}