Files

144 lines
5.7 KiB
YAML

extensions:
file_storage:
directory: /var/lib/han-otel/host-collector
timeout: 10s
receivers:
filelog/docker:
include: [/var/lib/docker/containers/*/*-json.log]
start_at: end
include_file_path: true
storage: file_storage
operators:
- type: json_parser
id: docker-json
timestamp:
parse_from: attributes.time
layout_type: gotime
layout: "2006-01-02T15:04:05.000000000Z07:00"
- type: regex_parser
id: docker-service-label
parse_from: attributes["attrs"]["tag"]
if: 'attributes["attrs"]["tag"] != nil'
regex: '^(?P<docker_service>nginx|keycloak|redis)$'
- type: move
from: attributes.docker_service
to: resource["service.name"]
- type: move
from: attributes.stream
to: attributes["log.iostream"]
- type: move
from: attributes.log
to: body
- type: json_parser
id: structured-body
parse_from: body
parse_to: attributes
if: 'body matches "^\\s*\\{"'
on_error: send
journald/host:
directory: /var/log/journal
units:
- docker.service
- han-stack@production.service
- han-secrets@production.service
- han-chat-docker-firewall.service
- certbot.service
- fail2ban.service
priority: info
start_at: end
storage: file_storage
processors:
memory_limiter:
check_interval: 1s
limit_mib: 192
spike_limit_mib: 48
resource/common:
attributes:
- {key: service.namespace, value: han-chat, action: upsert}
- {key: deployment.environment, value: "${env:APP_ENV}", action: upsert}
- {key: service.version, value: "${env:RELEASE_VERSION}", action: upsert}
- {key: host.name, value: "${env:HOST_NAME}", action: upsert}
transform/journal:
error_mode: ignore
log_statements:
- context: log
statements:
- set(resource.attributes["service.name"], attributes["_SYSTEMD_UNIT"]) where resource.attributes["service.name"] == nil and attributes["_SYSTEMD_UNIT"] != nil
- set(attributes["event.source"], "journald") where attributes["_SYSTEMD_UNIT"] != nil
- set(attributes["event.source"], "docker-json-file") where attributes["_SYSTEMD_UNIT"] == nil
- set(attributes["route.class"], "api") where resource.attributes["service.name"] == "nginx" and IsMatch(attributes["uri"], "^/api/")
- set(attributes["route.class"], "auth") where resource.attributes["service.name"] == "nginx" and IsMatch(attributes["uri"], "^/auth/")
- set(attributes["route.class"], "bitrix") where resource.attributes["service.name"] == "nginx" and IsMatch(attributes["uri"], "^/bitrix/")
- set(attributes["route.class"], "callbacks") where resource.attributes["service.name"] == "nginx" and IsMatch(attributes["uri"], "^/callbacks/")
- set(attributes["route.class"], "static") where resource.attributes["service.name"] == "nginx" and attributes["route.class"] == nil
- replace_pattern(body, "(?i)(Bearer|Basic)\\s+[A-Za-z0-9._~+/=-]+", "$$1 [REDACTED]") where IsString(body)
- replace_pattern(body, "(?i)(token|secret|password|code)=([^&\\s]+)", "$$1=[REDACTED]") where IsString(body)
- set(body, "nginx.access") where resource.attributes["service.name"] == "nginx" and attributes["log.iostream"] == "stdout"
- set(body, "keycloak.event") where resource.attributes["service.name"] == "keycloak" and attributes["log.iostream"] == "stdout"
attributes/redact:
actions:
- {key: authorization, action: delete}
- {key: http.request.header.authorization, action: delete}
- {key: http.request.header.cookie, action: delete}
- {key: http.response.header.set-cookie, action: delete}
- {key: url.query, action: delete}
- {key: url.full, action: delete}
- {key: http.target, action: delete}
- {key: http.request.body, action: delete}
- {key: db.statement, action: delete}
- {key: message, action: delete}
- {key: payload, action: delete}
- {key: user.phone, action: delete}
- {key: user.email, action: delete}
- {key: remote_addr, action: delete}
- {key: user_agent, action: delete}
- {key: uri, action: delete}
filter/allowlist:
error_mode: ignore
logs:
log_record:
- 'attributes["_SYSTEMD_UNIT"] == nil and resource.attributes["service.name"] != "nginx" and resource.attributes["service.name"] != "keycloak" and resource.attributes["service.name"] != "redis"'
- 'resource.attributes["service.name"] == "otel-collector" or resource.attributes["service.name"] == "otel-host-collector"'
filter/noise:
error_mode: ignore
logs:
log_record:
- 'resource.attributes["service.name"] == "nginx" and severity_number < SEVERITY_NUMBER_WARN and IsMatch(body, "(/health/live|/nginx-health/live|/.well-known/acme-challenge/)")'
batch:
timeout: 5s
send_batch_size: 512
send_batch_max_size: 1024
exporters:
otlp/remote:
endpoint: "${env:OTEL_REMOTE_ENDPOINT}"
headers:
authorization: ${file:/run/han-chat/secrets/OTEL_REMOTE_AUTH_HEADER}
tls:
insecure: "${env:OTEL_REMOTE_TLS_INSECURE}"
sending_queue:
enabled: true
queue_size: 5000
storage: file_storage
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 0s
service:
extensions: [file_storage]
pipelines:
logs:
receivers: [filelog/docker, journald/host]
processors:
[memory_limiter, resource/common, filter/allowlist, filter/noise, transform/journal, attributes/redact, batch]
exporters: [otlp/remote]
telemetry:
logs:
level: error
metrics:
level: none