1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package openmetrics2021import (22 "errors"23 "fmt"24 "net"25 "net/http"26 "sync"2728 "github.com/foxcpp/maddy/framework/config"29 "github.com/foxcpp/maddy/framework/log"30 "github.com/foxcpp/maddy/framework/module"31 "github.com/prometheus/client_golang/prometheus/promhttp"32)3334const modName = "openmetrics"3536type Endpoint struct {37 addrs []string38 logger log.Logger3940 listenersWg sync.WaitGroup41 serv http.Server42 mux *http.ServeMux43}4445func New(_ string, args []string) (module.Module, error) {46 return &Endpoint{47 addrs: args,48 logger: log.Logger{Name: modName, Debug: log.DefaultLogger.Debug},49 }, nil50}5152func (e *Endpoint) Init(cfg *config.Map) error {53 cfg.Bool("debug", false, false, &e.logger.Debug)54 if _, err := cfg.Process(); err != nil {55 return err56 }5758 e.mux = http.NewServeMux()59 e.mux.Handle("/metrics", promhttp.Handler())60 e.serv.Handler = e.mux6162 for _, a := range e.addrs {63 endp, err := config.ParseEndpoint(a)64 if err != nil {65 return fmt.Errorf("%s: malformed endpoint: %v", modName, err)66 }67 if endp.IsTLS() {68 return fmt.Errorf("%s: TLS is not supported yet", modName)69 }70 l, err := net.Listen(endp.Network(), endp.Address())71 if err != nil {72 return fmt.Errorf("%s: %v", modName, err)73 }7475 e.listenersWg.Add(1)76 go func() {77 e.logger.Println("listening on", endp.String())78 err := e.serv.Serve(l)79 if err != nil && !errors.Is(err, http.ErrServerClosed) {80 e.logger.Error("serve failed", err, "endpoint", a)81 }82 e.listenersWg.Done()83 }()84 }8586 return nil87}8889func (e *Endpoint) Name() string {90 return modName91}9293func (e *Endpoint) InstanceName() string {94 return ""95}9697func (e *Endpoint) Close() error {98 if err := e.serv.Close(); err != nil {99 return err100 }101 e.listenersWg.Wait()102 return nil103}104105func init() {106 module.RegisterEndpoint(modName, New)107}