Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
software:fluent-bit-loki-grafana:fluent-bit:docker-swarm-2 [2025/11/26 00:30] – создано mirocowsoftware:fluent-bit-loki-grafana:fluent-bit:docker-swarm-2 [2025/12/06 03:35] (текущий) mirocow
Строка 1: Строка 1:
-====== Обработка многострочных логов ======+====== Обработка логов Docker ======
  
 === fluent-bit.conf === === fluent-bit.conf ===
  
 <code ini> <code ini>
 +[SERVICE]
 +    flush                     1
 +    log_level                 info
 +    daemon                    off
 +    storage.path              /var/log/flb-storage/
 +    storage.sync              normal
 +    storage.checksum          off
 +    storage.max_chunks_up     128
 +    storage.backlog.mem_limit 10M
 +    parsers_file              parsers.conf
 +    http_server               on
 +    http_listen               0.0.0.0
 +    http_port                 2020
  
 +[INPUT]
 +    Name              tail
 +    Path              /var/lib/docker/containers/*/*.log
 +    Parser            docker
 +    Refresh_Interval  10
 +    Ignore_Older      1h
 +    Docker_Mode       On
 +    Tag               docker.<file_name>
 +    Tag_Regex         (?<file_name>[a-f0-9]*)-json.log
 +    Mem_Buf_Limit     50MB
 +    Skip_Long_Lines   On
 +    DB                /var/log/flb-storage/flb_db.db
 +    DB.sync           normal
 +    Storage.Type      filesystem
 +    Read_from_Head    false
 +
 +# Только для отладки
 +# [INPUT]
 +#     Name              tail
 +#     Path              /var/lib/docker/containers/*/*.log
 +#     Parser            docker
 +#     Refresh_Interval  10
 +#     Docker_Mode       On
 +#     Tag               docker.<file_name>
 +#     Tag_Regex         (?<file_name>[a-f0-9]*)-json.log
 +#     Mem_Buf_Limit     50MB
 +#     Skip_Long_Lines   On
 +#     DB                /var/log/flb-storage/flb_db.db
 +#     DB.sync           normal
 +#     Storage.Type      filesystem
 +#     Read_from_Head    true
 +
 +# Фильтруем пустые логи
 +[FILTER]
 +    name                grep
 +    match               docker.*
 +    Exclude             log ^$
 +    Exclude             log ^\s*$
 +    Exclude             log ^==>.+<==$
 +
 +# Извлекаем сырой лог
 +[FILTER]
 +    name                modify
 +    match               docker.*
 +    copy                log raw_log
 +    copy                exception.backtrace exception_backtrace
 +    copy                exception.class exception_class
 +    copy                exception.message exception_message
 +
 +# Очищаем docker.* - оставляем ТОЛЬКО нужные поля
 +[FILTER]
 +    name                record_modifier
 +    match               docker.*
 +
 +    whitelist_key       date
 +    whitelist_key       log
 +    whitelist_key       raw_log
 +    whitelist_key       exception_backtrace
 +    whitelist_key       exception_class
 +    whitelist_key       exception_message
 +
 +    whitelist_key       method
 +    whitelist_key       path
 +    whitelist_key       action
 +    whitelist_key       status
 +    whitelist_key       remote_ip
 +    whitelist_key       controller
 +    whitelist_key       line_id
 +
 +#
 +# FILTERS
 +#
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              nginx_access
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              gitlab_json
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              gitlab_registry
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              sidekiq_json
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              mysql_error
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              mysql_slow
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              postgresql
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              postgresql_detailed
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              nextcloud_access
 +    reserve_data        true
 +    Preserve_Key        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              apache_access
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              php_fpm
 +    reserve_data        true
 +
 +[FILTER]
 +    name                parser
 +    match               docker.*
 +    key_name            raw_log
 +    parser              grafana_regex
 +    reserve_data        true
 +
 +# Структуризация распарсенных полей В raw_log
 +[FILTER]
 +    name                nest
 +    match               docker.*
 +    operation           nest
 +    wildcard            remote_*
 +    wildcard            method
 +    wildcard            path
 +    wildcard            status
 +    wildcard            body_bytes
 +    wildcard            user_agent
 +    wildcard            referrer
 +    wildcard            logger
 +    wildcard            endpoint
 +    wildcard            pluginId
 +    wildcard            dsName
 +    wildcard            dsUID
 +    wildcard            uname
 +    wildcard            level
 +    wildcard            msg
 +    wildcard            statusCode
 +    wildcard            resourcePath
 +    wildcard            exception
 +    nest_under          parsed_data
 +
 +#
 +# FILTERS
 +#
 +
 +# Метаданные Docker
 +[FILTER]
 +    name                lua
 +    match               docker.*
 +    script              /fluent-bit/bin/docker-metadata.lua
 +    call                enrich_with_docker_metadata
 +
 +# Копируем метаданные
 +[FILTER]
 +    name                modify
 +    match               docker.*
 +    copy                docker.hostname hostname
 +    copy                docker.container_started started
 +    copy                docker.container_name container_name
 +    copy                docker.container_name service_name
 +    copy                docker.container_id container_id
 +    copy                docker.state state
 +    copy                docker.stream stream
 +    copy                docker.line_id line_id
 +
 +    copy                log _raw
 +    copy                parsed_data _parsed
 +    # copy                exception_class _class
 +    # copy                exception_message _message
 +    # copy                exception_backtrace _backtrace
 +
 +    copy                docker.label_project project
 +    copy                docker.label_service service
 +    copy                docker.label_logging logging
 +    copy                docker.label_logging_jobname logging_jobname
 +
 +# Структурируем через nest
 +[FILTER]
 +    name                nest
 +    match               docker.*
 +    operation           nest
 +    wildcard            _*
 +    nest_under          log
 +    remove_prefix       _
 +
 +# Добавляем host metadata
 +[FILTER]
 +    name                modify
 +    match               docker.*
 +    set                 node_id ${NODE_ID}
 +    set                 node_name ${NODE_NAME}
 +    set                 host_name ${NODE_NAME}
 +
 +# Перетагиваем только логи с enabled logging
 +[FILTER]
 +    name                rewrite_tag
 +    match               docker.*
 +    rule                $logging ^enabled$ data.$container_id true
 +
 +[FILTER]
 +    name                record_modifier
 +    match               data.*
 +
 +    whitelist_key       date
 +    whitelist_key       log
 +    whitelist_key       exception_class
 +    whitelist_key       exception_message
 +    whitelist_key       exception_backtrace
 +
 +    whitelist_key       method
 +    whitelist_key       path
 +    whitelist_key       action
 +    whitelist_key       status
 +    whitelist_key       remote_ip
 +    whitelist_key       controller
 +    whitelist_key       line_id
 +
 +    whitelist_key       node_id
 +    whitelist_key       node_name
 +    whitelist_key       host_name
 +    whitelist_key       hostname
 +    whitelist_key       started
 +    whitelist_key       container_name
 +    whitelist_key       service_name
 +    whitelist_key       container_id
 +    whitelist_key       stream
 +    whitelist_key       project
 +    whitelist_key       service
 +    whitelist_key       logging_jobname
 +
 +[OUTPUT]
 +    name                loki
 +    match               data.*
 +    host                loki
 +    port                3100
 +    labels              job=$logging_jobname, node_name=$node_name, container_id=$container_id, container_name=$container_name, service_name=$service_name, project=$project, service=$service, level=$stream
 +    label_keys          $node_name,$container_id,$container_name,$service_name,$project,$service
 +    line_format         json
 +    auto_kubernetes_labels off
 +
 +# Только для отладки
 +# [OUTPUT]
 +#     name                stdout
 +#     match               data.*
 +#     format              json
 </code> </code>
  
-=== parsers_multiline.conf ===+=== parsers.conf ===
  
 <code ini> <code ini>
 +# Базовый парсер для Docker JSON логов
 +[PARSER]
 +    Name        docker
 +    Format      json
 +    Time_Key    time
 +    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
 +    Time_Keep   On
 +
 +# Nginx access логи
 +[PARSER]
 +    Name        nginx_access
 +    Format      regex
 +    Regex       ^(?<remote_ip>[^ ]*) - - \[(?<timestamp>[^\]]*)\] "(?<method>\w+) (?<path>[^ ]*) HTTP/[0-9.]+" (?<status>\d+) (?<body_bytes>\d+) "(?<referrer>[^"]*)" "(?<user_agent>[^"]*)"
 +    Time_Key    timestamp
 +    Time_Format %d/%b/%Y:%H:%M:%S %z
 +
 +# Gitlab JSON логи (application logs)
 +[PARSER]
 +    Name        gitlab_json
 +    Format      json
 +    # Time_Key    time    # Используем время из Docker
 +    Time_Keep   On
 +
 +# GitLab Registry логи
 +[PARSER]
 +    Name        gitlab_registry
 +    Format      regex
 +    Regex       ^\d{4}-\d{2}-\d{2}_\d{2}:\d{2}:\d{2}\.\d+ time="(?<time>[^"]*)" level=(?<level>\w+) msg="(?<msg>[^"]*)"(?<rest>.*)
 +    Time_Key    time
 +    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
 +    Time_Keep   On
 +
 +# Sidekiq JSON логи
 +[PARSER]
 +    Name        sidekiq_json
 +    Format      json
 +    # Time_Key    time    # Используем время из Docker
 +    Time_Keep   On
 +
 +# Nextcloud Apache-style логи
 +[PARSER]
 +    Name        nextcloud_access
 +    Format      regex
 +    Regex       ^(?<remote_ip>[^ ]*) (?<user_ident>[^ ]*) (?<user_id>[^ ]*) \[(?<timestamp>[^\]]*)\] "(?<method>\w+) (?<path>[^ ]*) HTTP/[0-9.]+" (?<status>\d+) (?<body_bytes>\d+) "(?<referrer>[^"]*)" "(?<user_agent>[^"]*)"
 +    Time_Key    timestamp
 +    Time_Format %d/%b/%Y:%H:%M:%S %z  # ← Apache/Nginx формат!
 +    Time_Keep   On
 +
 +# Apache access логи
 +[PARSER]
 +    Name        apache_access
 +    Format      regex
 +    Regex       ^(?<remote_ip>[^ ]*) - - \[(?<timestamp>[^\]]*)\] "(?<method>\w+) (?<path>[^ ]*) HTTP/[0-9.]+" (?<status>\d+) (?<body_bytes>\d+) "(?<referrer>[^"]*)" "(?<user_agent>[^"]*)"
 +    Time_Key    timestamp
 +    Time_Format %d/%b/%Y:%H:%M:%S %z
 +
 +# MySQL error логи
 +[PARSER]
 +    Name        mysql_error
 +    Format      regex
 +    Regex       ^(?<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z) (?<level>\w+) (?<message>.*)
 +    Time_Key    timestamp
 +    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
 +    Time_Keep   On
 +
 +# MySQL slow query логи
 +[PARSER]
 +    Name        mysql_slow
 +    Format      regex
 +    Regex       ^# Time: (?<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+Z).*# User@Host: (?<user>[^\[]*)\[(?<database>[^\]]*)\] @ (?<host>[\w\.]*)\s*\[(?<ip>[\d\.]*)\].*# Query_time: (?<query_time>[\d\.]*) Lock_time: (?<lock_time>[\d\.]*) Rows_sent: (?<rows_sent>\d*) Rows_examined: (?<rows_examined>\d*).*use (?<used_database>\w*);.*SET timestamp=(?<timestamp_unix>\d*);(?<query>.*)
 +    Time_Key    timestamp
 +    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
 +    Time_Keep   On
 +
 +# PostgreSQL логи
 +[PARSER]
 +    Name        postgresql
 +    Format      regex
 +    Regex       ^(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d+ [A-Z]{3}) \[(?<pid>\d+)\] (?<level>\w+):\s*(?<message>.*)
 +    Time_Key    timestamp
 +    Time_Format %Y-%m-%d %H:%M:%S.%L %Z
 +    Time_Keep   On
 +
 +# PostgreSQL extended логи (с деталями запросов)
 +[PARSER]
 +    Name        postgresql_detailed
 +    Format      regex
 +    Regex       ^(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d+ [A-Z]{3}) \[(?<pid>\d+)\] (?<level>\w+):\s*duration: (?<duration>[\d\.]*) ms\s*(?<message>.*)
 +    Time_Key    timestamp
 +    Time_Format %Y-%m-%d %H:%M:%S.%L %Z
 +    Time_Keep   On
 +
 +# PHP-FPM логи
 +[PARSER]
 +    Name        php_fpm
 +    Format      regex
 +    Regex       ^\[(?<timestamp>[^\]]+)\] (?<level>\w+): (?<message>.*)
 +    Time_Key    timestamp
 +    Time_Format %d-%b-%Y %H:%M:%S
 +    Time_Keep   On
 +
 +# Стандартный syslog
 +[PARSER]
 +    Name        syslog_rfc3164
 +    Format      regex
 +    Regex       ^\<(?<pri>[0-9]+)\>(?<timestamp>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? (?<message>.*)$
 +    Time_Key    timestamp
 +    Time_Format %b %d %H:%M:%S
 +    Time_Keep   On
 +
 +# Grafana лог формата key=value
 +[PARSER]
 +    Name        grafana_logfmt
 +    Format      logfmt
 +    Time_Key    t
 +    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
 +    Time_Keep   On
  
 +[PARSER]
 +    Name        grafana_regex
 +    Format      regex
 +    Regex       logger=(?<logger>[^ ]*) endpoint=(?<endpoint>[^ ]*) pluginId=(?<pluginId>[^ ]*) dsName=(?<dsName>[^ ]*) dsUID=(?<dsUID>[^ ]*) uname=(?<uname>[^ ]*) t=(?<t>[^ ]*) level=(?<level>[^ ]*) msg="(?<msg>[^"]*)" error=(?<error>[^ ]*) statusCode=(?<statusCode>[^ ]*) resourcePath="(?<resourcePath>[^"]*)"
 +    Time_Key    t
 +    Time_Format %Y-%m-%dT%H:%M:%S.%LZ
 +    Time_Keep   On
 </code> </code>
  
Строка 22: Строка 446:
  
 <code yaml> <code yaml>
 +auth_enabled: false
  
 +server:
 +  http_listen_port: 3100
 +
 +common:
 +  instance_addr: 127.0.0.1
 +  path_prefix: /loki
 +  storage:
 +    filesystem:
 +      chunks_directory: /loki/chunks
 +      rules_directory: /loki/rules
 +  replication_factor: 1
 +  ring:
 +    kvstore:
 +      store: inmemory
 +
 +schema_config:
 +  configs:
 +    - from: 2020-10-24
 +      store: tsdb
 +      object_store: filesystem
 +      schema: v13
 +      index:
 +        prefix: index_
 +        period: 24h
 +
 +ruler:
 +  alertmanager_url: http://localhost:9093
 +
 +limits_config:
 +  retention_period: 720h
 +  reject_old_samples: true
 +  reject_old_samples_max_age: 720h
 +  allow_structured_metadata: true
 +  max_query_length: 721h
 +  
 +ingester:
 +  lifecycler:
 +    ring:
 +      kvstore:
 +        store: inmemory
 +      replication_factor: 1
 +    final_sleep: 0s
 +  chunk_idle_period: 1h
 +  max_chunk_age: 1h
 +  chunk_target_size: 1048576
 +  chunk_retain_period: 30s
 +
 +table_manager:
 +  retention_deletes_enabled: true
 +  retention_period: 720h
 </code> </code>
  
Строка 34: Строка 509:
  
 <code bash> <code bash>
 +# Проверяем конфигурацию
 +$ docker exec -it <fluentbit_container> /fluent-bit/bin/fluent-bit -c /fluent-bit/etc/fluent-bit.conf --dry-run
  
 +# Смотрим логи
 +$ docker service logs logging_fluent-bit
 +
 +# Проверяем метрики
 +$ curl http://localhost:2020/api/v1/metrics | jq
 +
 +# Тестируем парсеры
 +$ echo '2025-11-21T02:13:34.366Z {"method":"PUT","path":"/projects","status":500}' | \
 +$ docker exec -i <fluentbit_container> /fluent-bit/bin/fluent-bit -c /fluent-bit/etc/fluent-bit.conf -i stdin -o stdout
 </code> </code>
  
 ==== Запросы в Grafana ==== ==== Запросы в Grafana ====
  
-<code>+<code json>
 {job="fluent-bit"} |= "gitlab" {job="fluent-bit"} |= "gitlab"
-</code> 
  
-<code> 
 {container_name="gitlab" {container_name="gitlab"
-</code> 
  
-<code> 
 {job="fluent-bit"} |~ "(?i)error|exception|fail" {job="fluent-bit"} |~ "(?i)error|exception|fail"
-</code> 
  
-<code> 
 {node_name="node-1"} {node_name="node-1"}
-</code> 
  
-<code> 
 # Все логи GitLab # Все логи GitLab
 {container_name=~".*gitlab.*" {container_name=~".*gitlab.*"
-</code> 
  
-<code> 
 # Логи по компонентам # Логи по компонентам
 {container_name=~".*gitlab.*"} | json | component="gitaly.UnaryServerInterceptor" {container_name=~".*gitlab.*"} | json | component="gitaly.UnaryServerInterceptor"
-</code> 
  
-<code> 
 # Ошибки # Ошибки
 {container_name=~".*gitlab.*"} | json | level="error" {container_name=~".*gitlab.*"} | json | level="error"
-</code> 
  
-<code> 
 # Запросы с определенным correlation_id # Запросы с определенным correlation_id
 {container_name=~".*gitlab.*"} | json | correlation_id="01KAJ30DCE4BW6JSAT7KHGZ9PX" {container_name=~".*gitlab.*"} | json | correlation_id="01KAJ30DCE4BW6JSAT7KHGZ9PX"
-</code> 
  
-<code> 
 # Логи Sidekiq # Логи Sidekiq
 {container_name=~".*gitlab.*"} | json | severity="INFO" {container_name=~".*gitlab.*"} | json | severity="INFO"
 +
 +# Все логи GitLab с parsed_data
 +{container_name=~".*gitlab.*"} | json
 +
 +# Логи с ошибками
 +{environment="production"} | json | level="error" 
 +
 +# Медленные PostgreSQL запросы
 +{service_name=~".*postgres.*"} | json | duration > 1000
 +
 +# Nginx 5xx ошибки
 +{container_name=~".*nginx.*"} | json | status >= 500
 +
 +# Sidekiq логи
 +{container_name=~".*sidekiq.*"} | json | severity="INFO"
 </code> </code>