1
1
"""Services and functions that can be used to create custom actions"""
2
+ import contextlib
2
3
import logging
3
4
from typing import Dict , List
4
5
5
6
import bugzilla as rh_bugzilla
6
7
from atlassian import Jira
8
+ from prometheus_client import Counter , Summary
7
9
8
10
from src .app import environment
9
11
from src .jbi .models import Actions
16
18
ServiceHealth = Dict [str , bool ]
17
19
18
20
21
+ class InstrumentedClient :
22
+ """This class wraps an object and increments a counter everytime
23
+ the specieds methods are called, and times their execution.
24
+ """
25
+
26
+ counters : Dict [str , Counter ] = {}
27
+ timers : Dict [str , Counter ] = {}
28
+
29
+ def __init__ (self , wrapped , prefix , methods ):
30
+ self .wrapped = wrapped
31
+ self .methods = methods
32
+
33
+ # We have a single instrument per prefix. Methods are reported as labels.
34
+ counter_name = prefix + "_methods_total"
35
+ if counter_name not in self .counters :
36
+ self .counters [counter_name ] = Counter (
37
+ counter_name , f"{ prefix } method calls" , labelnames = ["method" ]
38
+ )
39
+ self .counter = self .counters [counter_name ]
40
+
41
+ timer_name = prefix + "_methods_milliseconds"
42
+ if timer_name not in self .timers :
43
+ self .timers [timer_name ] = Summary (
44
+ timer_name , f"{ prefix } method timing" , labelnames = ["method" ]
45
+ )
46
+ self .timer = self .timers [timer_name ]
47
+
48
+ def __getattr__ (self , attr ):
49
+ if attr in self .methods :
50
+ self .counter .labels (method = attr ).inc ()
51
+ timer_cm = self .timer .labels (method = attr ).time ()
52
+ else :
53
+ timer_cm = contextlib .nullcontext ()
54
+
55
+ with timer_cm :
56
+ return getattr (self .wrapped , attr )
57
+
58
+
19
59
def get_jira ():
20
60
"""Get atlassian Jira Service"""
21
- return Jira (
61
+ jira_client = Jira (
22
62
url = settings .jira_base_url ,
23
63
username = settings .jira_username ,
24
64
password = settings .jira_api_key , # package calls this param 'password' but actually expects an api key
25
65
cloud = True , # we run against an instance of Jira cloud
26
66
)
67
+ instrumented_methods = (
68
+ "update_issue_field" ,
69
+ "set_issue_status" ,
70
+ "issue_add_comment" ,
71
+ "create_issue" ,
72
+ )
73
+ return InstrumentedClient (
74
+ wrapped = jira_client , prefix = "jbi_jira" , methods = instrumented_methods
75
+ )
27
76
28
77
29
78
def jira_visible_projects (jira = None ) -> List [Dict ]:
@@ -35,9 +84,17 @@ def jira_visible_projects(jira=None) -> List[Dict]:
35
84
36
85
def get_bugzilla ():
37
86
"""Get bugzilla service"""
38
- return rh_bugzilla .Bugzilla (
87
+ bugzilla_client = rh_bugzilla .Bugzilla (
39
88
settings .bugzilla_base_url , api_key = str (settings .bugzilla_api_key )
40
89
)
90
+ instrumented_methods = (
91
+ "get_bug" ,
92
+ "get_comments" ,
93
+ "update_bugs" ,
94
+ )
95
+ return InstrumentedClient (
96
+ wrapped = bugzilla_client , prefix = "jbi_bugzilla" , methods = instrumented_methods
97
+ )
41
98
42
99
43
100
def _bugzilla_check_health () -> ServiceHealth :
0 commit comments