Вопрос или проблема
У меня есть около 800 лог-файлов, и я пытаюсь написать скрипт, который сообщает количество строк в секунду или “запросы в секунду” в каждом лог-файле и выводит результат, который включает метку времени для наибольшего количества строк в секунду, имя лог-файла и наибольшее количество в секунду из этого файла, а затем переходит ко второму лог-файлу и делает то же самое, затем добавляет результаты к тому же выходному файлу.
Фрагмент лог-файла показан ниже.
В настоящее время я использую эту команду для получения результатов из каждого лога, но делать это для 800 лог-файлов непрактично
grep "2017-02-22" "LogFile.log" | cut -c1-20 | uniq -c | sort -n | tail -n1
Эта команда выдает список количества строк за 10 секунд, но это не очень эффективно
Таким образом, выходной файл должен выглядеть так:
Date/time "1st LogFileName" "highest requests per second for this log"
Date/time "2nd LogFileName" "highest requests per second for this log"
#Fields: date time time-taken c-ip cs-username cs-auth-group x-exception-id sc-filter-result cs-categories cs(Referer) sc-status s-action cs-method
rs(Content-Type) cs-uri-scheme cs-host cs-uri-port cs-uri-path cs-uri-query cs-uri-extension cs(User-Agent) s-ip sc-bytes cs-bytes x-virus-id x-bl
uecoat-application-name x-bluecoat-application-operation
#Remark: 1412140034 "lofnetsg1" "192.168.13.14" "main"
2017-02-15 17:49:06 8 10.23.53.112 - - - OBSERVED "Technology/Internet" - 404 TCP_NC_MISS GET text/html;%20charset=iso-8859-1 http dci.sophosupd.c
om 80 /osxhe/d/16/d16e39472e867bf7f8407db13d3502b5.dat - dat "Sophos%20AutoUpdate/ CFNetwork/760.6.3 Darwin/15.6.0 (x86_64)" 192.168.13.14 437 243
- "none" "none"
2017-02-15 17:49:06 578 10.4.33.22 - - - OBSERVED "Web Ads/Analytics" - 200 TCP_TUNNELED CONNECT - tcp tpc.googlesyndication.com 443 / - - "Mozill
a/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko" 192.168.13.14 21106 2873 - "none" "none"
2017-02-15 17:49:06 17 10.17.87.27 - - - OBSERVED "Web Ads/Analytics" - 200 TCP_NC_MISS GET - http t.lkqd.net 80 /t ?ev=147&tsid=132117&env=3&cb=7
43590466414&format=0&did=2&osid=2&pubtagtype=lkqd-formats&render=html5&apt=auto&uimp=6944564170577988928&svrs=0.45&srvid=10.10.4.214&oip=134.174.21
.158&vrs=197&tsl=13827&ear=0&width=300&height=250&phost=&host=reuters.com&appname=&idfa=&aid=&bundleid=&lsid=&loclat=&loclong=&contentid=&contentti
tle=&contentlength=&contenturl=&appstoreurl=&execution=inbanner&placement=&browserid=1&adplayersize=small&pid=326&sid=150846&spid=18106&psid=&ppid=
&lkqdtagtype=platform-connection&tlr=0&adid=127634&asrc=15817&dealid=117723&c1=&c2=&c3=&tsia=8945&tssa=&rnd=157089284&cs=3668523497 - "Mozilla/5.0
(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" 192.168.13.14 290 1534 - "none" "none"
2017-02-15 17:49:06 669 10.23.112.63 - - - OBSERVED "Radio/Audio Streams" - 200 TCP_MISS GET audio/x-aac http primary.hls-streaming.production.str
eaming.siriusxm.com 80 /AAC_Data/broadwaysbest/HLS_broadwaysbest_64k_v3/broadwaysbest_64k_1_021560803727_00310913_v3.aac ?consumer=k2&gupId=BE4A750
32FEC2FF7293A7F5C0FAEFEA3 aac "SXMLiveAudioPlayer/1485824608 CFNetwork/808.3 Darwin/16.3.0" 192.168.13.14 79798 1119 - "none" "none"
2017-02-15 17:49:06 32 10.64.5.81 - - - OBSERVED "Web Ads/Analytics" Error
.html 200 TCP_NC_MISS GET text/javascript http beacon.krxd.net 80 /optout_check ?callback=Krux.ns._default.kxjsonp_optOutCheck - "Mozilla/5.0 (Win
dows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" 192.168.13.14 635 451 - "none" "none"
Пример использования pv
в Linux/macos, мой случай для подсчета запросов в секунду от Google
.....:~$ sudo tail -f /var/log/nginx/access.log|grep google | pv --line-mode --rate > /dev/null
[38.1 /s]s]
Вам понадобится файл позиции. Файл позиции должен хранить время и размер (в байтах) файла при начальном чтении или позицию файла при последнем чтении.
Затем вы используете tail -c +bytepos
, чтобы перейти к этой позиции, и затем ограничиваете вывод, используя sed '/PATTERN/!q' FILE
, который должен копировать свой stdout, пока он больше не соответствует PATTERN. Вам нужно будет создать негативный шаблон. Далее просто используйте wc для подсчета строк.
Так что что-то вроде (непроверенного):
tail -c +bytepos | sed '/timestamp/!q' | wc
При создании дополнительных строк в Logfile.log
, чтобы сделать вопрос более корректным при обсуждении “Эта команда выдает список количества строк за 10 секунд“
#Fields: date time time-taken c-ip cs-username cs-auth-group x-exception-id sc-filter-result cs-categories cs(Referer) sc-status s-action cs-method rs(Content-Type) cs
#Remark: 1412140034 "lofnetsg1" "192.168.13.14" "main"2017-02-15 17:49:06 8 10.23.53.112 - - - OBSERVED "Technology/Internet" - 404 TCP_NC_MISS GET text/html;%20chars2017-02-15 17:49:06 17 10.17.87.27 - - - OBSERVED "Web Ads/Analytics" - 200 TCP_NC_MISS GET - http t.lkqd.net 80 /t ?ev=147&tsid=132117&env=3&cb=743590466414&format=0
2017-02-15 17:49:06 669 10.23.112.63 - - - OBSERVED "Radio/Audio Streams" - 200 TCP_MISS GET audio/x-aac http primary.hls-streaming.production.steaming.siriusxm.com 8
2017-02-15 17:49:06 32 10.64.5.81 - - - OBSERVED "Web Ads/Analytics" Error.html 200 TCP_NC_MISS GET text/javascript http beacon.krxd.net 80 /optout_check ?callback=Kr
2017-02-15 17:49:16 17 10.17.87.27 - - - OBSERVED "Web Ads/Analytics" - 200 TCP_NC_MISS GET - http t.lkqd.net 80 /t ?ev=147&tsid=132117&env=3&cb=743590466414&format=0
2017-02-15 17:49:16 669 10.23.112.63 - - - OBSERVED "Radio/Audio Streams" - 200 TCP_MISS GET audio/x-aac http primary.hls-streaming.production.steaming.siriusxm.com 8
2017-02-15 17:49:26 32 10.64.5.81 - - - OBSERVED "Web Ads/Analytics" Error.html 200 TCP_NC_MISS GET text/javascript http beacon.krxd.net 80 /optout_check ?callback=Kr
Awk может помочь:
awk '$1=="2017-02-15"{ a[substr($0,1,18)]++ }
END{ for(i in a){ print i,a[i] }}' Logfile.log
$1=="2017-02-15"
: Для строк, где первое поле соответствует 15 февраля 2017 года- создаем переменную в массиве
a
с индексомsubstr($0,1,18)
, первые 18 символов даты и времени, и увеличиваем счетчик на 1 END{}
В блоке end мы перечисляем все суммы.
Вывод, с данными (простого!) ввода:
2017-02-15 17:49:0 3
2017-02-15 17:49:1 2
2017-02-15 17:49:2 1
.
Ответ или решение
Для решения задачи по подсчету количества строк в логах и определения максимального числа запросов в секунду для каждого файла, необходимо создать скрипт, который автоматизирует этот процесс. У вас имеется около 800 лог-файлов, и ручная обработка каждого из них — задача не из легких. Использование команды grep
, как показано в вашем примере, может дать результаты, но для большого количества файлов этот метод малоэффективен. Вместо этого можно воспользоваться языком программирования, например, Python, Bash или другим, с поддержкой обработки строк и файлов.
Теория
Основная задача — оптимизировать процесс обработки логов и вывести данные в требуемом формате. Для этого, сначала нужно прочитать каждый лог-файл, извлекая временные метки каждого запроса, чтобы затем по времени сгруппировать запросы и посчитать их количество в секунду. После подсчета необходимо найти максимальное значение числа запросов в секунду и сохранить информацию во внешний файл в нужном формате.
Пример
Рассмотрим использование Python как инструмента для решения этой задачи. Python предоставляет мощные библиотеки для работы с датами и файлами, такие как datetime
и стандартные возможности для работы с файловой системой.
Вот пример реализации скрипта с использованием Python:
import os
from datetime import datetime
def parse_line(line):
try:
# Предполагаем, что дата и время находятся в начале строки
ts = line[:19]
dt = datetime.strptime(ts, '%Y-%m-%d %H:%M:%S')
return dt
except ValueError:
return None
def process_file(file_path):
requests_per_second = {}
with open(file_path, 'r') as file:
for line in file:
dt = parse_line(line)
if dt:
second = dt.strftime('%Y-%m-%d %H:%M:%S')
if second not in requests_per_second:
requests_per_second[second] = 0
requests_per_second[second] += 1
# Получение времени с максимальным количеством запросов
max_requests_time = max(requests_per_second, key=requests_per_second.get)
max_requests_count = requests_per_second[max_requests_time]
return max_requests_time, max_requests_count
def main(log_directory, output_file):
with open(output_file, 'w') as output:
for log_file in os.listdir(log_directory):
if log_file.endswith('.log'):
full_path = os.path.join(log_directory, log_file)
max_time, max_count = process_file(full_path)
output.write(f"{max_time} \"{log_file}\" {max_count}\n")
log_directory = '/path/to/logs'
output_file = '/path/to/output.txt'
main(log_directory, output_file)
Применение
-
Сбор данных: Скрипт последовательно проходит по каждому лог-файлу в заданной директории и извлекает временные метки, записывая количество строк, соответствующих каждой секунде.
-
Обработка данных: Используя структуру словарей, сохраняются временные метки и количество строк (запросов) для этих меток.
-
Анализ данных: После сбора данных для каждого файла находят временную метку с наибольшей нагрузкой (максимальным количеством запросов в секунду).
-
Сохранение результатов: Результаты записываются в итоговый файл в указанном формате, содержащем дату и время, имя файла и количество запросов.
Эта автоматизация экономит время и усилия, необходимые для анализа большого количества лог-файлов вручную. Представленный подход позволяет решить задачу быстро и эффективно, сохраняя важные метаданные и упрощая последующий анализ данных. Эффективная обработка логов позволяет не только наблюдать за текущими запросами, но и прогнозировать будущие пики нагрузки.