Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
from common.utils import safe_get_env_var
import os

try:
import colorlog
HAS_COLORLOG = True
except ImportError:
HAS_COLORLOG = False

def grouping_function(request):
env = safe_get_env_var("FLASK_ENV")
if True:
Expand All @@ -26,27 +32,50 @@ def grouping_function(request):
return None


# Determine if colored logging should be used
use_colored_logs = (
HAS_COLORLOG and
os.environ.get('USE_COLORED_LOGS', 'true').lower() == 'true'
)

# Build formatters dictionary
formatters = {
'default': {
'format': '[%(asctime)s] {%(pathname)s:%(funcName)s:%(lineno)d} %(levelname)s - %(message)s',
}
}

if use_colored_logs:
formatters['colored'] = {
'()': 'colorlog.ColoredFormatter',
'format': '%(log_color)s[%(asctime)s] %(levelname)s%(reset)s - %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S',
'log_colors': {
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red,bg_white',
}
}

dict_config = {
'version': 1,
'formatters': {
'default': {
'format': '[%(asctime)s] {%(pathname)s:%(funcName)s:%(lineno)d} %(levelname)s - %(message)s',
}
},
'formatters': formatters,
'handlers': {
'default': {
'level': 'DEBUG',
'formatter': 'default',
'class': 'logging.handlers.RotatingFileHandler',
'filename': "test.log",
'maxBytes': 5000000,
'backupCount': 10
},
'level': 'DEBUG',
'formatter': 'default',
'class': 'logging.handlers.RotatingFileHandler',
'filename': "test.log",
'maxBytes': 5000000,
'backupCount': 10
},
'console': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'default',
},
'formatter': 'colored' if use_colored_logs else 'default',
},
},
'loggers': {
'myapp': {
Expand Down
12 changes: 12 additions & 0 deletions api/leaderboard/leaderboard_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,18 @@ def get_github_leaderboard(event_id: str) -> Dict[str, Any]:
org_name = get_github_organizations(event_id)
org_duration = time.time() - org_start
logger.debug("get_github_organizations took %.2f seconds", org_duration)

if org_name["github_organizations"] == []:
logger.warning("No GitHub organizations found for event ID: %s", event_id)
return {
"github_organizations": [],
"github_repositories": [],
"github_contributors": [],
"github_achievements": [],
"generalStats": [],
"individualAchievements": [],
"teamAchievements": []
}

repos_start = time.time()
repos = get_github_repositories(org_name["github_organizations"][0]["name"])
Expand Down
29 changes: 27 additions & 2 deletions api/messages/messages_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -1766,8 +1766,6 @@ def save_news(json):
return Message("Saved News")

def save_praise(json):
logger.debug(f"Attempting to save the praise with the json object {json}")

# Make sure these fields exist praise_receiver, praise_channel, praise_message
check_fields = ["praise_receiver", "praise_channel", "praise_message"]
for field in check_fields:
Expand All @@ -1777,6 +1775,33 @@ def save_praise(json):

logger.debug(f"Detected required fields, attempting to save praise")
json["timestamp"] = datetime.now(pytz.utc).astimezone().isoformat()

# Add ohack.dev user IDs for both sender and receiver
try:
# Get ohack.dev user ID for praise receiver
receiver_user = get_user_by_user_id(json["praise_receiver"])
if receiver_user and "id" in receiver_user:
json["praise_receiver_ohack_id"] = receiver_user["id"]
logger.debug(f"Added praise_receiver_ohack_id: {receiver_user['id']}")
else:
logger.warning(f"Could not find ohack.dev user for praise_receiver: {json['praise_receiver']}")
json["praise_receiver_ohack_id"] = None

# Get ohack.dev user ID for praise sender
sender_user = get_user_by_user_id(json["praise_sender"])
if sender_user and "id" in sender_user:
json["praise_sender_ohack_id"] = sender_user["id"]
logger.debug(f"Added praise_sender_ohack_id: {sender_user['id']}")
else:
logger.warning(f"Could not find ohack.dev user for praise_sender: {json['praise_sender']}")
json["praise_sender_ohack_id"] = None

except Exception as e:
logger.error(f"Error getting ohack.dev user IDs: {str(e)}")
json["praise_receiver_ohack_id"] = None
json["praise_sender_ohack_id"] = None

logger.info(f"Attempting to save the praise with the json object {json}")
upsert_praise(json)

logger.info("Updated praise successfully")
Expand Down
14 changes: 14 additions & 0 deletions api/teams/teams_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,20 @@ def send_team_message(admin_user, teamid, json):
slack_channel = team_data["slack_channel"]
send_slack(message, slack_channel)

# I'd also like to send each of them an email using send_volunteer_message from volunteers_service.py where we need to get their Slack User ID and pass that in as recipient_id
from api.volunteers.volunteers_service import send_volunteer_message, get_user_from_slack_id
for user_ref in team_data.get("users", []):
user_data = user_ref.get().to_dict()
slack_user_id = user_data.get("user_id", "")
if slack_user_id:
send_volunteer_message(
admin_user=admin_user,
recipient_id=slack_user_id,
subject=f"Message from Opportunity Hack Team {team_data['name']}",
message=message
)


# If communication_history doesn't exist, create it and append the timestamp, sender, text
if "communication_history" not in team_data:
team_data["communication_history"] = []
Expand Down
31 changes: 30 additions & 1 deletion common/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
import sys
from typing import Any, Dict, Optional, Union

try:
import colorlog
HAS_COLORLOG = True
except ImportError:
HAS_COLORLOG = False

# Configure default log level
log_level = logging.INFO

Expand Down Expand Up @@ -65,6 +71,14 @@ def format(self, record: logging.LogRecord) -> str:
# Determine if we should use JSON logging based on environment
use_json_logging = os.environ.get('USE_JSON_LOGGING', 'false').lower() == 'true'

# Determine if we should use colored logging (only in non-JSON mode)
# Default to True if colorlog is available and we're not using JSON logging
use_colored_logging = (
HAS_COLORLOG and
not use_json_logging and
os.environ.get('USE_COLORED_LOGS', 'true').lower() == 'true'
)

# Root logger configuration
def configure_root_logger():
"""Configure the root logger with appropriate handlers"""
Expand All @@ -82,9 +96,24 @@ def configure_root_logger():
# Apply appropriate formatter
if use_json_logging:
formatter = JsonFormatter()
elif use_colored_logging:
# Use colorlog for colored output with nice formatting
formatter = colorlog.ColoredFormatter(
'%(log_color)s%(asctime)s - %(name)s - %(levelname)s%(reset)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
log_colors={
'DEBUG': 'cyan',
'INFO': 'green',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'red,bg_white',
},
secondary_log_colors={},
style='%'
)
else:
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)

Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ resend==2.3.0
readme-metrics[Flask]==3.1.0
redis==5.2.1
tiktoken==0.9.0
numpy==1.26.3
numpy==1.26.3
colorlog==6.7.0
Loading