Last active
November 4, 2025 16:36
-
-
Save kitzberger/0f0fa7900f7032a365b400c077d38b24 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # TYPO3 Log Tail Formatter | |
| # Formats TYPO3 log files with custom column rendering | |
| # Parse arguments | |
| COMPACT=false | |
| LOG_PATH="" | |
| MAX_LINES="" | |
| JQ_FILTER="." | |
| GREP_PATTERN="" | |
| NO_JSON=false | |
| for arg in "$@"; do | |
| if [ "$arg" = "--compact" ]; then | |
| COMPACT=true | |
| elif [ "$arg" = "--no-json" ]; then | |
| NO_JSON=true | |
| elif [[ "$arg" =~ ^--max-lines=([0-9]+)$ ]]; then | |
| MAX_LINES="${BASH_REMATCH[1]}" | |
| elif [[ "$arg" =~ ^--jq=(.+)$ ]]; then | |
| JQ_FILTER="${BASH_REMATCH[1]}" | |
| elif [[ "$arg" =~ ^--grep=(.+)$ ]]; then | |
| GREP_PATTERN="${BASH_REMATCH[1]}" | |
| else | |
| LOG_PATH="$arg" | |
| fi | |
| done | |
| # Use default path if none provided | |
| LOG_PATH="${LOG_PATH:-var/log/typo3_*.log}" | |
| # Set up tail pipeline | |
| if [ -n "$GREP_PATTERN" ]; then | |
| TAIL_CMD="tail -f $LOG_PATH | grep --line-buffered '$GREP_PATTERN'" | |
| else | |
| TAIL_CMD="tail -f $LOG_PATH" | |
| fi | |
| eval "$TAIL_CMD" | while IFS= read -r line; do | |
| # Parse the log line | |
| # Format: Fri, 24 Oct 2025 10:53:28 +0200 [DEBUG] request="9be3da5813753" component="...": message - {json} | |
| if [[ $line =~ ^([^[]+)\[([A-Z]+)\]\ request=\"([^\"]+)\"\ component=\"([^\"]+)\":\ ([^-]+)-\ (\{.*\})$ ]]; then | |
| datetime="${BASH_REMATCH[1]}" | |
| severity="${BASH_REMATCH[2]}" | |
| request="${BASH_REMATCH[3]}" | |
| component="${BASH_REMATCH[4]}" | |
| message="${BASH_REMATCH[5]}" | |
| json="${BASH_REMATCH[6]}" | |
| # Format datetime based on compact mode | |
| if [ "$COMPACT" = true ]; then | |
| formatted_time=$(date -d "$datetime" "+%H:%M:%S" 2>/dev/null || echo "$datetime") | |
| else | |
| formatted_time=$(date -d "$datetime" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$datetime") | |
| fi | |
| # Shorten request to 4 characters | |
| request_short="${request:0:4}" | |
| # Format component based on compact mode | |
| if [ "$COMPACT" = true ]; then | |
| # Shorten component: keep uppercase chars and last part complete | |
| # E.g., Extcode.CartPayone.EventListener.Order.Payment.ProviderRedirect | |
| # => E.CP.EL.O.P.ProviderRedirect | |
| IFS='.' read -ra PARTS <<< "$component" | |
| component_formatted="" | |
| for i in "${!PARTS[@]}"; do | |
| if [ $i -eq $((${#PARTS[@]} - 1)) ]; then | |
| # Last part: keep complete | |
| component_formatted+="${PARTS[$i]}" | |
| else | |
| # Other parts: extract uppercase letters | |
| uppercase=$(echo "${PARTS[$i]}" | grep -o '[A-Z]' | tr -d '\n') | |
| component_formatted+="${uppercase}." | |
| fi | |
| done | |
| else | |
| # Use full FQCN | |
| component_formatted="$component" | |
| fi | |
| # Print formatted output | |
| echo -e "\033[90m$formatted_time\033[0m \033[1m[$severity]\033[0m \033[36m$request_short\033[0m \033[33m$component_formatted\033[0m: $message" | |
| if [ "$NO_JSON" = false ]; then | |
| if [ -n "$MAX_LINES" ]; then | |
| echo "$json" | jq --color-output "$JQ_FILTER" 2>/dev/null | head -n "$MAX_LINES" || echo "$json" | |
| else | |
| echo "$json" | jq --color-output "$JQ_FILTER" 2>/dev/null || echo "$json" | |
| fi | |
| fi | |
| elif [[ $line =~ ^([^[]+)\[([A-Z]+)\]\ request=\"([^\"]+)\"\ component=\"([^\"]+)\":\ (.+)$ ]]; then | |
| # Line without JSON | |
| datetime="${BASH_REMATCH[1]}" | |
| severity="${BASH_REMATCH[2]}" | |
| request="${BASH_REMATCH[3]}" | |
| component="${BASH_REMATCH[4]}" | |
| message="${BASH_REMATCH[5]}" | |
| # Format datetime based on compact mode | |
| if [ "$COMPACT" = true ]; then | |
| formatted_time=$(date -d "$datetime" "+%H:%M:%S" 2>/dev/null || echo "$datetime") | |
| else | |
| formatted_time=$(date -d "$datetime" "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo "$datetime") | |
| fi | |
| # Shorten request to 4 characters | |
| request_short="${request:0:4}" | |
| # Format component based on compact mode | |
| if [ "$COMPACT" = true ]; then | |
| # Shorten component | |
| IFS='.' read -ra PARTS <<< "$component" | |
| component_formatted="" | |
| for i in "${!PARTS[@]}"; do | |
| if [ $i -eq $((${#PARTS[@]} - 1)) ]; then | |
| component_formatted+="${PARTS[$i]}" | |
| else | |
| uppercase=$(echo "${PARTS[$i]}" | grep -o '[A-Z]' | tr -d '\n') | |
| component_formatted+="${uppercase}." | |
| fi | |
| done | |
| else | |
| # Use full FQCN | |
| component_formatted="$component" | |
| fi | |
| # Print formatted output | |
| echo -e "\033[90m$formatted_time\033[0m \033[1m[$severity]\033[0m \033[36m$request_short\033[0m \033[33m$component_formatted\033[0m: $message" | |
| else | |
| # Print line as-is if it doesn't match the pattern | |
| echo "$line" | |
| fi | |
| done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment