Skip to content

Commit c8c92ed

Browse files
committed
Initial commit
0 parents  commit c8c92ed

File tree

2 files changed

+277
-0
lines changed

2 files changed

+277
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# CoScale CLI files
2+
api.conf
3+
coscale-cli-*
4+
5+
# Vscode
6+
.vscode

stats.py

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
#!/usr/bin/env python3
2+
import json
3+
import requests
4+
from datetime import timedelta, datetime, tzinfo
5+
import time
6+
import calendar
7+
8+
#
9+
# Configuration values
10+
#
11+
12+
# Location of CoScale install
13+
ENV = "https://app.coscale.com/api/v1/app"
14+
15+
# Name of the metric
16+
METRIC_NAME = "Docker container total cpu usage in cores"
17+
18+
# Application data
19+
APP_ID = "000000-08e8-4f72-0000-220ff6600000"
20+
APP_TOKEN = "000000-ebd1-4880-0000-3f4c06500000"
21+
22+
# Data to retrieve
23+
START_DATE = datetime(2018, 5, 25)
24+
END_DATE = datetime(2018, 5, 27)
25+
26+
# Images to retrieve data for, these should match the ones in CoScale Docker group
27+
IMAGES = [
28+
"docker.io/kidk/training-images-calc_words",
29+
"docker.io/kidk/training-images-web",
30+
]
31+
32+
#
33+
# DO NOT CHANGE ANYTHING BELOW THIS LINE
34+
#
35+
def dt2ts(dt):
36+
"""Converts a datetime object to UTC timestamp"""
37+
return calendar.timegm(dt.utctimetuple())
38+
39+
def debug(variable, fail=True):
40+
print(json.dumps(variable, indent=2, sort_keys=True))
41+
if fail:
42+
exit(0)
43+
44+
print("Retrieving data timerange from %s to %s" % (
45+
START_DATE, END_DATE
46+
))
47+
START_TIME = dt2ts(START_DATE)
48+
END_TIME = dt2ts(END_DATE)
49+
50+
class API:
51+
52+
token = None
53+
app = None
54+
env = None
55+
56+
def __init__(self, env, app, token):
57+
r = requests.post(
58+
"{env}/{app}/login/".format(env=env, app=app), data={"accessToken": token}
59+
)
60+
self.token = json.loads(r.text)["token"]
61+
self.app = app
62+
self.env = env
63+
64+
def do_post():
65+
return None
66+
67+
def do_get():
68+
return None
69+
70+
def get_metric_id(self, name):
71+
r = requests.get(
72+
"{env}/{app}/metrics/?selectByName={name}".format(
73+
env=self.env, app=self.app, name=name
74+
),
75+
headers={"HTTPAuthorization": self.token},
76+
data={},
77+
)
78+
metrics = json.loads(r.text)
79+
80+
return metrics[0]["id"]
81+
82+
def get_servergroup_children(self, id, start, stop):
83+
# Retrieve group children
84+
r = requests.get(
85+
"{env}/{app}/servergroups/{group_id}/servergroups/?start={start}&stop={stop}".format(
86+
env=self.env, app=self.app, group_id=id, start=start, stop=stop
87+
),
88+
headers={"HTTPAuthorization": self.token},
89+
)
90+
91+
return json.loads(r.text)
92+
93+
def get_servergroup_servers(self, id, start, stop):
94+
r = requests.get(
95+
"{env}/{app}/servergroups/{group_id}/servers/?start={start}&stop={stop}".format(
96+
env=self.env, app=self.app, group_id=id, start=start, stop=stop
97+
),
98+
headers={"HTTPAuthorization": self.token},
99+
)
100+
101+
return json.loads(r.text)
102+
103+
def get_servergroup(self, name):
104+
# Retrieve group ID
105+
r = requests.get(
106+
"{env}/{app}/servergroups/?selectByName={name}".format(
107+
env=self.env, app=self.app, name=name
108+
),
109+
headers={"HTTPAuthorization": self.token},
110+
data={},
111+
)
112+
113+
return json.loads(r.text)[0]
114+
115+
def get_data(self, metric, servers, start, stop):
116+
postdata = {
117+
"start": range_start_time,
118+
"stop": range_stop_time,
119+
"ids": [
120+
{
121+
"metricId": METRIC_ID,
122+
"dimensionsSpecs": [],
123+
"subjects": "%s" % servers,
124+
"viewtype": "AVG",
125+
}
126+
],
127+
}
128+
r = requests.post(
129+
"{env}/{app}/data/dimension/getCalculated/calculated/?function=summary&mode=average".format(
130+
env=self.env, app=self.app
131+
),
132+
headers={"HTTPAuthorization": self.token},
133+
data={"data": json.dumps(postdata)},
134+
)
135+
136+
return json.loads(r.text)
137+
138+
def get_all_servers_in_group_helper(self, group):
139+
serverIds = group['serverIds']
140+
141+
for child_group in group['servergroups']:
142+
serverIds = serverIds + self.get_all_servers_in_group_helper(child_group)
143+
144+
return serverIds
145+
146+
def get_all_servers_in_group(self, id, start, stop):
147+
# Retrieve all containers
148+
r = requests.get(
149+
"{env}/{app}/servergroups/{group_id}/?expand=servergroups&expand=serverIds&start={start}&stop={stop}".format(
150+
env=self.env, app=self.app, group_id=id, start=start, stop=stop
151+
),
152+
headers={"HTTPAuthorization": self.token},
153+
)
154+
groups = json.loads(r.text)
155+
156+
# Get list of all container id's
157+
serverIds = self.get_all_servers_in_group_helper(groups)
158+
159+
return list(set(serverIds)) # Remove duplicates
160+
161+
162+
# Init API and login
163+
API = API(ENV, SOURCE['id'], SOURCE['token'])
164+
165+
# Retrieve the metric ID for metric name
166+
METRIC_ID = API.get_metric_id(METRIC_NAME)
167+
print("Retrieved metricId %s for '%s'" % (METRIC_ID, METRIC_NAME))
168+
169+
# Retrieve Docker group children
170+
image_group = API.get_servergroup('Docker')
171+
images_group = API.get_servergroup_children(image_group['id'], start=START_TIME, stop=END_TIME)
172+
173+
# Prepare list of all containers running for image
174+
containers = {}
175+
for group in images_group:
176+
image_name = group["name"]
177+
if image_name in IMAGES:
178+
# Add element to containers list
179+
if image_name not in containers:
180+
containers[image_name] = {}
181+
182+
# Retrieve subgroups
183+
subgroups = API.get_servergroup_children(group["id"], start=START_TIME, stop=END_TIME)
184+
185+
# Retrieve containers from subgroups
186+
for subgroup in subgroups:
187+
servers = API.get_servergroup_servers(subgroup['id'], START_TIME, END_TIME)
188+
189+
# Add servers to containers list
190+
for server in servers:
191+
server_id = server['id']
192+
if server_id not in containers:
193+
containers[image_name][server_id] = server['name']
194+
195+
print("Found following containers for selected images")
196+
#debug(containers, False)
197+
198+
# Retrieve for each image type and containers
199+
metric_data = {}
200+
datapoints = 0
201+
for image in containers:
202+
# Check if metric_data image exists
203+
if image not in metric_data:
204+
metric_data[image] = {}
205+
206+
for container_id in containers[image]:
207+
metric_data[image][container_id] = {}
208+
209+
for n in range(int ((END_DATE - START_DATE).days)):
210+
range_start_time = dt2ts(START_DATE + timedelta(n))
211+
range_stop_time = dt2ts(START_DATE + timedelta(n + 1))
212+
213+
# Retrieve data for all containers for this timerange
214+
servers = ','.join("s%s" % str(server_id) for server_id in containers[image])
215+
values = API.get_data(METRIC_ID, servers, range_start_time, range_stop_time)
216+
217+
# Parse data for each container and add it
218+
for value in values:
219+
container_id = int(value['s'][2:-1]) # Remove the [s at beginning and ] at the end
220+
metric_data[image][container_id][range_start_time] = {
221+
'start': range_start_time,
222+
'stop': range_stop_time,
223+
'value': value['calc'][0],
224+
}
225+
datapoints = datapoints + 1
226+
227+
print("Fetched %s datapoints" % datapoints)
228+
#debug(metric_data, False)
229+
230+
# Retrieve all namespaces
231+
namespaces = {}
232+
233+
# Retrieve Namespace group children
234+
namespace_group = API.get_servergroup('Namespaces')
235+
namespaces_group = API.get_servergroup_children(namespace_group['id'], start=START_TIME, stop=END_TIME)
236+
237+
238+
# Retrieve servers in namespaces
239+
for namespace in namespaces_group:
240+
# Prepare data
241+
namespace_name = namespace['name']
242+
namespace_id = namespace['id']
243+
if namespace_name not in namespaces:
244+
namespaces[namespace_name] = {}
245+
246+
# Loop days to limit amount of servers we get back
247+
for n in range(int ((END_DATE - START_DATE).days)):
248+
range_start_time = dt2ts(START_DATE + timedelta(n))
249+
range_stop_time = dt2ts(START_DATE + timedelta(n + 1))
250+
251+
serverIds = API.get_all_servers_in_group(namespace_id, range_start_time, range_stop_time)
252+
253+
# Check images
254+
for image in metric_data:
255+
if image not in namespaces[namespace_name]:
256+
namespaces[namespace_name][image] = {}
257+
258+
for container in metric_data[image]:
259+
total = 0.0
260+
if container in serverIds:
261+
value = metric_data[image][container][range_start_time]['value']
262+
if value is not 'null' and value is not None:
263+
total += value
264+
265+
date = datetime.fromtimestamp(range_start_time).strftime('%Y-%m-%d')
266+
if date not in namespaces[namespace_name][image]:
267+
namespaces[namespace_name][image][date] = 0
268+
269+
namespaces[namespace_name][image][date] += total
270+
271+
debug(namespaces)

0 commit comments

Comments
 (0)