Sanitized mirror from private repository - 2026-04-20 01:32:01 UTC
This commit is contained in:
249
ansible/automation/playbooks/container_logs.yml
Normal file
249
ansible/automation/playbooks/container_logs.yml
Normal file
@@ -0,0 +1,249 @@
|
||||
---
|
||||
# Container Logs Collection Playbook
|
||||
# Collect logs from multiple containers for troubleshooting
|
||||
# Usage: ansible-playbook playbooks/container_logs.yml -e "service_name=plex"
|
||||
# Usage: ansible-playbook playbooks/container_logs.yml -e "service_pattern=immich"
|
||||
# Usage: ansible-playbook playbooks/container_logs.yml -e "collect_all=true"
|
||||
|
||||
- name: Collect Container Logs
|
||||
hosts: "{{ host_target | default('all') }}"
|
||||
gather_facts: yes
|
||||
vars:
|
||||
target_service_name: "{{ service_name | default('') }}"
|
||||
target_service_pattern: "{{ service_pattern | default('') }}"
|
||||
target_collect_all: "{{ collect_all | default(false) }}"
|
||||
target_log_lines: "{{ log_lines | default(100) }}"
|
||||
target_log_since: "{{ log_since | default('1h') }}"
|
||||
output_dir: "/tmp/container_logs/{{ ansible_date_time.date }}"
|
||||
target_include_timestamps: "{{ include_timestamps | default(true) }}"
|
||||
target_follow_logs: "{{ follow_logs | default(false) }}"
|
||||
|
||||
tasks:
|
||||
- name: Validate input parameters
|
||||
fail:
|
||||
msg: "Specify either service_name, service_pattern, or collect_all=true"
|
||||
when:
|
||||
- target_service_name == ""
|
||||
- target_service_pattern == ""
|
||||
- not (target_collect_all | bool)
|
||||
|
||||
- name: Check if Docker is running
|
||||
systemd:
|
||||
name: docker
|
||||
register: docker_status
|
||||
failed_when: docker_status.status.ActiveState != "active"
|
||||
|
||||
- name: Create local log directory
|
||||
file:
|
||||
path: "{{ output_dir }}/{{ inventory_hostname }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Create remote log directory
|
||||
file:
|
||||
path: "{{ output_dir }}/{{ inventory_hostname }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Get specific service container
|
||||
shell: 'docker ps -a --filter "name={{ target_service_name }}" --format "{%raw%}{{.Names}}{%endraw%}"'
|
||||
register: specific_container
|
||||
when: target_service_name != ""
|
||||
changed_when: false
|
||||
|
||||
- name: Get containers matching pattern
|
||||
shell: 'docker ps -a --filter "name={{ target_service_pattern }}" --format "{%raw%}{{.Names}}{%endraw%}"'
|
||||
register: pattern_containers
|
||||
when: target_service_pattern != ""
|
||||
changed_when: false
|
||||
|
||||
- name: Get all containers
|
||||
shell: 'docker ps -a --format "{%raw%}{{.Names}}{%endraw%}"'
|
||||
register: all_containers
|
||||
when: target_collect_all | bool
|
||||
changed_when: false
|
||||
|
||||
- name: Combine container lists
|
||||
set_fact:
|
||||
target_containers: >-
|
||||
{{
|
||||
(specific_container.stdout_lines | default([])) +
|
||||
(pattern_containers.stdout_lines | default([])) +
|
||||
(all_containers.stdout_lines | default([]) if target_collect_all | bool else [])
|
||||
}}
|
||||
|
||||
- name: Display target containers
|
||||
debug:
|
||||
msg: |
|
||||
📦 CONTAINER LOG COLLECTION
|
||||
===========================
|
||||
🖥️ Host: {{ inventory_hostname }}
|
||||
📋 Target Containers: {{ target_containers | length }}
|
||||
{% for container in target_containers %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
📏 Log Lines: {{ target_log_lines }}
|
||||
⏰ Since: {{ target_log_since }}
|
||||
|
||||
- name: Fail if no containers found
|
||||
fail:
|
||||
msg: "No containers found matching the criteria"
|
||||
when: target_containers | length == 0
|
||||
|
||||
- name: Get container information
|
||||
shell: |
|
||||
docker inspect {{ item }} --format='
|
||||
Container: {{ item }}
|
||||
Image: {%raw%}{{.Config.Image}}{%endraw%}
|
||||
Status: {%raw%}{{.State.Status}}{%endraw%}
|
||||
Started: {%raw%}{{.State.StartedAt}}{%endraw%}
|
||||
Restart Count: {%raw%}{{.RestartCount}}{%endraw%}
|
||||
Health: {%raw%}{{if .State.Health}}{{.State.Health.Status}}{{else}}No health check{{end}}{%endraw%}
|
||||
'
|
||||
register: container_info
|
||||
loop: "{{ target_containers }}"
|
||||
changed_when: false
|
||||
|
||||
- name: Collect container logs
|
||||
shell: |
|
||||
echo "=== CONTAINER INFO ===" > {{ output_dir }}/{{ inventory_hostname }}/{{ item }}.log
|
||||
docker inspect {{ item }} --format='
|
||||
Container: {{ item }}
|
||||
Image: {%raw%}{{.Config.Image}}{%endraw%}
|
||||
Status: {%raw%}{{.State.Status}}{%endraw%}
|
||||
Started: {%raw%}{{.State.StartedAt}}{%endraw%}
|
||||
Restart Count: {%raw%}{{.RestartCount}}{%endraw%}
|
||||
Health: {%raw%}{{if .State.Health}}{{.State.Health.Status}}{{else}}No health check{{end}}{%endraw%}
|
||||
' >> {{ output_dir }}/{{ inventory_hostname }}/{{ item }}.log
|
||||
echo "" >> {{ output_dir }}/{{ inventory_hostname }}/{{ item }}.log
|
||||
echo "=== CONTAINER LOGS ===" >> {{ output_dir }}/{{ inventory_hostname }}/{{ item }}.log
|
||||
{% if target_include_timestamps | bool %}
|
||||
docker logs {{ item }} --since={{ target_log_since }} --tail={{ target_log_lines }} -t >> {{ output_dir }}/{{ inventory_hostname }}/{{ item }}.log 2>&1
|
||||
{% else %}
|
||||
docker logs {{ item }} --since={{ target_log_since }} --tail={{ target_log_lines }} >> {{ output_dir }}/{{ inventory_hostname }}/{{ item }}.log 2>&1
|
||||
{% endif %}
|
||||
loop: "{{ target_containers }}"
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Get container resource usage
|
||||
shell: 'docker stats {{ target_containers | join(" ") }} --no-stream --format "table {%raw%}{{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}{%endraw%}"'
|
||||
register: container_stats
|
||||
when: target_containers | length > 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Save container stats
|
||||
copy:
|
||||
content: |
|
||||
Container Resource Usage - {{ ansible_date_time.iso8601 }}
|
||||
Host: {{ inventory_hostname }}
|
||||
|
||||
{{ container_stats.stdout }}
|
||||
dest: "{{ output_dir }}/{{ inventory_hostname }}/container_stats.txt"
|
||||
when: container_stats.stdout is defined
|
||||
|
||||
- name: Check for error patterns in logs
|
||||
shell: |
|
||||
echo "=== ERROR ANALYSIS ===" > {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
echo "Host: {{ inventory_hostname }}" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
echo "Timestamp: {{ ansible_date_time.iso8601 }}" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
echo "" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
|
||||
for container in {{ target_containers | join(' ') }}; do
|
||||
echo "=== $container ===" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
|
||||
# Count error patterns
|
||||
error_count=$(docker logs $container --since={{ target_log_since }} 2>&1 | grep -i -E "(error|exception|failed|fatal|panic)" | wc -l)
|
||||
warn_count=$(docker logs $container --since={{ target_log_since }} 2>&1 | grep -i -E "(warn|warning)" | wc -l)
|
||||
|
||||
echo "Errors: $error_count" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
echo "Warnings: $warn_count" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
|
||||
# Show recent errors
|
||||
if [ $error_count -gt 0 ]; then
|
||||
echo "Recent Errors:" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
docker logs $container --since={{ target_log_since }} 2>&1 | grep -i -E "(error|exception|failed|fatal|panic)" | tail -5 >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
fi
|
||||
echo "" >> {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
done
|
||||
when: target_containers | length > 0
|
||||
ignore_errors: yes
|
||||
|
||||
- name: Create summary report
|
||||
copy:
|
||||
content: |
|
||||
📊 CONTAINER LOG COLLECTION SUMMARY
|
||||
===================================
|
||||
|
||||
🖥️ Host: {{ inventory_hostname }}
|
||||
📅 Collection Time: {{ ansible_date_time.iso8601 }}
|
||||
📦 Containers Processed: {{ target_containers | length }}
|
||||
📏 Log Lines per Container: {{ target_log_lines }}
|
||||
⏰ Time Range: {{ target_log_since }}
|
||||
|
||||
📋 CONTAINERS:
|
||||
{% for container in target_containers %}
|
||||
- {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
📁 LOG FILES LOCATION:
|
||||
{{ output_dir }}/{{ inventory_hostname }}/
|
||||
|
||||
📄 FILES CREATED:
|
||||
{% for container in target_containers %}
|
||||
- {{ container }}.log
|
||||
{% endfor %}
|
||||
- container_stats.txt
|
||||
- error_summary.txt
|
||||
- collection_summary.txt (this file)
|
||||
|
||||
🔍 QUICK ANALYSIS:
|
||||
Use these commands to analyze the logs:
|
||||
|
||||
# View error summary
|
||||
cat {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
|
||||
# Search for specific patterns
|
||||
grep -i "error" {{ output_dir }}/{{ inventory_hostname }}/*.log
|
||||
|
||||
# View container stats
|
||||
cat {{ output_dir }}/{{ inventory_hostname }}/container_stats.txt
|
||||
|
||||
# Follow live logs (if needed)
|
||||
{% for container in target_containers[:3] %}
|
||||
docker logs -f {{ container }}
|
||||
{% endfor %}
|
||||
|
||||
dest: "{{ output_dir }}/{{ inventory_hostname }}/collection_summary.txt"
|
||||
|
||||
- name: Display collection results
|
||||
debug:
|
||||
msg: |
|
||||
|
||||
✅ LOG COLLECTION COMPLETE
|
||||
==========================
|
||||
🖥️ Host: {{ inventory_hostname }}
|
||||
📦 Containers: {{ target_containers | length }}
|
||||
📁 Location: {{ output_dir }}/{{ inventory_hostname }}/
|
||||
|
||||
📄 Files Created:
|
||||
{% for container in target_containers %}
|
||||
- {{ container }}.log
|
||||
{% endfor %}
|
||||
- container_stats.txt
|
||||
- error_summary.txt
|
||||
- collection_summary.txt
|
||||
|
||||
🔍 Quick Commands:
|
||||
# View errors: cat {{ output_dir }}/{{ inventory_hostname }}/error_summary.txt
|
||||
# View stats: cat {{ output_dir }}/{{ inventory_hostname }}/container_stats.txt
|
||||
|
||||
==========================
|
||||
|
||||
- name: Archive logs (optional)
|
||||
archive:
|
||||
path: "{{ output_dir }}/{{ inventory_hostname }}"
|
||||
dest: "{{ output_dir }}/{{ inventory_hostname }}_logs_{{ ansible_date_time.epoch }}.tar.gz"
|
||||
remove: no
|
||||
when: archive_logs | default(false) | bool
|
||||
delegate_to: localhost
|
||||
Reference in New Issue
Block a user