summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/stl/trex_stl_lib/utils/GAObjClass.py
blob: be81175ea8b518675ec124bf4db6fb935ed4d713 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
try:  # Python2
    import Queue
    from urllib2 import *
except:  # Python3
    import queue as Queue
    from urllib.request import *
    from urllib.error import *
import threading
import sys
from time import sleep
from pprint import pprint

"""
GAObjClass is a class destined to send Google Analytics Information.

cid - unique number per user.
command - the Event Category rubric appears on site. type: TEXT
action - the Event Action rubric appears on site - type: TEXT
label - the Event Label rubric - type: TEXT
value - the event value metric - type: INTEGER

QUOTAS:
1 single payload - up to 8192Bytes
batched:
A maximum of 20 hits can be specified per request.
The total size of all hit payloads cannot be greater than 16K bytes.
No single hit payload can be greater than 8K bytes.
"""
url_single = 'https://www.google-analytics.com/collect'  # sending single event
url_batched = 'https://www.google-analytics.com/batch'  # sending batched events
url_debug = 'https://www.google-analytics.com/debug/collect'  # verifying hit is valid
url_conn = 'http://172.217.2.196'  # testing internet connection to this address (google-analytics server)


# ..................................................................class GA_ObjClass................................................................
class GA_ObjClass:
    def __init__(self, cid, trackerID, appName, appVer):
        self.cid = cid
        self.trackerID = trackerID
        self.appName = appName
        self.appVer = appVer
        self.payload = ''
        self.payload = GA_ObjClass.generate_payload(self)
        self.size = sys.getsizeof(self.payload)

    def generate_payload(self):
        self.payload += 'v=1&t=event&tid=' + str(self.trackerID)
        self.payload += '&cid=' + str(self.cid)
        self.payload += '&an=' + str(self.appName)
        self.payload += '&av=' + str(self.appVer)
        return self.payload


# ..................................................................class GA_EVENT_ObjClass................................................................
class GA_EVENT_ObjClass(GA_ObjClass):
    def __init__(self, cid, trackerID, command, action, label, value, appName, appVer):
        GA_ObjClass.__init__(self, cid, trackerID, appName, appVer)
        self.command = command
        self.action = action
        self.label = label
        self.value = value
        self.payload = self.generate_payload()
        self.size = sys.getsizeof(self.payload)

    def generate_payload(self):
        self.payload += '&ec=' + str(self.command)
        self.payload += '&ea=' + str(self.action)
        self.payload += '&el=' + str(self.label)
        self.payload += '&ev=' + str(self.value)
        return self.payload


# ..................................................................class GA_EXCEPTION_ObjClass................................................................
# ExceptionFatal - BOOLEAN
class GA_EXCEPTION_ObjClass(GA_ObjClass):
    def __init__(self, cid, trackerID, ExceptionName, ExceptionFatal, appName, appVer):
        GA_ObjClass.__init__(self, cid, trackerID, appName, appVer)
        self.ExceptionName = ExceptionName
        self.ExceptionFatal = ExceptionFatal
        self.payload = self.generate_payload()

    def generate_payload(self):
        self.payload += '&exd=' + str(self.ExceptionName)
        self.payload += '&exf=' + str(self.ExceptionFatal)
        return self.payload


# ..................................................................class GA_TESTING_ObjClass................................................................
class GA_TESTING_ObjClass(GA_ObjClass):
    def __init__(self, cid, trackerID, TRexMode, TestName, SetupName, appName, ActionNumber, appVer, TestType, Mppspc,
                 GoldenMin, GoldenMax):
        GA_ObjClass.__init__(self, cid, trackerID, appName, appVer)
        self.ActionNumber = ActionNumber
        self.TRexMode = TRexMode
        self.TestName = TestName
        self.SetupName = SetupName
        self.TestType = TestType
        self.Mppspc = Mppspc
        self.GoldenMin = GoldenMin
        self.GoldenMax = GoldenMax
        self.payload = self.generate_payload()
        self.size = sys.getsizeof(self.payload)

    def generate_payload(self):
        self.payload += '&ec=TRexTests'
        self.payload += '&ea=' + str(self.ActionNumber)
        self.payload += '&cd2=' + str(self.TRexMode)
        self.payload += '&cd1=' + str(self.TestName)
        self.payload += '&cd3=' + str(self.SetupName)
        self.payload += '&cd4=' + str(self.TestType)
        self.payload += '&cm1=' + str(self.Mppspc)
        self.payload += '&cm2=' + str(self.GoldenMin)
        self.payload += '&cm3=' + str(self.GoldenMax)
        return self.payload

        # .....................................................................class ga_Thread.................................................................


"""

Google analytics thread manager:

will report and empty queue of google analytics items to GA server, every Timeout (parameter given on initialization)
will perform connectivity check every timeout*10 seconds

"""


class ga_Thread(threading.Thread):
    def __init__(self, threadID, gManager):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.gManager = gManager

    def run(self):
        keepAliveCounter = 0
        # sys.stdout.write('thread started \n')
        # sys.stdout.flush()
        while True:
            if (keepAliveCounter == 10):
                keepAliveCounter = 0
                if (self.gManager.internet_on() == True):
                    self.gManager.connectedToInternet = 1
                else:
                    self.gManager.connectedToInternet = 0
            sleep(self.gManager.Timeout)
            keepAliveCounter += 1
            if not self.gManager.GA_q.empty():
                self.gManager.threadLock.acquire(1)
                #               sys.stdout.write('lock acquired: reporting to GA \n')
                #               sys.stdout.flush()
                if (self.gManager.connectedToInternet == 1):
                    self.gManager.emptyAndReportQ()
                self.gManager.threadLock.release()


# sys.stdout.write('finished \n')
#               sys.stdout.flush()
# .....................................................................class GAmanager.................................................................
"""

Google ID - specify tracker property, example: UA-75220362-2 (when the suffix '2' specifies the analytics property profile)

UserID - unique userID, this will differ between users on GA

appName - s string to determine app name

appVer - a string to determine app version

QueueSize - the size of the queue that holds reported items. once the Queue is full:
            on blocking mode:
                will block program until next submission to GA server, which will make new space
            on non-blocking mode:
                will drop new requests

Timout - the timeout the queue uses between data transmissions. Timeout should be shorter than the time it takes to generate 20 events. MIN VALUE = 11 seconds

User Permission - the user must accept data transmission, use this flag as 1/0 flag, when UserPermission=1 allows data collection
 
BlockingMode - set to 1 if you wish every Google Analytic Object will be submitted and processed, with no drops allowed. 
               this will block the running of the program until every item is processed

*** Restriction - Google's restriction for amount of packages being sent per session per second is: 1 event per second, per session. session length is 30min ***
"""


class GAmanager:
    def __init__(self, GoogleID, UserID, appName, appVer, QueueSize, Timeout, UserPermission, BlockingMode):
        self.UserID = UserID
        self.GoogleID = GoogleID
        self.QueueSize = QueueSize
        self.Timeout = Timeout
        self.appName = appName
        self.appVer = appVer
        self.UserPermission = UserPermission
        self.GA_q = Queue.Queue(QueueSize)
        self.thread = ga_Thread(UserID, self)
        self.threadLock = threading.Lock()
        self.BlockingMode = BlockingMode
        self.connectedToInternet = 0
        if (self.internet_on() == True):
            #           sys.stdout.write('internet connection active \n')
            #           sys.stdout.flush()
            self.connectedToInternet = 1
        else:
            self.connectedToInternet = 0

    def gaAddAction(self, Event, action, label, value):
        self.gaAddObject(
            GA_EVENT_ObjClass(self.UserID, self.GoogleID, Event, action, label, value, self.appName, self.appVer))

    def gaAddException(self, ExceptionName, ExceptionFatal):
        self.gaAddObject(
            GA_EXCEPTION_ObjClass(self.UserID, self.GoogleID, ExceptionName, ExceptionFatal, self.appName, self.appVer))

    def gaAddObject(self, Object):
        if (self.BlockingMode == 1):
            while (self.GA_q.full()):
                sleep(self.Timeout)
            #               sys.stdout.write('blocking mode=1 \n queue full - sleeping for timeout \n') # within Timout, the thread will empty part of the queue
            #               sys.stdout.flush()
        lockState = self.threadLock.acquire(self.BlockingMode)
        if (lockState == 1):
            #           sys.stdout.write('got lock, adding item \n')
            #           sys.stdout.flush()
            try:
                self.GA_q.put_nowait(Object)
            #               sys.stdout.write('got lock, item added \n')
            #               sys.stdout.flush()
            except Queue.Full:
                #               sys.stdout.write('Queue full \n')
                #               sys.stdout.flush()
                pass
            self.threadLock.release()

    def emptyQueueToList(self, obj_list):
        items = 0
        while ((not self.GA_q.empty()) and (items < 20)):
            obj_list.append(self.GA_q.get_nowait().payload)
            items += 1
        #           print items
        return obj_list

    def reportBatched(self, batched):
        req = Request(url_batched, data=batched.encode('ascii'))
        urlopen(req)

    #       pprint(r.json())

    def emptyAndReportQ(self):
        obj_list = []
        obj_list = self.emptyQueueToList(obj_list)
        if (len(obj_list) == 0):
            return
        batched = '\n'.join(obj_list)
        #       print sys.getsizeof(batched)
        #       print batched # - for debug
        self.reportBatched(batched)

    def printSelf(self):
        print('remaining in queue:')
        while not self.GA_q.empty():
            obj = self.GA_q.get_nowait()
            print(obj.payload)

    def internet_on(self):
        try:
            urlopen(url_conn, timeout=10)
            return True
        except URLError as err:
            pass
        return False

    def activate(self):
        if (self.UserPermission == 1):
            self.thread.start()


# .....................................................................class GAmanager_Regression.................................................................
"""
            *-*-*-*-Google Analytics Regression Manager-*-*-*-*
            attributes:
GoogleID - the tracker ID that Google uses in order to track the activity of a property. for regression use: 'UA-75220362-4'
AnalyticsUserID - text value  - used by Google to differ between 2 users sending data. (will not be presented on reports). use only as a way to differ between different users
TRexMode - text - will be presented on analysis. put here TRexMode
appName - text - will be presented on analysis. put here appName as string describing app name
appVer - text - will be presented on analysis. put here the appVer
QueueSize - integer - determines the queue size. the queue will hold pending request before submission. RECOMMENDED VALUE: 20
Timeout - integer (seconds) - the timeout in seconds between automated reports when activating reporting thread
UserPermission - boolean (1/0) - required in order to send packets, should be 1.
BlockingMode - boolean (1/0) - required when each tracked event is critical and program should halt until the event is reported
SetupName - text - will be presented on analysis. put here setup name as string.
"""


class GAmanager_Regression(GAmanager):
    def __init__(self, GoogleID, AnalyticsUserID, appName, appVer,
                 QueueSize, Timeout, UserPermission, BlockingMode):
        GAmanager.__init__(self, GoogleID, AnalyticsUserID, appName, appVer,
                           QueueSize, Timeout, UserPermission, BlockingMode)
        self.GoogleID = GoogleID
        self.AnalyticsUserID = AnalyticsUserID

    def gaAddTestQuery(self, TestName, TRexMode, SetupName, ActionNumber, TestType, Mppspc, GoldenMin, GoldenMax):
        self.gaAddObject(
            GA_TESTING_ObjClass(self.AnalyticsUserID, self.GoogleID, TRexMode, TestName, SetupName, self.appName,
                                ActionNumber, self.appVer, TestType, Mppspc, GoldenMin, GoldenMax))