Skip to content

Commit 024aa6c

Browse files
committed
add github API info to status page
1 parent 991a6a2 commit 024aa6c

File tree

4 files changed

+291
-36
lines changed

4 files changed

+291
-36
lines changed

website/static/js/repo_detail.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,14 @@ async function refreshSection(button, section) {
7373
console.log(`Sending section: '${sectionValue}'`);
7474

7575
// Get CSRF token from the meta tag
76-
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
76+
const csrfMetaTag = document.querySelector('meta[name="csrf-token"]');
77+
let csrfToken = '';
78+
79+
if (csrfMetaTag) {
80+
csrfToken = csrfMetaTag.getAttribute('content');
81+
} else {
82+
console.error('CSRF token meta tag not found. Make sure it exists in your HTML.');
83+
}
7784

7885
const response = await fetch(window.location.href, {
7986
method: 'POST',
@@ -339,7 +346,7 @@ function updateContributorStats(timePeriod, page = 1) {
339346
body: formData,
340347
headers: {
341348
'X-Requested-With': 'XMLHttpRequest',
342-
'X-CSRFToken': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
349+
'X-CSRFToken': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
343350
}
344351
})
345352
.then(response => {

website/templates/status_page.html

+175-27
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{% extends "base.html" %}
22
{% load static %}
3+
{% load custom_tags %}
4+
{% load humanize %}
35
{% block title %}
46
Service Status
57
{% endblock title %}
@@ -78,7 +80,7 @@ <h3 class="text-xl font-semibold mb-4">OpenAI API</h3>
7880
<!-- GitHub API Status -->
7981
<div class="bg-white rounded-lg shadow-sm p-6 border border-[#e74c3c]">
8082
<h3 class="text-xl font-semibold mb-4">GitHub API</h3>
81-
<div class="flex items-center">
83+
<div class="flex items-center mb-4">
8284
<div class="w-3 h-3 rounded-full mr-3 {% if status.github == None %}bg-gray-400{% elif status.github %}bg-green-500{% else %}bg-red-500{% endif %}">
8385
</div>
8486
{% if status.github == None %}
@@ -89,6 +91,97 @@ <h3 class="text-xl font-semibold mb-4">GitHub API</h3>
8991
<span class="text-red-600">Not Operational</span>
9092
{% endif %}
9193
</div>
94+
{% if status.github_rate_limit %}
95+
<div class="mt-4">
96+
<h4 class="text-lg font-semibold mb-2">Rate Limits</h4>
97+
<!-- Core Rate Limit -->
98+
<div class="mb-4">
99+
<h5 class="font-medium">Core API</h5>
100+
<div class="grid grid-cols-2 gap-2 mt-2">
101+
<div>
102+
<span class="text-gray-600">Remaining:</span>
103+
<span class="font-medium ml-1">{{ status.github_rate_limit.core.remaining }} / {{ status.github_rate_limit.core.limit }}</span>
104+
</div>
105+
<div>
106+
<span class="text-gray-600">Used:</span>
107+
<span class="font-medium ml-1">{{ status.github_rate_limit.core.used }}</span>
108+
</div>
109+
</div>
110+
<!-- Progress Bar -->
111+
{% with remaining=status.github_rate_limit.core.remaining|default:0 limit=status.github_rate_limit.core.limit|default:1 %}
112+
{% with percentage=remaining|div:limit|multiply:100|floatformat:0 %}
113+
<div class="w-full bg-gray-200 rounded-full h-2.5 mt-2">
114+
<div class="bg-[#e74c3c] h-2.5 rounded-full"
115+
style="width: {{ percentage }}%"></div>
116+
</div>
117+
<div class="text-xs text-gray-500 mt-1">
118+
Reset in:
119+
{% if status.github_rate_limit.core.reset %}
120+
{% with reset_time=status.github_rate_limit.core.reset|timestamp_to_datetime %}{{ reset_time|timeuntil }}{% endwith %}
121+
{% else %}
122+
Unknown
123+
{% endif %}
124+
</div>
125+
{% endwith %}
126+
{% endwith %}
127+
</div>
128+
<!-- Search Rate Limit -->
129+
<div class="mb-4">
130+
<h5 class="font-medium">Search API</h5>
131+
<div class="grid grid-cols-2 gap-2 mt-2">
132+
<div>
133+
<span class="text-gray-600">Remaining:</span>
134+
<span class="font-medium ml-1">{{ status.github_rate_limit.search.remaining }} / {{ status.github_rate_limit.search.limit }}</span>
135+
</div>
136+
<div>
137+
<span class="text-gray-600">Used:</span>
138+
<span class="font-medium ml-1">{{ status.github_rate_limit.search.used }}</span>
139+
</div>
140+
</div>
141+
<!-- Progress Bar -->
142+
{% with remaining=status.github_rate_limit.search.remaining|default:0 limit=status.github_rate_limit.search.limit|default:1 %}
143+
{% with percentage=remaining|div:limit|multiply:100|floatformat:0 %}
144+
<div class="w-full bg-gray-200 rounded-full h-2.5 mt-2">
145+
<div class="bg-[#e74c3c] h-2.5 rounded-full"
146+
style="width: {{ percentage }}%"></div>
147+
</div>
148+
{% endwith %}
149+
{% endwith %}
150+
</div>
151+
<!-- GraphQL Rate Limit -->
152+
<div>
153+
<h5 class="font-medium">GraphQL API</h5>
154+
<div class="grid grid-cols-2 gap-2 mt-2">
155+
<div>
156+
<span class="text-gray-600">Remaining:</span>
157+
<span class="font-medium ml-1">{{ status.github_rate_limit.graphql.remaining }} / {{ status.github_rate_limit.graphql.limit }}</span>
158+
</div>
159+
<div>
160+
<span class="text-gray-600">Used:</span>
161+
<span class="font-medium ml-1">{{ status.github_rate_limit.graphql.used }}</span>
162+
</div>
163+
</div>
164+
<!-- Progress Bar -->
165+
{% with remaining=status.github_rate_limit.graphql.remaining|default:0 limit=status.github_rate_limit.graphql.limit|default:1 %}
166+
{% with percentage=remaining|div:limit|multiply:100|floatformat:0 %}
167+
<div class="w-full bg-gray-200 rounded-full h-2.5 mt-2">
168+
<div class="bg-[#e74c3c] h-2.5 rounded-full"
169+
style="width: {{ percentage }}%"></div>
170+
</div>
171+
{% endwith %}
172+
{% endwith %}
173+
</div>
174+
</div>
175+
<!-- API Usage History -->
176+
{% if status.github_api_history %}
177+
<div class="mt-6">
178+
<h4 class="text-lg font-semibold mb-2">API Usage History</h4>
179+
<div class="w-full h-64">
180+
<canvas id="githubApiChart"></canvas>
181+
</div>
182+
</div>
183+
{% endif %}
184+
{% endif %}
92185
</div>
93186
<!-- Top Memory Consumers -->
94187
<div class="bg-white rounded-lg shadow-sm p-6 border border-[#e74c3c]">
@@ -249,36 +342,91 @@ <h4 class="text-lg font-semibold mb-4">Recent Activities</h4>
249342
responsive: true,
250343
maintainAspectRatio: false,
251344
scales: {
252-
x: {
253-
stacked: false,
254-
title: {
255-
display: true,
256-
text: 'Date'
257-
}
258-
},
259345
y: {
260-
stacked: false,
261-
beginAtZero: true,
262-
title: {
263-
display: true,
264-
text: 'Number of Activities'
265-
}
266-
}
267-
},
268-
plugins: {
269-
title: {
270-
display: true,
271-
text: 'Slack Bot Activities (Last 30 Days)',
272-
font: {
273-
size: 16
274-
}
275-
},
276-
legend: {
277-
position: 'bottom'
346+
beginAtZero: true
278347
}
279348
}
280349
}
281350
});
351+
352+
// GitHub API Usage History Chart
353+
const githubApiChartElement = document.getElementById('githubApiChart');
354+
if (githubApiChartElement) {
355+
let githubApiHistory = [];
356+
try {
357+
githubApiHistory = JSON.parse('{{ status.github_api_history|escapejs|default:"[]" }}');
358+
} catch (e) {
359+
console.error('Error parsing GitHub API history:', e);
360+
}
361+
362+
if (githubApiHistory && githubApiHistory.length > 0) {
363+
// Format the data for the chart
364+
const timestamps = githubApiHistory.map(entry => entry.timestamp);
365+
const remaining = githubApiHistory.map(entry => parseInt(entry.remaining) || 0);
366+
const used = githubApiHistory.map(entry => parseInt(entry.used) || 0);
367+
368+
new Chart(githubApiChartElement, {
369+
type: 'line',
370+
data: {
371+
labels: timestamps,
372+
datasets: [
373+
{
374+
label: 'Remaining',
375+
data: remaining,
376+
backgroundColor: 'rgba(231, 76, 60, 0.2)',
377+
borderColor: '#e74c3c',
378+
borderWidth: 2,
379+
tension: 0.1,
380+
fill: true
381+
},
382+
{
383+
label: 'Used',
384+
data: used,
385+
backgroundColor: 'rgba(52, 152, 219, 0.2)',
386+
borderColor: '#3498db',
387+
borderWidth: 2,
388+
tension: 0.1,
389+
fill: true
390+
}
391+
]
392+
},
393+
options: {
394+
responsive: true,
395+
maintainAspectRatio: false,
396+
scales: {
397+
y: {
398+
beginAtZero: true,
399+
title: {
400+
display: true,
401+
text: 'API Calls'
402+
}
403+
},
404+
x: {
405+
title: {
406+
display: true,
407+
text: 'Time'
408+
}
409+
}
410+
},
411+
plugins: {
412+
title: {
413+
display: true,
414+
text: 'GitHub API Usage History'
415+
},
416+
tooltip: {
417+
callbacks: {
418+
label: function(context) {
419+
const label = context.dataset.label || '';
420+
const value = context.parsed.y;
421+
return `${label}: ${value}`;
422+
}
423+
}
424+
}
425+
}
426+
}
427+
});
428+
}
429+
}
282430
});
283431
</script>
284-
{% endblock %}
432+
{% endblock extra_js %}

website/templatetags/custom_tags.py

+37
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,40 @@ def get_page_votes(template_name, vote_type="upvote"):
122122
return int(stat.value)
123123
except (DailyStats.DoesNotExist, ValueError):
124124
return 0
125+
126+
127+
@register.filter
128+
def timestamp_to_datetime(timestamp):
129+
"""
130+
Convert a Unix timestamp to a datetime object.
131+
132+
Args:
133+
timestamp (int): Unix timestamp in seconds
134+
135+
Returns:
136+
datetime: Datetime object
137+
"""
138+
try:
139+
# Convert to integer first to handle string inputs
140+
timestamp_int = int(float(timestamp))
141+
return timezone.datetime.fromtimestamp(timestamp_int)
142+
except (ValueError, TypeError):
143+
return None
144+
145+
146+
@register.filter
147+
def div(value, arg):
148+
"""
149+
Divide the value by the argument.
150+
151+
Args:
152+
value (float): The numerator
153+
arg (float): The denominator
154+
155+
Returns:
156+
float: The result of the division
157+
"""
158+
try:
159+
return float(value) / float(arg)
160+
except (ValueError, ZeroDivisionError):
161+
return 0

0 commit comments

Comments
 (0)