monitoring: refine mail stats and add send-limit usage
This commit is contained in:
parent
1fb56bae70
commit
d5d2fc66b9
@ -935,6 +935,15 @@ def build_overview():
|
|||||||
{"color": "red", "value": 100},
|
{"color": "red", "value": 100},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
mail_limit_thresholds = {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": None},
|
||||||
|
{"color": "yellow", "value": 70},
|
||||||
|
{"color": "orange", "value": 85},
|
||||||
|
{"color": "red", "value": 95},
|
||||||
|
],
|
||||||
|
}
|
||||||
mail_api_thresholds = {
|
mail_api_thresholds = {
|
||||||
"mode": "absolute",
|
"mode": "absolute",
|
||||||
"steps": [
|
"steps": [
|
||||||
@ -946,28 +955,28 @@ def build_overview():
|
|||||||
(
|
(
|
||||||
30,
|
30,
|
||||||
"Mail Bounce Rate (1d)",
|
"Mail Bounce Rate (1d)",
|
||||||
'postmark_outbound_bounce_rate{window="1d"}',
|
'max(postmark_outbound_bounce_rate{window="1d"})',
|
||||||
"percent",
|
"percent",
|
||||||
mail_bounce_rate_thresholds,
|
mail_bounce_rate_thresholds,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
31,
|
31,
|
||||||
"Mail Bounced (1d)",
|
"Mail Bounced (1d)",
|
||||||
'postmark_outbound_bounced{window="1d"}',
|
'max(postmark_outbound_bounced{window="1d"})',
|
||||||
"none",
|
"none",
|
||||||
mail_bounce_count_thresholds,
|
mail_bounce_count_thresholds,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
32,
|
32,
|
||||||
"Mail Sent (1d)",
|
"Mail Limit Used (30d)",
|
||||||
'postmark_outbound_sent{window="1d"}',
|
"max(postmark_sending_limit_used_percent)",
|
||||||
"none",
|
"percent",
|
||||||
None,
|
mail_limit_thresholds,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
33,
|
33,
|
||||||
"Postmark API Up",
|
"Postmark API Up",
|
||||||
"postmark_api_up",
|
"max(postmark_api_up)",
|
||||||
"none",
|
"none",
|
||||||
mail_api_thresholds,
|
mail_api_thresholds,
|
||||||
),
|
),
|
||||||
@ -1875,33 +1884,42 @@ def build_mail_dashboard():
|
|||||||
{"color": "green", "value": 1},
|
{"color": "green", "value": 1},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
limit_thresholds = {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{"color": "green", "value": None},
|
||||||
|
{"color": "yellow", "value": 70},
|
||||||
|
{"color": "orange", "value": 85},
|
||||||
|
{"color": "red", "value": 95},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
current_stats = [
|
current_stats = [
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
"Bounce Rate (1d)",
|
"Bounce Rate (1d)",
|
||||||
'postmark_outbound_bounce_rate{window="1d"}',
|
'max(postmark_outbound_bounce_rate{window="1d"})',
|
||||||
"percent",
|
"percent",
|
||||||
bounce_rate_thresholds,
|
bounce_rate_thresholds,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
2,
|
2,
|
||||||
"Bounce Rate (7d)",
|
"Bounce Rate (7d)",
|
||||||
'postmark_outbound_bounce_rate{window="7d"}',
|
'max(postmark_outbound_bounce_rate{window="7d"})',
|
||||||
"percent",
|
"percent",
|
||||||
bounce_rate_thresholds,
|
bounce_rate_thresholds,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
3,
|
3,
|
||||||
"Bounced (1d)",
|
"Bounced (1d)",
|
||||||
'postmark_outbound_bounced{window="1d"}',
|
'max(postmark_outbound_bounced{window="1d"})',
|
||||||
"none",
|
"none",
|
||||||
bounce_count_thresholds,
|
bounce_count_thresholds,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
4,
|
4,
|
||||||
"Bounced (7d)",
|
"Bounced (7d)",
|
||||||
'postmark_outbound_bounced{window="7d"}',
|
'max(postmark_outbound_bounced{window="7d"})',
|
||||||
"none",
|
"none",
|
||||||
bounce_count_thresholds,
|
bounce_count_thresholds,
|
||||||
),
|
),
|
||||||
@ -1923,7 +1941,7 @@ def build_mail_dashboard():
|
|||||||
stat_panel(
|
stat_panel(
|
||||||
5,
|
5,
|
||||||
"Sent (1d)",
|
"Sent (1d)",
|
||||||
'postmark_outbound_sent{window="1d"}',
|
'max(postmark_outbound_sent{window="1d"})',
|
||||||
{"h": 4, "w": 6, "x": 0, "y": 4},
|
{"h": 4, "w": 6, "x": 0, "y": 4},
|
||||||
decimals=0,
|
decimals=0,
|
||||||
)
|
)
|
||||||
@ -1932,7 +1950,7 @@ def build_mail_dashboard():
|
|||||||
stat_panel(
|
stat_panel(
|
||||||
6,
|
6,
|
||||||
"Sent (7d)",
|
"Sent (7d)",
|
||||||
'postmark_outbound_sent{window="7d"}',
|
'max(postmark_outbound_sent{window="7d"})',
|
||||||
{"h": 4, "w": 6, "x": 6, "y": 4},
|
{"h": 4, "w": 6, "x": 6, "y": 4},
|
||||||
decimals=0,
|
decimals=0,
|
||||||
)
|
)
|
||||||
@ -1940,30 +1958,69 @@ def build_mail_dashboard():
|
|||||||
panels.append(
|
panels.append(
|
||||||
stat_panel(
|
stat_panel(
|
||||||
7,
|
7,
|
||||||
"Postmark API Up",
|
"Limit Used (30d)",
|
||||||
"postmark_api_up",
|
"max(postmark_sending_limit_used_percent)",
|
||||||
{"h": 4, "w": 6, "x": 12, "y": 4},
|
{"h": 4, "w": 6, "x": 12, "y": 4},
|
||||||
|
thresholds=limit_thresholds,
|
||||||
|
unit="percent",
|
||||||
|
decimals=1,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
panels.append(
|
||||||
|
stat_panel(
|
||||||
|
8,
|
||||||
|
"Send Limit (30d)",
|
||||||
|
"max(postmark_sending_limit)",
|
||||||
|
{"h": 4, "w": 6, "x": 18, "y": 4},
|
||||||
|
decimals=0,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
panels.append(
|
||||||
|
stat_panel(
|
||||||
|
9,
|
||||||
|
"Postmark API Up",
|
||||||
|
"max(postmark_api_up)",
|
||||||
|
{"h": 4, "w": 6, "x": 0, "y": 8},
|
||||||
thresholds=api_thresholds,
|
thresholds=api_thresholds,
|
||||||
decimals=0,
|
decimals=0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
panels.append(
|
panels.append(
|
||||||
stat_panel(
|
stat_panel(
|
||||||
8,
|
10,
|
||||||
"Last Success",
|
"Last Success",
|
||||||
"postmark_last_success_timestamp_seconds",
|
"max(postmark_last_success_timestamp_seconds)",
|
||||||
{"h": 4, "w": 6, "x": 18, "y": 4},
|
{"h": 4, "w": 6, "x": 6, "y": 8},
|
||||||
unit="dateTimeAsIso",
|
unit="dateTimeAsIso",
|
||||||
decimals=0,
|
decimals=0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
panels.append(
|
||||||
|
stat_panel(
|
||||||
|
11,
|
||||||
|
"Exporter Errors",
|
||||||
|
"sum(postmark_request_errors_total)",
|
||||||
|
{"h": 4, "w": 6, "x": 12, "y": 8},
|
||||||
|
decimals=0,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
panels.append(
|
||||||
|
stat_panel(
|
||||||
|
12,
|
||||||
|
"Limit Used (30d)",
|
||||||
|
"max(postmark_sending_limit_used)",
|
||||||
|
{"h": 4, "w": 6, "x": 18, "y": 8},
|
||||||
|
decimals=0,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
panels.append(
|
panels.append(
|
||||||
timeseries_panel(
|
timeseries_panel(
|
||||||
9,
|
13,
|
||||||
"Bounce Rate (1d vs 7d)",
|
"Bounce Rate (1d vs 7d)",
|
||||||
"postmark_outbound_bounce_rate",
|
"max by (window) (postmark_outbound_bounce_rate)",
|
||||||
{"h": 8, "w": 12, "x": 0, "y": 8},
|
{"h": 8, "w": 12, "x": 0, "y": 12},
|
||||||
unit="percent",
|
unit="percent",
|
||||||
legend="{{window}}",
|
legend="{{window}}",
|
||||||
legend_display="table",
|
legend_display="table",
|
||||||
@ -1972,10 +2029,10 @@ def build_mail_dashboard():
|
|||||||
)
|
)
|
||||||
panels.append(
|
panels.append(
|
||||||
timeseries_panel(
|
timeseries_panel(
|
||||||
10,
|
14,
|
||||||
"Bounced (1d vs 7d)",
|
"Bounced (1d vs 7d)",
|
||||||
"postmark_outbound_bounced",
|
"max by (window) (postmark_outbound_bounced)",
|
||||||
{"h": 8, "w": 12, "x": 12, "y": 8},
|
{"h": 8, "w": 12, "x": 12, "y": 12},
|
||||||
unit="none",
|
unit="none",
|
||||||
legend="{{window}}",
|
legend="{{window}}",
|
||||||
legend_display="table",
|
legend_display="table",
|
||||||
@ -1984,10 +2041,10 @@ def build_mail_dashboard():
|
|||||||
)
|
)
|
||||||
panels.append(
|
panels.append(
|
||||||
timeseries_panel(
|
timeseries_panel(
|
||||||
11,
|
15,
|
||||||
"Sent (1d vs 7d)",
|
"Sent (1d vs 7d)",
|
||||||
"postmark_outbound_sent",
|
"max by (window) (postmark_outbound_sent)",
|
||||||
{"h": 8, "w": 12, "x": 0, "y": 16},
|
{"h": 8, "w": 12, "x": 0, "y": 20},
|
||||||
unit="none",
|
unit="none",
|
||||||
legend="{{window}}",
|
legend="{{window}}",
|
||||||
legend_display="table",
|
legend_display="table",
|
||||||
@ -1996,10 +2053,10 @@ def build_mail_dashboard():
|
|||||||
)
|
)
|
||||||
panels.append(
|
panels.append(
|
||||||
timeseries_panel(
|
timeseries_panel(
|
||||||
12,
|
16,
|
||||||
"Exporter Errors",
|
"Exporter Errors",
|
||||||
"postmark_request_errors_total",
|
"sum(postmark_request_errors_total)",
|
||||||
{"h": 8, "w": 12, "x": 12, "y": 16},
|
{"h": 8, "w": 12, "x": 12, "y": 20},
|
||||||
unit="none",
|
unit="none",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@ -19,6 +19,7 @@ WINDOWS = [
|
|||||||
Window("today", 0),
|
Window("today", 0),
|
||||||
Window("1d", 1),
|
Window("1d", 1),
|
||||||
Window("7d", 7),
|
Window("7d", 7),
|
||||||
|
Window("30d", 30),
|
||||||
]
|
]
|
||||||
|
|
||||||
API_BASE = os.environ.get("POSTMARK_API_BASE", "https://api.postmarkapp.com").rstrip("/")
|
API_BASE = os.environ.get("POSTMARK_API_BASE", "https://api.postmarkapp.com").rstrip("/")
|
||||||
@ -28,6 +29,12 @@ LISTEN_PORT = int(os.environ.get("LISTEN_PORT", "8000"))
|
|||||||
|
|
||||||
PRIMARY_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN", "").strip()
|
PRIMARY_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN", "").strip()
|
||||||
FALLBACK_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN_FALLBACK", "").strip()
|
FALLBACK_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN_FALLBACK", "").strip()
|
||||||
|
LIMIT_WINDOW = os.environ.get("POSTMARK_SENDING_LIMIT_WINDOW", "30d").strip()
|
||||||
|
LIMIT_RAW = os.environ.get("POSTMARK_SENDING_LIMIT", "").strip()
|
||||||
|
try:
|
||||||
|
SENDING_LIMIT = float(LIMIT_RAW) if LIMIT_RAW else 0.0
|
||||||
|
except ValueError:
|
||||||
|
SENDING_LIMIT = 0.0
|
||||||
|
|
||||||
EXPORTER_INFO = Info("postmark_exporter", "Exporter build info")
|
EXPORTER_INFO = Info("postmark_exporter", "Exporter build info")
|
||||||
EXPORTER_INFO.info(
|
EXPORTER_INFO.info(
|
||||||
@ -62,6 +69,18 @@ POSTMARK_OUTBOUND_BOUNCE_RATE = Gauge(
|
|||||||
"Outbound bounce rate percentage within the selected window",
|
"Outbound bounce rate percentage within the selected window",
|
||||||
labelnames=("window",),
|
labelnames=("window",),
|
||||||
)
|
)
|
||||||
|
POSTMARK_SENDING_LIMIT_GAUGE = Gauge(
|
||||||
|
"postmark_sending_limit",
|
||||||
|
"Configured Postmark sending limit for the active account",
|
||||||
|
)
|
||||||
|
POSTMARK_SENDING_LIMIT_USED = Gauge(
|
||||||
|
"postmark_sending_limit_used",
|
||||||
|
"Messages sent within the configured send limit window",
|
||||||
|
)
|
||||||
|
POSTMARK_SENDING_LIMIT_USED_PERCENT = Gauge(
|
||||||
|
"postmark_sending_limit_used_percent",
|
||||||
|
"Percent of the configured send limit used within the limit window",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fetch_outbound_stats(token: str, window: Window) -> dict:
|
def fetch_outbound_stats(token: str, window: Window) -> dict:
|
||||||
@ -83,15 +102,25 @@ def fetch_outbound_stats(token: str, window: Window) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def update_metrics(token: str) -> None:
|
def update_metrics(token: str) -> None:
|
||||||
|
sent_by_window = {}
|
||||||
for window in WINDOWS:
|
for window in WINDOWS:
|
||||||
data = fetch_outbound_stats(token, window)
|
data = fetch_outbound_stats(token, window)
|
||||||
sent = int(data.get("Sent", 0) or 0)
|
sent = int(data.get("Sent", 0) or 0)
|
||||||
bounced = int(data.get("Bounced", 0) or 0)
|
bounced = int(data.get("Bounced", 0) or 0)
|
||||||
rate = (bounced / sent * 100.0) if sent else 0.0
|
rate = (bounced / sent * 100.0) if sent else 0.0
|
||||||
|
sent_by_window[window.label] = sent
|
||||||
POSTMARK_OUTBOUND_SENT.labels(window=window.label).set(sent)
|
POSTMARK_OUTBOUND_SENT.labels(window=window.label).set(sent)
|
||||||
POSTMARK_OUTBOUND_BOUNCED.labels(window=window.label).set(bounced)
|
POSTMARK_OUTBOUND_BOUNCED.labels(window=window.label).set(bounced)
|
||||||
POSTMARK_OUTBOUND_BOUNCE_RATE.labels(window=window.label).set(rate)
|
POSTMARK_OUTBOUND_BOUNCE_RATE.labels(window=window.label).set(rate)
|
||||||
|
|
||||||
|
POSTMARK_SENDING_LIMIT_GAUGE.set(SENDING_LIMIT)
|
||||||
|
limit_window_sent = sent_by_window.get(LIMIT_WINDOW, 0)
|
||||||
|
POSTMARK_SENDING_LIMIT_USED.set(limit_window_sent)
|
||||||
|
if SENDING_LIMIT:
|
||||||
|
POSTMARK_SENDING_LIMIT_USED_PERCENT.set(limit_window_sent / SENDING_LIMIT * 100.0)
|
||||||
|
else:
|
||||||
|
POSTMARK_SENDING_LIMIT_USED_PERCENT.set(0.0)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
if not PRIMARY_TOKEN and not FALLBACK_TOKEN:
|
if not PRIMARY_TOKEN and not FALLBACK_TOKEN:
|
||||||
|
|||||||
@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounce_rate{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -89,7 +89,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate{window=\"7d\"}",
|
"expr": "max(postmark_outbound_bounce_rate{window=\"7d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -158,7 +158,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounced{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -227,7 +227,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced{window=\"7d\"}",
|
"expr": "max(postmark_outbound_bounced{window=\"7d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -296,7 +296,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent{window=\"1d\"}",
|
"expr": "max(postmark_outbound_sent{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -357,7 +357,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent{window=\"7d\"}",
|
"expr": "max(postmark_outbound_sent{window=\"7d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -405,7 +405,7 @@
|
|||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"title": "Postmark API Up",
|
"title": "Limit Used (30d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
"type": "prometheus",
|
"type": "prometheus",
|
||||||
"uid": "atlas-vm"
|
"uid": "atlas-vm"
|
||||||
@ -418,7 +418,137 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_api_up",
|
"expr": "max(postmark_sending_limit_used_percent)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "orange",
|
||||||
|
"value": 85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 95
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percent",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 1
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Send Limit (30d)",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 4
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "max(postmark_sending_limit)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "rgba(115, 115, 115, 1)",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Postmark API Up",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "max(postmark_api_up)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -464,7 +594,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 8,
|
"id": 10,
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"title": "Last Success",
|
"title": "Last Success",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -474,12 +604,12 @@
|
|||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 4,
|
"h": 4,
|
||||||
"w": 6,
|
"w": 6,
|
||||||
"x": 18,
|
"x": 6,
|
||||||
"y": 4
|
"y": 8
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_last_success_timestamp_seconds",
|
"expr": "max(postmark_last_success_timestamp_seconds)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -525,7 +655,129 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 9,
|
"id": 11,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Exporter Errors",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 12,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(postmark_request_errors_total)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "rgba(115, 115, 115, 1)",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Limit Used (30d)",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "max(postmark_sending_limit_used)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "rgba(115, 115, 115, 1)",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Bounce Rate (1d vs 7d)",
|
"title": "Bounce Rate (1d vs 7d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -536,11 +788,11 @@
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 8
|
"y": 12
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate",
|
"expr": "max by (window) (postmark_outbound_bounce_rate)",
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
"legendFormat": "{{window}}"
|
"legendFormat": "{{window}}"
|
||||||
}
|
}
|
||||||
@ -562,7 +814,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 10,
|
"id": 14,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Bounced (1d vs 7d)",
|
"title": "Bounced (1d vs 7d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -573,11 +825,11 @@
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 12,
|
"x": 12,
|
||||||
"y": 8
|
"y": 12
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced",
|
"expr": "max by (window) (postmark_outbound_bounced)",
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
"legendFormat": "{{window}}"
|
"legendFormat": "{{window}}"
|
||||||
}
|
}
|
||||||
@ -599,7 +851,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 11,
|
"id": 15,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Sent (1d vs 7d)",
|
"title": "Sent (1d vs 7d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -610,11 +862,11 @@
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 16
|
"y": 20
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent",
|
"expr": "max by (window) (postmark_outbound_sent)",
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
"legendFormat": "{{window}}"
|
"legendFormat": "{{window}}"
|
||||||
}
|
}
|
||||||
@ -636,7 +888,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 12,
|
"id": 16,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Exporter Errors",
|
"title": "Exporter Errors",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -647,11 +899,11 @@
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 12,
|
"x": 12,
|
||||||
"y": 16
|
"y": 20
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_request_errors_total",
|
"expr": "sum(postmark_request_errors_total)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -802,7 +802,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounce_rate{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -878,7 +878,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounced{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -941,7 +941,7 @@
|
|||||||
{
|
{
|
||||||
"id": 32,
|
"id": 32,
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"title": "Mail Sent (1d)",
|
"title": "Mail Limit Used (30d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
"type": "prometheus",
|
"type": "prometheus",
|
||||||
"uid": "atlas-vm"
|
"uid": "atlas-vm"
|
||||||
@ -954,7 +954,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent{window=\"1d\"}",
|
"expr": "max(postmark_sending_limit_used_percent)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -968,20 +968,28 @@
|
|||||||
"mode": "absolute",
|
"mode": "absolute",
|
||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"color": "rgba(115, 115, 115, 1)",
|
"color": "green",
|
||||||
"value": null
|
"value": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"color": "green",
|
"color": "yellow",
|
||||||
"value": 1
|
"value": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "orange",
|
||||||
|
"value": 85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 95
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"unit": "none",
|
"unit": "percent",
|
||||||
"custom": {
|
"custom": {
|
||||||
"displayMode": "auto"
|
"displayMode": "auto"
|
||||||
},
|
},
|
||||||
"decimals": 0
|
"decimals": 1
|
||||||
},
|
},
|
||||||
"overrides": []
|
"overrides": []
|
||||||
},
|
},
|
||||||
@ -1022,7 +1030,7 @@
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_api_up",
|
"expr": "max(postmark_api_up)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -29,7 +29,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounce_rate{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -98,7 +98,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate{window=\"7d\"}",
|
"expr": "max(postmark_outbound_bounce_rate{window=\"7d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -167,7 +167,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounced{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -236,7 +236,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced{window=\"7d\"}",
|
"expr": "max(postmark_outbound_bounced{window=\"7d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -305,7 +305,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent{window=\"1d\"}",
|
"expr": "max(postmark_outbound_sent{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -366,7 +366,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent{window=\"7d\"}",
|
"expr": "max(postmark_outbound_sent{window=\"7d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -414,7 +414,7 @@ data:
|
|||||||
{
|
{
|
||||||
"id": 7,
|
"id": 7,
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"title": "Postmark API Up",
|
"title": "Limit Used (30d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
"type": "prometheus",
|
"type": "prometheus",
|
||||||
"uid": "atlas-vm"
|
"uid": "atlas-vm"
|
||||||
@ -427,7 +427,137 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_api_up",
|
"expr": "max(postmark_sending_limit_used_percent)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "yellow",
|
||||||
|
"value": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "orange",
|
||||||
|
"value": 85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 95
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "percent",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 1
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Send Limit (30d)",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 4
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "max(postmark_sending_limit)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "rgba(115, 115, 115, 1)",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Postmark API Up",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 0,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "max(postmark_api_up)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -473,7 +603,7 @@ data:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 8,
|
"id": 10,
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"title": "Last Success",
|
"title": "Last Success",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -483,12 +613,12 @@ data:
|
|||||||
"gridPos": {
|
"gridPos": {
|
||||||
"h": 4,
|
"h": 4,
|
||||||
"w": 6,
|
"w": 6,
|
||||||
"x": 18,
|
"x": 6,
|
||||||
"y": 4
|
"y": 8
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_last_success_timestamp_seconds",
|
"expr": "max(postmark_last_success_timestamp_seconds)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -534,7 +664,129 @@ data:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 9,
|
"id": 11,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Exporter Errors",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 12,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "sum(postmark_request_errors_total)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "rgba(115, 115, 115, 1)",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Limit Used (30d)",
|
||||||
|
"datasource": {
|
||||||
|
"type": "prometheus",
|
||||||
|
"uid": "atlas-vm"
|
||||||
|
},
|
||||||
|
"gridPos": {
|
||||||
|
"h": 4,
|
||||||
|
"w": 6,
|
||||||
|
"x": 18,
|
||||||
|
"y": 8
|
||||||
|
},
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"expr": "max(postmark_sending_limit_used)",
|
||||||
|
"refId": "A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fieldConfig": {
|
||||||
|
"defaults": {
|
||||||
|
"color": {
|
||||||
|
"mode": "thresholds"
|
||||||
|
},
|
||||||
|
"mappings": [],
|
||||||
|
"thresholds": {
|
||||||
|
"mode": "absolute",
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"color": "rgba(115, 115, 115, 1)",
|
||||||
|
"value": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "green",
|
||||||
|
"value": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"unit": "none",
|
||||||
|
"custom": {
|
||||||
|
"displayMode": "auto"
|
||||||
|
},
|
||||||
|
"decimals": 0
|
||||||
|
},
|
||||||
|
"overrides": []
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"colorMode": "value",
|
||||||
|
"graphMode": "area",
|
||||||
|
"justifyMode": "center",
|
||||||
|
"reduceOptions": {
|
||||||
|
"calcs": [
|
||||||
|
"lastNotNull"
|
||||||
|
],
|
||||||
|
"fields": "",
|
||||||
|
"values": false
|
||||||
|
},
|
||||||
|
"textMode": "value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Bounce Rate (1d vs 7d)",
|
"title": "Bounce Rate (1d vs 7d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -545,11 +797,11 @@ data:
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 8
|
"y": 12
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate",
|
"expr": "max by (window) (postmark_outbound_bounce_rate)",
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
"legendFormat": "{{window}}"
|
"legendFormat": "{{window}}"
|
||||||
}
|
}
|
||||||
@ -571,7 +823,7 @@ data:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 10,
|
"id": 14,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Bounced (1d vs 7d)",
|
"title": "Bounced (1d vs 7d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -582,11 +834,11 @@ data:
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 12,
|
"x": 12,
|
||||||
"y": 8
|
"y": 12
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced",
|
"expr": "max by (window) (postmark_outbound_bounced)",
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
"legendFormat": "{{window}}"
|
"legendFormat": "{{window}}"
|
||||||
}
|
}
|
||||||
@ -608,7 +860,7 @@ data:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 11,
|
"id": 15,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Sent (1d vs 7d)",
|
"title": "Sent (1d vs 7d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -619,11 +871,11 @@ data:
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 0,
|
"x": 0,
|
||||||
"y": 16
|
"y": 20
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent",
|
"expr": "max by (window) (postmark_outbound_sent)",
|
||||||
"refId": "A",
|
"refId": "A",
|
||||||
"legendFormat": "{{window}}"
|
"legendFormat": "{{window}}"
|
||||||
}
|
}
|
||||||
@ -645,7 +897,7 @@ data:
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 12,
|
"id": 16,
|
||||||
"type": "timeseries",
|
"type": "timeseries",
|
||||||
"title": "Exporter Errors",
|
"title": "Exporter Errors",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
@ -656,11 +908,11 @@ data:
|
|||||||
"h": 8,
|
"h": 8,
|
||||||
"w": 12,
|
"w": 12,
|
||||||
"x": 12,
|
"x": 12,
|
||||||
"y": 16
|
"y": 20
|
||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_request_errors_total",
|
"expr": "sum(postmark_request_errors_total)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -811,7 +811,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounce_rate{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounce_rate{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -887,7 +887,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_bounced{window=\"1d\"}",
|
"expr": "max(postmark_outbound_bounced{window=\"1d\"})",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -950,7 +950,7 @@ data:
|
|||||||
{
|
{
|
||||||
"id": 32,
|
"id": 32,
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"title": "Mail Sent (1d)",
|
"title": "Mail Limit Used (30d)",
|
||||||
"datasource": {
|
"datasource": {
|
||||||
"type": "prometheus",
|
"type": "prometheus",
|
||||||
"uid": "atlas-vm"
|
"uid": "atlas-vm"
|
||||||
@ -963,7 +963,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_outbound_sent{window=\"1d\"}",
|
"expr": "max(postmark_sending_limit_used_percent)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -977,20 +977,28 @@ data:
|
|||||||
"mode": "absolute",
|
"mode": "absolute",
|
||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"color": "rgba(115, 115, 115, 1)",
|
"color": "green",
|
||||||
"value": null
|
"value": null
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"color": "green",
|
"color": "yellow",
|
||||||
"value": 1
|
"value": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "orange",
|
||||||
|
"value": 85
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"color": "red",
|
||||||
|
"value": 95
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"unit": "none",
|
"unit": "percent",
|
||||||
"custom": {
|
"custom": {
|
||||||
"displayMode": "auto"
|
"displayMode": "auto"
|
||||||
},
|
},
|
||||||
"decimals": 0
|
"decimals": 1
|
||||||
},
|
},
|
||||||
"overrides": []
|
"overrides": []
|
||||||
},
|
},
|
||||||
@ -1031,7 +1039,7 @@ data:
|
|||||||
},
|
},
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"expr": "postmark_api_up",
|
"expr": "max(postmark_api_up)",
|
||||||
"refId": "A"
|
"refId": "A"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@ -39,6 +39,14 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: postmark-exporter
|
name: postmark-exporter
|
||||||
key: relay-password
|
key: relay-password
|
||||||
|
- name: POSTMARK_SENDING_LIMIT
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postmark-exporter
|
||||||
|
key: sending-limit
|
||||||
|
optional: true
|
||||||
|
- name: POSTMARK_SENDING_LIMIT_WINDOW
|
||||||
|
value: "30d"
|
||||||
- name: POLL_INTERVAL_SECONDS
|
- name: POLL_INTERVAL_SECONDS
|
||||||
value: "60"
|
value: "60"
|
||||||
- name: LISTEN_PORT
|
- name: LISTEN_PORT
|
||||||
|
|||||||
@ -26,6 +26,7 @@ data:
|
|||||||
Window("today", 0),
|
Window("today", 0),
|
||||||
Window("1d", 1),
|
Window("1d", 1),
|
||||||
Window("7d", 7),
|
Window("7d", 7),
|
||||||
|
Window("30d", 30),
|
||||||
]
|
]
|
||||||
|
|
||||||
API_BASE = os.environ.get("POSTMARK_API_BASE", "https://api.postmarkapp.com").rstrip("/")
|
API_BASE = os.environ.get("POSTMARK_API_BASE", "https://api.postmarkapp.com").rstrip("/")
|
||||||
@ -35,6 +36,12 @@ data:
|
|||||||
|
|
||||||
PRIMARY_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN", "").strip()
|
PRIMARY_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN", "").strip()
|
||||||
FALLBACK_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN_FALLBACK", "").strip()
|
FALLBACK_TOKEN = os.environ.get("POSTMARK_SERVER_TOKEN_FALLBACK", "").strip()
|
||||||
|
LIMIT_WINDOW = os.environ.get("POSTMARK_SENDING_LIMIT_WINDOW", "30d").strip()
|
||||||
|
LIMIT_RAW = os.environ.get("POSTMARK_SENDING_LIMIT", "").strip()
|
||||||
|
try:
|
||||||
|
SENDING_LIMIT = float(LIMIT_RAW) if LIMIT_RAW else 0.0
|
||||||
|
except ValueError:
|
||||||
|
SENDING_LIMIT = 0.0
|
||||||
|
|
||||||
EXPORTER_INFO = Info("postmark_exporter", "Exporter build info")
|
EXPORTER_INFO = Info("postmark_exporter", "Exporter build info")
|
||||||
EXPORTER_INFO.info(
|
EXPORTER_INFO.info(
|
||||||
@ -69,6 +76,18 @@ data:
|
|||||||
"Outbound bounce rate percentage within the selected window",
|
"Outbound bounce rate percentage within the selected window",
|
||||||
labelnames=("window",),
|
labelnames=("window",),
|
||||||
)
|
)
|
||||||
|
POSTMARK_SENDING_LIMIT_GAUGE = Gauge(
|
||||||
|
"postmark_sending_limit",
|
||||||
|
"Configured Postmark sending limit for the active account",
|
||||||
|
)
|
||||||
|
POSTMARK_SENDING_LIMIT_USED = Gauge(
|
||||||
|
"postmark_sending_limit_used",
|
||||||
|
"Messages sent within the configured send limit window",
|
||||||
|
)
|
||||||
|
POSTMARK_SENDING_LIMIT_USED_PERCENT = Gauge(
|
||||||
|
"postmark_sending_limit_used_percent",
|
||||||
|
"Percent of the configured send limit used within the limit window",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def fetch_outbound_stats(token: str, window: Window) -> dict:
|
def fetch_outbound_stats(token: str, window: Window) -> dict:
|
||||||
@ -90,15 +109,25 @@ data:
|
|||||||
|
|
||||||
|
|
||||||
def update_metrics(token: str) -> None:
|
def update_metrics(token: str) -> None:
|
||||||
|
sent_by_window = {}
|
||||||
for window in WINDOWS:
|
for window in WINDOWS:
|
||||||
data = fetch_outbound_stats(token, window)
|
data = fetch_outbound_stats(token, window)
|
||||||
sent = int(data.get("Sent", 0) or 0)
|
sent = int(data.get("Sent", 0) or 0)
|
||||||
bounced = int(data.get("Bounced", 0) or 0)
|
bounced = int(data.get("Bounced", 0) or 0)
|
||||||
rate = (bounced / sent * 100.0) if sent else 0.0
|
rate = (bounced / sent * 100.0) if sent else 0.0
|
||||||
|
sent_by_window[window.label] = sent
|
||||||
POSTMARK_OUTBOUND_SENT.labels(window=window.label).set(sent)
|
POSTMARK_OUTBOUND_SENT.labels(window=window.label).set(sent)
|
||||||
POSTMARK_OUTBOUND_BOUNCED.labels(window=window.label).set(bounced)
|
POSTMARK_OUTBOUND_BOUNCED.labels(window=window.label).set(bounced)
|
||||||
POSTMARK_OUTBOUND_BOUNCE_RATE.labels(window=window.label).set(rate)
|
POSTMARK_OUTBOUND_BOUNCE_RATE.labels(window=window.label).set(rate)
|
||||||
|
|
||||||
|
POSTMARK_SENDING_LIMIT_GAUGE.set(SENDING_LIMIT)
|
||||||
|
limit_window_sent = sent_by_window.get(LIMIT_WINDOW, 0)
|
||||||
|
POSTMARK_SENDING_LIMIT_USED.set(limit_window_sent)
|
||||||
|
if SENDING_LIMIT:
|
||||||
|
POSTMARK_SENDING_LIMIT_USED_PERCENT.set(limit_window_sent / SENDING_LIMIT * 100.0)
|
||||||
|
else:
|
||||||
|
POSTMARK_SENDING_LIMIT_USED_PERCENT.set(0.0)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
if not PRIMARY_TOKEN and not FALLBACK_TOKEN:
|
if not PRIMARY_TOKEN and not FALLBACK_TOKEN:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user