mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-18 14:47:03 +00:00
Introduce expvar counters
This patch introduces expvar counters to chasquid and the queue packages. For now there's only a handful of counters, but they will be expanded in future patches.
This commit is contained in:
14
chasquid.go
14
chasquid.go
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"expvar"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -14,6 +15,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -37,11 +39,19 @@ import (
|
|||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Command-line flags.
|
||||||
var (
|
var (
|
||||||
configDir = flag.String("config_dir", "/etc/chasquid",
|
configDir = flag.String("config_dir", "/etc/chasquid",
|
||||||
"configuration directory")
|
"configuration directory")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Exported variables.
|
||||||
|
var (
|
||||||
|
commandCount = expvar.NewMap("chasquid/smtpIn/commandCount")
|
||||||
|
responseCodeCount = expvar.NewMap("chasquid/smtpIn/responseCodeCount")
|
||||||
|
spfResultCount = expvar.NewMap("chasquid/smtpIn/spfResultCount")
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -476,6 +486,7 @@ loop:
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commandCount.Add(cmd, 1)
|
||||||
if cmd == "AUTH" {
|
if cmd == "AUTH" {
|
||||||
c.tr.Debugf("-> AUTH <redacted>")
|
c.tr.Debugf("-> AUTH <redacted>")
|
||||||
} else {
|
} else {
|
||||||
@@ -642,6 +653,8 @@ func (c *Conn) MAIL(params string) (code int, msg string) {
|
|||||||
c.spfResult, c.spfError = spf.CheckHost(
|
c.spfResult, c.spfError = spf.CheckHost(
|
||||||
tcp.IP, envelope.DomainOf(e.Address))
|
tcp.IP, envelope.DomainOf(e.Address))
|
||||||
c.tr.Debugf("SPF %v (%v)", c.spfResult, c.spfError)
|
c.tr.Debugf("SPF %v (%v)", c.spfResult, c.spfError)
|
||||||
|
spfResultCount.Add(string(c.spfResult), 1)
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc7208#section-8
|
// https://tools.ietf.org/html/rfc7208#section-8
|
||||||
// We opt not to fail on errors, to avoid accidents to prevent
|
// We opt not to fail on errors, to avoid accidents to prevent
|
||||||
// delivery.
|
// delivery.
|
||||||
@@ -964,6 +977,7 @@ func (c *Conn) readLine() (line string, err error) {
|
|||||||
func (c *Conn) writeResponse(code int, msg string) error {
|
func (c *Conn) writeResponse(code int, msg string) error {
|
||||||
defer c.tc.W.Flush()
|
defer c.tc.W.Flush()
|
||||||
|
|
||||||
|
responseCodeCount.Add(strconv.Itoa(code), 1)
|
||||||
return writeResponse(c.tc.W, code, msg)
|
return writeResponse(c.tc.W, code, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package courier
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"expvar"
|
||||||
"flag"
|
"flag"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
@@ -29,6 +30,11 @@ var (
|
|||||||
fakeMX = map[string]string{}
|
fakeMX = map[string]string{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Exported variables.
|
||||||
|
var (
|
||||||
|
tlsCount = expvar.NewMap("chasquid/smtpOut/tlsCount")
|
||||||
|
)
|
||||||
|
|
||||||
// SMTP delivers remote mail via outgoing SMTP.
|
// SMTP delivers remote mail via outgoing SMTP.
|
||||||
type SMTP struct {
|
type SMTP struct {
|
||||||
}
|
}
|
||||||
@@ -91,6 +97,7 @@ retry:
|
|||||||
// Unfortunately, many servers use self-signed certs, so if we
|
// Unfortunately, many servers use self-signed certs, so if we
|
||||||
// fail verification we just try again without validating.
|
// fail verification we just try again without validating.
|
||||||
if insecure {
|
if insecure {
|
||||||
|
tlsCount.Add("tls:failed", 1)
|
||||||
return tr.Errorf("TLS error: %v", err), false
|
return tr.Errorf("TLS error: %v", err), false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,10 +108,13 @@ retry:
|
|||||||
|
|
||||||
if config.InsecureSkipVerify {
|
if config.InsecureSkipVerify {
|
||||||
tr.Debugf("Insecure - using TLS, but cert does not match %s", mx)
|
tr.Debugf("Insecure - using TLS, but cert does not match %s", mx)
|
||||||
|
tlsCount.Add("tls:insecure", 1)
|
||||||
} else {
|
} else {
|
||||||
|
tlsCount.Add("tls:secure", 1)
|
||||||
tr.Debugf("Secure - using TLS")
|
tr.Debugf("Secure - using TLS")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
tlsCount.Add("plain", 1)
|
||||||
tr.Debugf("Insecure - NOT using TLS")
|
tr.Debugf("Insecure - NOT using TLS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"expvar"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -51,6 +52,14 @@ var (
|
|||||||
errQueueFull = fmt.Errorf("Queue size too big, try again later")
|
errQueueFull = fmt.Errorf("Queue size too big, try again later")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Exported variables.
|
||||||
|
var (
|
||||||
|
putCount = expvar.NewInt("chasquid/queue/putCount")
|
||||||
|
itemsWritten = expvar.NewInt("chasquid/queue/itemsWritten")
|
||||||
|
dsnQueued = expvar.NewInt("chasquid/queue/dsnQueued")
|
||||||
|
deliverAttempts = expvar.NewMap("chasquid/queue/deliverAttempts")
|
||||||
|
)
|
||||||
|
|
||||||
// Channel used to get random IDs for items in the queue.
|
// Channel used to get random IDs for items in the queue.
|
||||||
var newID chan string
|
var newID chan string
|
||||||
|
|
||||||
@@ -148,6 +157,7 @@ func (q *Queue) Put(hostname, from string, to []string, data []byte) (string, er
|
|||||||
if q.Len() >= maxQueueSize {
|
if q.Len() >= maxQueueSize {
|
||||||
return "", errQueueFull
|
return "", errQueueFull
|
||||||
}
|
}
|
||||||
|
putCount.Add(1)
|
||||||
|
|
||||||
item := &Item{
|
item := &Item{
|
||||||
Message: Message{
|
Message: Message{
|
||||||
@@ -272,6 +282,7 @@ func ItemFromFile(fname string) (*Item, error) {
|
|||||||
func (item *Item) WriteTo(dir string) error {
|
func (item *Item) WriteTo(dir string) error {
|
||||||
item.Lock()
|
item.Lock()
|
||||||
defer item.Unlock()
|
defer item.Unlock()
|
||||||
|
itemsWritten.Add(1)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
item.CreatedAtTs, err = ptypes.TimestampProto(item.CreatedAt)
|
item.CreatedAtTs, err = ptypes.TimestampProto(item.CreatedAt)
|
||||||
@@ -394,12 +405,14 @@ func sendDSN(tr *trace.Trace, q *Queue, item *Item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tr.Printf("queued DSN: %s", id)
|
tr.Printf("queued DSN: %s", id)
|
||||||
|
dsnQueued.Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// deliver the item to the given recipient, using the couriers from the queue.
|
// deliver the item to the given recipient, using the couriers from the queue.
|
||||||
// Return an error (if any), and whether it is permanent or not.
|
// Return an error (if any), and whether it is permanent or not.
|
||||||
func (item *Item) deliver(q *Queue, rcpt *Recipient) (err error, permanent bool) {
|
func (item *Item) deliver(q *Queue, rcpt *Recipient) (err error, permanent bool) {
|
||||||
if rcpt.Type == Recipient_PIPE {
|
if rcpt.Type == Recipient_PIPE {
|
||||||
|
deliverAttempts.Add("pipe", 1)
|
||||||
c := strings.Fields(rcpt.Address)
|
c := strings.Fields(rcpt.Address)
|
||||||
if len(c) == 0 {
|
if len(c) == 0 {
|
||||||
return fmt.Errorf("empty pipe"), true
|
return fmt.Errorf("empty pipe"), true
|
||||||
@@ -413,8 +426,10 @@ func (item *Item) deliver(q *Queue, rcpt *Recipient) (err error, permanent bool)
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if envelope.DomainIn(rcpt.Address, q.localDomains) {
|
if envelope.DomainIn(rcpt.Address, q.localDomains) {
|
||||||
|
deliverAttempts.Add("email:local", 1)
|
||||||
return q.localC.Deliver(item.From, rcpt.Address, item.Data)
|
return q.localC.Deliver(item.From, rcpt.Address, item.Data)
|
||||||
} else {
|
} else {
|
||||||
|
deliverAttempts.Add("email:remote", 1)
|
||||||
from := item.From
|
from := item.From
|
||||||
if !envelope.DomainIn(item.From, q.localDomains) {
|
if !envelope.DomainIn(item.From, q.localDomains) {
|
||||||
// We're sending from a non-local to a non-local. This should
|
// We're sending from a non-local to a non-local. This should
|
||||||
|
|||||||
Reference in New Issue
Block a user