0

This is the input file:

{"meta":"","level":"error","message":"clientErrorHandler: Erro não previsto ou mapeado durante chamada dos serviços.","timestamp":"2017-04-06T16:08:37.861Z"}
{"meta":"","level":"error","message":"clientErrorHandler: Erro não previsto ou mapeado durante chamada dos serviços.","timestamp":"2017-04-06T19:40:17.682Z"}

Basically, such log is the outcome of my NodeJs Application via Winstom module. My doubt focuses how to adjust the logstash filter in order to get 4 fields created in ElasticSearch.

My intention is to see "columns" (properties or fileds may be better words in ElasticSearch context I guess): level (eg. error), message_source (eg. clientErrorHandler), message_content (eg. Erro não ...serviços) and error_time without nanoseconds (eg. 2017-04-06T19:40:17).

I got stuck on this point:

1 - I used this logstash.conf

input {
    file {
         path => "/home/demetrio/dev/testes_manuais/ELK/logs/*"
         start_position => "beginning"

   }
}

filter {

  grok {
        match => {
        "message" => '%{SYSLOG5424SD:loglevel} %{TIMESTAMP_ISO8601:Date} %{GREEDYDATA:content}'
      }
  }

  date {
    match => [ "Date", "YYYY-mm-dd HH:mm:ss.SSS" ]
    locale => en
  }

}

output {
  stdout {
    codec => plain {
                        charset => "ISO-8859-1"
                }

    }
    elasticsearch {
        hosts => "http://127.0.0.1:9200"
        index => "dmz-logs-indice"

  }
}

2 - search ElasticSearch via Kibana DevTools

GET _search
{
  "query": {
    "match_all": {}
  }
}

and I saw:

{
  "took": 5,
  "timed_out": false,
  "_shards": {
    "total": 6,
    "successful": 6,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": ".kibana",
        "_type": "config",
        "_id": "5.3.0",
        "_score": 1,
        "_source": {
          "buildNum": 14823
        }
      },
      {
        "_index": "dmz-logs-indice",
        "_type": "logs",
        "_id": "AVtJLZ5x6gscWn5fxxA_",
        "_score": 1,
        "_source": {
          "path": "/home/demetrio/dev/testes_manuais/ELK/logs/logs.log",
          "@timestamp": "2017-04-07T16:09:36.996Z",
          "@version": "1",
          "host": "nodejs",
          "message": """{"meta":"","level":"error","message":"clientErrorHandler: Erro não previsto ou mapeado durante chamada dos serviços.","timestamp":"2017-04-06T16:08:37.861Z"}""",
          "tags": [
            "_grokparsefailure"
          ]
        }
      },
      {
        "_index": "dmz-logs-indice",
        "_type": "logs",
        "_id": "AVtJLZ5x6gscWn5fxxBA",
        "_score": 1,
        "_source": {
          "path": "/home/demetrio/dev/testes_manuais/ELK/logs/logs.log",
          "@timestamp": "2017-04-07T16:09:36.998Z",
          "@version": "1",
          "host": "nodejs",
          "message": """{"meta":"","level":"error","message":"clientErrorHandler: Erro não previsto ou mapeado durante chamada dos serviços.","timestamp":"2017-04-06T19:40:17.682Z"}""",
          "tags": [
            "_grokparsefailure"
          ]
        }
      }
    ]
  }
}

I guess I should use some RegularExpresss or Grok in order to divide in four peaces:

1 - level 2 - message with what come before ":" 3 - message with what come after ":" 4 - timestamp

And, if it is possible, provide better column (field/property) labels like:

1 - level 2 - message_source 3 - message_content 4 - error_time

And finally remove the timestamp nanoseconds

PS. Just in case some future reader get interested on how I am logging in NodeJs, here you are:

...

var winston = require('winston');
winston.emitErrs = true;

var logger = new winston.Logger({
    transports: [
        new winston.transports.File({
            level: 'error',
            filename: './logs/logs.log',
            handleExceptions: true,
            json: true,
            maxsize: 5242880, //5MB
            maxFiles: 5,
            colorize: false,
            prettyPrint: true
        })               
    ],
    exitOnError: false
});

...

function clientErrorHandler(err, req, res, next) {
      logger.log("error","clientErrorHandler: Erro não previsto ou mapeado durante chamada dos serviços.",err.message);

      res.send(500, { error: 'Erro genérico!' });

  }

app.use(clientErrorHandler);

PS2: I carefully read questions like Filter specific Message with logstash before sending to ElasticSearch but I am really stuck

Community
  • 1
  • 1
DemeCarvO
  • 487
  • 4
  • 16
  • 28

1 Answers1

1

Since your application outputs log as JSON string, you can configure Logstash to parse the log as JSON. This is as simple as adding codec => "json" into the file input configuration.

Below is an example configuration for your scenario:

input {
  file {
    path => "/home/demetrio/dev/testes_manuais/ELK/logs/*"
    start_position => "beginning"
    codec => "json"
  }
}

filter {
  # This matches `timestamp` field into `@timestamp` field for Kibana to consume.
  date {
    match => [ "timestamp", "ISO8601" ]
    remove_field => [ "timestamp" ]
  }
}

output {
  stdout {
    # This codec gives your more details about the event.
    codec => rubydebug
  }

  elasticsearch {
    hosts => "http://127.0.0.1:9200"
    index => "dmz-logs-indice"
  }
}

This is the sample stdout from Logstash:

{
          "path" => "/home/demetrio/dev/testes_manuais/ELK/logs/demo.log",
    "@timestamp" => 2017-04-06T19:40:17.682Z,
         "level" => "error",
          "meta" => "",
      "@version" => "1",
          "host" => "dbf718c4b8e4",
       "message" => "clientErrorHandler: Erro não previsto ou mapeado durante chamada dos serviços.",
}
Tim Wong
  • 600
  • 3
  • 9
  • thanks. I am just missing how to accomplish this part of my question "My intention is to see "columns" (properties or fileds may be better words in ElasticSearch context I guess): level (eg. error), message_source (eg. clientErrorHandler), message_content (eg. Erro não ...serviços) and error_time without nanoseconds (eg. 2017-04-06T19:40:17)". My final intention is to separate such message text. With your answer, I get the entire message in a single field. – DemeCarvO Apr 10 '17 at 14:45