@@ -64,19 +64,16 @@ func prometheusDomainStatsTypeDesc(metric string, help string) *prometheus.Desc
6464
6565// NewExporter returns an initialized exporter.
6666func NewExporter () * Exporter {
67- // NewMailgunFromEnv requires MG_DOMAIN to get set, even though we don't need it for listing all domains
68- err := os .Setenv ("MG_DOMAIN" , "dummy" )
69- if err != nil {
70- log .Fatal ().Err (err ).Msgf ("%v" , err )
67+ apiKey := os .Getenv ("MG_API_KEY" )
68+ if apiKey == "" {
69+ log .Fatal ().Msg ("MG_API_KEY environment variable is required" )
7170 }
7271
73- mg , err := mailgun .NewMailgunFromEnv ()
74- APIBase , exists := os .LookupEnv ("API_BASE" )
75- if exists {
76- mg .SetAPIBase (APIBase )
77- }
78- if err != nil {
79- log .Fatal ().Err (err ).Msgf ("%v" , err )
72+ mg := mailgun .NewMailgun (apiKey )
73+ if apiBase , exists := os .LookupEnv ("API_BASE" ); exists {
74+ if err := mg .SetAPIBase (apiBase ); err != nil {
75+ log .Fatal ().Err (err ).Msgf ("Failed to set API base: %v" , err )
76+ }
8077 }
8178
8279 return NewExporterWithClient (NewMailgunClientWrapper (mg ))
@@ -187,118 +184,94 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
187184
188185 metrics , err := e .mg .GetMetrics (ctx , domain )
189186 if err != nil {
190- log .Error ().Err (err )
187+ log .Error ().Err (err ).Msgf ("Failed to get metrics for domain %s" , domain )
188+ continue
191189 }
192190
193- var acceptedTotalIncoming = float64 (0 )
194- var acceptedTotalOutgoing = float64 (0 )
195- var clickedTotal = float64 (0 )
196- var complainedTotal = float64 (0 )
197- var deliveredHttpTotal = float64 (0 )
198- var deliveredSmtpTotal = float64 (0 )
199- var failedPermanentBounce = float64 (0 )
200- var failedPermanentDelayedBounce = float64 (0 )
201- var failedPermanentSuppressBounce = float64 (0 )
202- var failedPermanentSuppressComplaint = float64 (0 )
203- var failedPermanentSuppressUnsubscribe = float64 (0 )
204- var failedTemporaryEspblock = float64 (0 )
205- var openedTotal = float64 (0 )
206- var storedTotal = float64 (0 )
207- var unsubscribedTotal = float64 (0 )
208-
209- for _ , stat := range stats {
210- acceptedTotalIncoming += float64 (stat .Accepted .Incoming )
211- acceptedTotalOutgoing += float64 (stat .Accepted .Outgoing )
212- clickedTotal += float64 (stat .Clicked .Total )
213- complainedTotal += float64 (stat .Complained .Total )
214- complainedTotal += float64 (stat .Complained .Total )
215- deliveredHttpTotal += float64 (stat .Delivered .Http )
216- deliveredSmtpTotal += float64 (stat .Delivered .Smtp )
217- failedPermanentBounce += float64 (stat .Failed .Permanent .Bounce )
218- failedPermanentDelayedBounce += float64 (stat .Failed .Permanent .DelayedBounce )
219- failedPermanentSuppressBounce += float64 (stat .Failed .Permanent .SuppressBounce )
220- failedPermanentSuppressComplaint += float64 (stat .Failed .Permanent .SuppressComplaint )
221- failedPermanentSuppressUnsubscribe += float64 (stat .Failed .Permanent .SuppressUnsubscribe )
222- failedTemporaryEspblock += float64 (stat .Failed .Temporary .Espblock )
223- openedTotal += float64 (stat .Opened .Total )
224- storedTotal += float64 (stat .Stored .Total )
225- unsubscribedTotal += float64 (stat .Unsubscribed .Total )
191+ // Helper function to safely get uint64 pointer value
192+ getVal := func (p * uint64 ) float64 {
193+ if p == nil {
194+ return 0
195+ }
196+ return float64 (* p )
226197 }
227198
228199 // Begin Accepted Total
229200 ch <- prometheus .MustNewConstMetric (
230201 e .acceptedTotal ,
231202 prometheus .CounterValue ,
232- acceptedTotalIncoming ,
203+ getVal ( metrics . AcceptedIncomingCount ) ,
233204 domain , "incoming" ,
234205 )
235206 ch <- prometheus .MustNewConstMetric (
236207 e .acceptedTotal ,
237208 prometheus .CounterValue ,
238- acceptedTotalOutgoing ,
209+ getVal ( metrics . AcceptedOutgoingCount ) ,
239210 domain , "outgoing" ,
240211 )
241212 // End Accepted Total
242213
243- ch <- prometheus .MustNewConstMetric (e .clickedTotal , prometheus .CounterValue , clickedTotal , domain )
244- ch <- prometheus .MustNewConstMetric (e .complainedTotal , prometheus .CounterValue , complainedTotal , domain )
214+ ch <- prometheus .MustNewConstMetric (e .clickedTotal , prometheus .CounterValue , getVal ( metrics . ClickedCount ) , domain )
215+ ch <- prometheus .MustNewConstMetric (e .complainedTotal , prometheus .CounterValue , getVal ( metrics . ComplainedCount ) , domain )
245216
246217 // Begin Delivered Total
247218 ch <- prometheus .MustNewConstMetric (
248219 e .deliveredTotal ,
249220 prometheus .CounterValue ,
250- deliveredHttpTotal ,
221+ getVal ( metrics . DeliveredHTTPCount ) ,
251222 domain , "http" ,
252223 )
253224 ch <- prometheus .MustNewConstMetric (
254225 e .deliveredTotal ,
255226 prometheus .CounterValue ,
256- deliveredSmtpTotal ,
227+ getVal ( metrics . DeliveredSMTPCount ) ,
257228 domain , "smtp" ,
258229 )
259230 // End Delivered Total
260231
261232 // Begin Failed Permanent Total
233+ // Note: v5 API provides different granularity for permanent failures
234+ // Using hard_bounces as "bounce" and soft_bounces + delayed_bounce combined for other categories
262235 ch <- prometheus .MustNewConstMetric (
263236 e .failedPermanentTotal ,
264237 prometheus .CounterValue ,
265- failedPermanentBounce ,
238+ getVal ( metrics . HardBouncesCount ) ,
266239 domain , "bounce" ,
267240 )
268241 ch <- prometheus .MustNewConstMetric (
269242 e .failedPermanentTotal ,
270243 prometheus .CounterValue ,
271- failedPermanentDelayedBounce ,
244+ getVal ( metrics . DelayedBounceCount ) ,
272245 domain , "delayed_bounce" ,
273246 )
274247 ch <- prometheus .MustNewConstMetric (
275248 e .failedPermanentTotal ,
276249 prometheus .CounterValue ,
277- failedPermanentSuppressBounce ,
250+ getVal ( metrics . SuppressedBouncesCount ) ,
278251 domain , "suppress_bounce" ,
279252 )
280253 ch <- prometheus .MustNewConstMetric (
281254 e .failedPermanentTotal ,
282255 prometheus .CounterValue ,
283- failedPermanentSuppressComplaint ,
256+ getVal ( metrics . SuppressedComplaintsCount ) ,
284257 domain , "suppress_complaint" ,
285258 )
286259 ch <- prometheus .MustNewConstMetric (e .failedPermanentTotal , prometheus .CounterValue ,
287- failedPermanentSuppressUnsubscribe ,
260+ getVal ( metrics . SuppressedUnsubscribedCount ) ,
288261 domain , "suppress_unsubscribe" ,
289262 )
290263 // End Failed Permanent Total
291264
292265 ch <- prometheus .MustNewConstMetric (
293266 e .failedTemporaryTotal ,
294267 prometheus .CounterValue ,
295- failedTemporaryEspblock ,
268+ getVal ( metrics . TemporaryFailedESPBlockCount ) ,
296269 domain , "esp_block" ,
297270 )
298271
299- ch <- prometheus .MustNewConstMetric (e .openedTotal , prometheus .CounterValue , openedTotal , domain )
300- ch <- prometheus .MustNewConstMetric (e .storedTotal , prometheus .CounterValue , storedTotal , domain )
301- ch <- prometheus .MustNewConstMetric (e .unsubscribedTotal , prometheus .CounterValue , unsubscribedTotal , domain )
272+ ch <- prometheus .MustNewConstMetric (e .openedTotal , prometheus .CounterValue , getVal ( metrics . OpenedCount ) , domain )
273+ ch <- prometheus .MustNewConstMetric (e .storedTotal , prometheus .CounterValue , getVal ( metrics . StoredCount ) , domain )
274+ ch <- prometheus .MustNewConstMetric (e .unsubscribedTotal , prometheus .CounterValue , getVal ( metrics . UnsubscribedCount ) , domain )
302275 }
303276
304277 ch <- prometheus .MustNewConstMetric (e .up , prometheus .GaugeValue , 1 )
0 commit comments