Promtail and Grafana - json log file from docker container not displayed - docker

my application's services are deployed via docker-compose. Currently, I also deployed Grafana, Loki and Promtail within the same docker-compose network.
Following the getting-started guide, collecting and displaying the log files from /var/log with the config
- job_name: system
entry_parser: raw
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*log
works fine.
However, my backend logs (NestJS) into a log file which is stored in a docker volume.
Example log entry:
{"message":"Mapped {/api/drink, POST} route","context":"RouterExplorer","level":"info","timestamp":"2021-03-23T17:08:16.334Z"}
The path to the log is
/var/lib/docker/volumes/my_volume/_data/general.log
When I add the following config to Promtail
- job_name: backend
pipeline_stages:
- json:
expressions:
level: level
message: message
timestamp: timestamp
context: context
static_configs:
- targets:
- localhost
labels:
job: backend
__path__: /var/lib/docker/volumes/my_volume/_data/general.log
and use the query {job="backend"} in Grafana, nothing is displayed.
Furthermore, the log of the promtail container doesn't give any information.
What am I missing?
Thank you in advance!

In your pipeline stages you need to store the extracted values:
pipeline_stages:
- json:
expressions:
level: level
message: message
timestamp: timestamp
context: context
- timestamp:
source: timestamp
- labels:
level:
context:
- output:
source: message
This will set the timestamp, the labels context, level and the message will be the log line.
Documentation can be found here.

Related

Collecting Docker events logs with Promtail

How can I get logs from docker events to Promtail?
I'm using Docker to run a set of containers on my server, and I would like to collect and centralize their logs using Promtail. Specifically, I would like to capture logs from the docker events(logs from the docker daemon about when the container is started, etc. ) command and send them to Promtail.
How can I achieve this? What are the steps and configurations I need to set up in order to get logs from docker events to Promtail?
Note that my Docker host is running on a Windows machine, and I'm using the latest version of Promtail.
my promtail.yaml file :
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: flog_scrape
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
filters:
- name: label
values: ["logging=promtail"]
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'logstream'
- source_labels: ['__meta_docker_container_label_logging_jobname']
target_label: 'job'
Any help or advice would be greatly appreciated. Thank you!

remove timestamp from log line with Promtail

I am scraping logs from docker with Promtail to Loki.
Works very well, but I would like to remove timestamp from log line once it has been extracted by Promtail.
The reason is that I end up with log panel that half of screen is occupied by timestamp. If I want to display timestamp in panel, I can do that, so I dont really need it in log line.
I have been reading documentation, but not sure how to approach it. logfmt? replace? timestamp?
https://grafana.com/docs/loki/latest/clients/promtail/stages/logfmt/
promtail-config.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# local machine logs
- job_name: local logs
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*log
# docker containers
- job_name: containers
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 15s
pipeline_stages:
- docker: {}
relabel_configs:
- source_labels: ['__meta_docker_container_label_com_docker_compose_service']
regex: '(.*)'
target_label: 'service'
Thank you
Actually I just realized I was looking for wrong thing. I just wanted to display less logs in Grafana, logs were formatted properly. I just had to select fields to display.
Thanks!

How to get container id from first docker-compose service inside second service?

I want to run filebeat as a sidecar container next to my main application container to collect application logs. I'm using docker-compose to start both services together, filebeat depending on the application container.
This is all working fine. I'm using a shared volume for the application logs.
However I would like to collect docker container logs (stdout JSON driver) as well in filebeat.
Filebeat provides a docker/container input module for this purpose. Here is my configuration. First part is to get the application logs. Second part should get docker logs:
filebeat.inputs:
- type: log
paths:
- /path/to/my/application/*.log.json
exclude_lines: ['DEBUG']
- type: docker
containers.ids: '*'
json.message_key: message
json.keys_under_root: true
json.add_error_key: true
json.overwrite_keys: true
tags: ["docker"]
What I don't like it the containers.ids: '*'. Here I would want to point filebeat to the direct application container, ignoring all others.
Since I don't know the container ID before I run docker-compose up starting both containers, I was wondering if there is a easy way to get the container ID from my application container in my filebeat container (via docker-comnpose?) to filter on this ID?
I think you may work around the problem:
first set all the logs from the contianer to a syslog:
driver: "syslog"
options:
syslog-address: "tcp://localhost:9000"
then configure filebeat to get the logs from that syslog server like this:
filebeat.inputs:
- type: syslog
protocol.udp:
host: "localhost:9000"
This is also not really answering the question, but should work as a solution as well.
The main idea is to use label within the filebeat autodiscovery filter.
Taken from this post: https://discuss.elastic.co/t/filebeat-autodiscovery-filtering-by-container-labels/120201/5
filebeat.yml
filebeat.autodiscover:
providers:
- type: docker
templates:
- condition:
contains:
docker.container.labels.somelabel: "somevalue"
config:
- type: docker
containers.ids:
- "${data.docker.container.id}"
output.console:
pretty: true
docker-compose.yml:
version: '3'
services:
filebeat:
image: docker.elastic.co/beats/filebeat:6.2.1
command: "--strict.perms=false -v -e -d autodiscover,docker"
user: root
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml
- /var/lib/docker/containers:/var/lib/docker/containers
- /var/run/docker.sock:/var/run/docker.sock
test:
image: alpine
command: "sh -c 'while true; do echo test; sleep 1; done'"
depends_on:
- filebeat
labels:
somelabel: "somevalue"

With Prometheus how to monitor a scaled Docker service where each instance serves its own /metrics?

I have a Prometheus setup that monitors metrics exposed by my own services. This works fine for a single instance, but once I start scaling them, Prometheus gets completely confused and starts tracking incorrect values.
All services are running on a single node, through docker-compose.
This is the job in the scrape_configs:
- job_name: 'wowanalyzer'
static_configs:
- targets: ['prod:8000']
Each instance of prod tracks metrics in its memory and serves it at /metrics. I'm guessing Prometheus picks a random container each time it scraps which leads to the huge increase in counts recorded, building up over time. Instead I'd like Prometheus to read /metrics on all instances simultaneously, regardless of the amount of instances active at that time.
docker-gen (https://github.com/jwilder/docker-gen) was developed for this purpose.
You would need to create a sidecart container running docker-gen that generates a new set of targets.
If I remember well the host names generated are prod_1, prod_2, prod_X, etc.
I tried a lot to find something to help us with this issue but it looks an unsolved issue.
So, I decided to create this tool that helps us with this service-discovery.
https://github.com/juliofalbo/docker-compose-prometheus-service-discovery
Feel free to contribute and open issues!
You can use DNS service discovery feature. For example:
docker-compose.yml:
version: "3"
services:
myapp:
image: appimage:v1
restart: always
networks:
- back
prometheus:
image: "prom/prometheus:v2.32.1"
container_name: "prometheus"
restart: "always"
ports: [ "9090:9090" ]
volumes:
- "./prometheus.yml:/etc/prometheus/prometheus.yml"
- "prometheus_data:/prometheus"
networks:
- back
prometheus.yml sample:
global:
scrape_interval: 15s
evaluation_interval: 60s
scrape_configs:
- job_name: 'monitoringjob'
dns_sd_configs:
- names: [ 'myapp' ] <-- service name from docker-compose
type: 'A'
port: 8080
metrics_path: '/actuator/prometheus'
You can check your DNS records using nslookup util from any container in this network:
docker exec -it myapp bash
bash-4.2# yum install bind-utils
bash-4.2# nslookup myapp
Server: 127.0.0.11
Address: 127.0.0.11#53
Non-authoritative answer:
Name: myapp
Address: 172.22.0.2
Name: myapp
Address: 172.22.0.7

Failing to deploy a neo4j service as a docker stack using Docker Swarm via a docker-compose file

I am trying to configure a docker-compose.yml (I am aware version and services is not stated, they are apart of the file) file to run a neo4j instance. I am using docker swarm and deploying a stack i.e. used the following commands:
docker swarm init
docker stack deploy -c docker-compose.yml neo
note_db:
image: neo4j:latest
environment:
- NEO4J_AUTH=<username>/<password>
- NEO4J_dbms_mode=CORE
- NEO4J_ACCEPT_LICENSE_AGREEMENT=yes
- NEO4J_dbms_connector_http_listen__address=:7474
- NEO4J_dbms_connector_https_listen__address=:6477
- NEO4J_dbms_connector_bolt_listen__address=:7687
ports:
- "7474:7474"
- "6477:6477"
- "7687:7687"
volumes:
- type: bind
source: ~/neo4j/data
target: /data
- type: bind
source: ~/neo4j/logs
target: /logs
deploy:
replicas: 1
resources:
limits:
cpus: "0.1"
memory: 120M
restart_policy:
condition: on-failure
I have omitted the username and password. I am currently only trying to spin up one instance as I am still testing. I have removed NEO4J_AUTH as well as NEO4J_AUTH=none, with the same outcome.
The logs provide the following:
org.neo4j.commandline.admin.CommandFailed: initial password was not set because live Neo4j-users were detected., at org.neo4j.commandline.admin.security.SetInitialPasswordCommand.setPasswor (SetInitialPasswordCommand.java:83)
command failed: initial password was not set because live Neo4j-users were detected.,
Starting Neo4j.,
2018-09-17 16:12:39.396+0000 INFO ======== Neo4j 3.4.7 ========,
2018-09-17 16:12:41.990+0000 INFO Starting...,
2018-09-17 16:12:43.792+0000 ERROR Failed to start Neo4j: Starting Neo4j failed: Component 'org.neo4j.server.database.LifecycleManagingDatabase#70b0b186' was successfully initialized, but failed to start. Please see the attached cause exception "/logs/debug.log (Permission denied)".
In the debug.log file, the only things I found is :
[o.n.b.s.a.BasicAuthentication] Failed authentication attempt for 'neo4j' (no other failures, errors or warnings).
Clearly, I have some sort of auth issue but I am not sure where the error lies and how to address it. I have attempted NEO4J_AUTH=none and removing the ENV completely, it still does not work.
Someone has posted something along the lines of this issue but they haven't received any responses. I am hoping mine does.
FROM user: logisima
You don't have any issue with auth, it's a permission issue : cause exception "/logs/debug.log (Permission denied)"

Resources