Git Product home page Git Product logo

gelf-php's Issues

Closed connections and timeouts on TcpTransport (was: Incomplete write: Only 0 of 358 written)

Hello! I have bug when i write log to GrayLog on the large load project. There is the bug:
Incomplete write: Only 0 of 358 written in /data/home/projects/payprocessing/classes/vendor/graylog2/gelf-php/src/Gelf/Transport/StreamSocketClient.php:212

Here is the message send to socket:

{
"version": "1.0",
"host": "pay-1.reserve.lan",
"short_message": "Redirect to https://www.platron.ru/payment_params.",
"full_message": "Redirect to https://www.platron.ru/payment_params.php?customer=5d44643437990b1774efb742ed1fb9a031005685\r\n(Process number: 84073)",
"level": 6,
"timestamp": 1484144247.0146,
"facility": "paypocessing",
"file": "Platron::payment"
}

I try to send id manual - and it's worked! So the problem in fwrite function. There is a notice in php documentation about fwrite function:

http://php.net/manual/en/function.fwrite.php

Some people say that when writing to a socket not all of the bytes requested to be written may be written. You may have to call fwrite again to write bytes that were not written the first time. (At least this is how the write() system call in UNIX works.)

I think you need to try fwrite_retry several times, before throw error, or, maybe, use some other function.

Why Logger::interpolate() is private ???

Hello,
I'm switching from an old GELF lib to yours and I needed to do some adjustments regarding our needs.

I was wondering if is there is any interest of having this following method to be private:

    private static function interpolate($message, array $context)
    {
        // build a replacement array with braces around the context keys
        $replace = array();
        foreach ($context as $key => $val) {
            $replace['{' . $key . '}'] = $val;
        }

        // interpolate replacement values into the message and return
        return strtr($message, $replace);
    }

Instead of simply overriding the interpolate like that:

    protected static function interpolate($message, array $context)
    {
        // Do some stufff
       return parent::interpolate($message, $context);
    }

I have to override the protected function initMessage($level, $message, array $context) method :/

Replace all occurances of StringableClass

In some unittests a dummy class Gelf\Test\StringableClass is used.

  1. Replace all occurances with
$toString = $this->getMock('dummyClass', array('__toString'));
$toString->method('__toString')->willReturn('toString');
  1. Delete class
  2. Remove require_once for class in tests/bootstrap.php

StreamSocketClient throws exception

Does it make sense that StreamSocketClient::buildSocket method throws exception if it can't connect? I mean if graylog server is down, nobody is catching this exception and my app is no available. Or one of solution would be instead of RuntimeException throw more specific exception that i could catch and handle it.

Issues with setAdditional

Hello,

Is anyone having issues with $message->setAdditional($key,$value) function. Here is the test script

<?php
require_once __DIR__ . '/vendor/gelf-php/gelf-php-master/vendor/autoload.php';
$transport = new Gelf\Transport\TcpTransport("<IP>, <PORT>);
$publisher = new Gelf\Publisher();
$publisher->addTransport($transport);
$message = new Gelf\Message();
$message->setShortMessage("It works in TCP!")
        ->setLevel(\Psr\Log\LogLevel::ALERT)
        ->setFullMessage("There was a foo in bar")
        ->setFacility("local8")
;
$message->setAdditional("IP", "10.4.13.45");
//var_dump($message);
$publisher->publish($message);
var_dump($publisher);

it works without setAdditional. And I do not see an error with setAdditional part of the script but nothing gets pushed to the graylog server.

Decide on a new minimum version

Potential candidates:

  • 7.2: Current active version
  • 7.3: Typehints for properties

Ruled out:

  • Anything 5.x -- even good old PHP5.6 is out of support
  • 7.1: Almost EOL'd and PHP7 users are usually faster to upgrade anyway

Message with boolean value is filtered out

Currently, if some key has boolean value, is wrongly converted empty string and filtered out as empty value. #38 solves this, but it's somehow stuck and also solves an another problem.

Provide example configs for Symfony (was: How to configure IgnoreErrorTransportWrapper in config.yml symfony2 project ?)

I'm trying to stream logs from a symfony 2 app to a graylog 2 server using the gelf format.
My monolog configuration looks as follows:
monolog: handlers: graylog: type: gelf publisher: hostname: my-graylog-server.com port: 12201 level: debug formatter: app.gelf_formatter
I'm getting a connection refused error when the graylog server is not available.
[2017-07-28 16:03:25] app.ERROR: Failed to write to socket: fwrite(): send of 153 bytes failed with errno=111 Connection refused (8) [] []
This is why I'm looking for how to set IgnoreErrorTransportWrapper option in my config.yml
Any help would be greatly appreciated!

Better support for different versions of Gelf

In gelf-php 1.* the support for GELF 1.0 and 1.1 is hardcoded into Message:toArray.

2.0 should have better support for current and future versions of GELF in regards to architecture, message transformation and serialization.

Fix SSL deprecation warnings

Deprecated: SNI_server_name is deprecated in favor of peer_name in /var/www/vendor/graylog2/gelf-php/src/Gelf/Transport/StreamSocketClient.php on line 153

Deprecated: the 'CN_match' SSL context option is deprecated in favor of 'peer_name' in /var/www/vendor/graylog2/gelf-php/src/Gelf/Transport/StreamSocketClient.php on line 153

See #69

fwrite return values

Hello,

I use php 5.6 on debian jessy.
I have a problem with TCPTransport.

I establish a connection to tha graylog2 server.
Everything is fine but when an error occurred, for example "Connection reset by peer" or "Broken pipe" - when I shutdown graylog2 infrastructure
fwrite returns with int(0), not boolean false value so "Failed to write to socket" exception will not be thrown because of $byteCount === false condition

Only the the following notice are generated:
Message: fwrite(): send of 166 bytes failed with errno=104 Connection reset by peer
Message: fwrite(): send of 166 bytes failed with errno=32 Broken pipe

Thx,
Cyr

Named constructor HttpTransport::fromUrl

It'd be a nice addition for HttpTransport to have string-constructor like $transport = HttpTransport::fromUrl("http://logs.example.org:8080/gelf").

  • Use http://php.net/manual/function.parse-url.php
  • http and https should set their port automatically if not specified
  • Maybe allow an optional detailed SslOptions-object as a 2nd paramater (see #24)?

/cc @steffkes

Option to do connection via Proxy

Would be nice to have an option to initialize HttpTransport / socket-client via Proxy.
Maybe like this :

$opts = array('http' => array('proxy' => 'tcp://127.0.0.1:8080', 'request_fulluri' => true));
$context = stream_context_create($opts);

Validation fails when logging a zero value

Both of the following fail validation:

$logger->info(0);

and

$logger->info('0');

Why are these not valid log messages? Could the validator check for an empty string instead of a "falsey" value? Or are falsey values also forbidden by the graylog specification. Happy to try and submit a PR if required.

Hope you can help
Cheers

400 Bad Request when using SSL and SAN certificates

We have our graylog instance sitting on a server that is not directly reachable from the Internet. In order to allow access to the HTTP GELF input, we defined a ProxyPass on a publicly visible server like so:

    <Location /gelf/>
        ProxyPass http://10.24.0.42:12201/gelf
        ProxyPassReverse http://10.24.0.42:12201/gelf
    </Location>

However, trying to establish a connection to graylog through this using the stream_socket_client as the StreamSocketClient does, always results in a 400 - Bad Request response by the Apache server:

RuntimeException: Graylog-Server didn't answer properly, expected 'HTTP/1.x 202 Accepted', response is 'HTTP/1.1 400 Bad Request Date: Thu, 22 Sep 2016 17:44:48 GMT Server: Apache/2.4.10 (Debian) Content-Length: 445 Connection: close Content-Type: text/html; charset=iso-8859-1' in /var/www/vendor/graylog2/gelf-php/src/Gelf/Transport/HttpTransport.php on line 189

Using curl, there's no issue at all:

kwisatz@mazer:~$ curl -i -XPOST https://graylog.domain.tld/gelf/ -p0 -d '{"short_message":"Hello there", "host":"example.org", "facility":"test", "_foo":"bar"}'
HTTP/1.1 202 Accepted
Date: Thu, 22 Sep 2016 17:15:07 GMT
Server: Apache/2.4.10 (Debian)
Content-Length: 0
Strict-Transport-Security: max-age=15768000
Connection: close

I've been trying to figure out if I had to configure mod_proxy differently for this to work but haven't really found any useful clues. I'm also not familiar with PHP's stream_socket_client and how this works on ssl:// socket connections.

It works just fine when not using SSL, but I'd really prefer not to send this data over the wire in plain-text.

I was hoping someone might have had the same issue already and solved it or someone might know how to configure mod_proxy with Apache?

Or, failure to figure this out, would it be possible to switch out the socketClient for a simple php-curl client?

How to set $connectTimeout for UdpTransport?

Hi,

is there any way to set $connectTimeout for UdpTransport - which uses StreamSocketClient? Or maybe get access to the $socketClient so we could set it after initializing the UdpTransport?

Thanks,
Patryk

Add HTTP-Authentication support to HttpTransport

Securing the GELF-endpoint behind authentication is a common usecase.

We probably do not need a constructor-argument though. An HTTP-Authentication header can be added at each request. It's not required on stream-connect. setAuthentication($user, $password) should be sufficient.

Also only supporting baisc-mode is okay initially, I think.

/cc @steffkes

Is CHUNK_MAX_COUNT too big?

A message MUST NOT consist of more than 128 chunks.
(c) https://www.graylog.org/resources/gelf/

But I see that your lib allowing up to 256 chunks. Please clarify which is correct.

Also I see logstash logs messages like this:

{
  :timestamp=>"2015-10-14T13:38:01.927000+0300",
  :message=>"Gelfd failed to parse a message skipping",
  :exception=>#<Gelfd::TooManyChunksError: 130 greater than 128>,
  :backtrace=>[
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/gelfd-0.2.0/lib/gelfd/chunked_parser.rb:40:in `parse_chunk'",
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/gelfd-0.2.0/lib/gelfd/chunked_parser.rb:8:in `parse'",
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/gelfd-0.2.0/lib/gelfd/parser.rb:10:in `parse'",
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-input-gelf-1.0.0/lib/logstash/inputs/gelf.rb:100:in `udp_listener'",
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-input-gelf-1.0.0/lib/logstash/inputs/gelf.rb:62:in `run'",
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-core-1.5.4-java/lib/logstash/pipeline.rb:177:in `inputworker'",
    "/opt/logstash/vendor/bundle/jruby/1.9/gems/logstash-core-1.5.4-java/lib/logstash/pipeline.rb:171:in `start_input'"
  ],
  :level=>:warn
}

Publish/tag a version ?

Hi,

We have some issues with UDP transport and the 1.5.3 version (Incomplete write: Only 0 of XXX written)
d98632d seems to correct it. Can you publish a tagged version with these changes ?

Thx a lot !

Extensive documentation

Currently the documentation is almost non existent. This should be changed.

  • Explain architecture with comprehensive examples
  • Explain integration into monolog
  • Update README with links to new docs

Fix message-to-array conversion / better support for multiple GELF standards

Tasklist

  • Move message-to-array logic to classes (separate ones for 1.0 and 1.1) SerializerInterface which convert the message to a JsonSerializable structure
  • Move any logic revolving around $version or getVersion from Message to the serializers
  • Move message-validation to serializers

Original issue

There is currently a condition in place to handle 1.0 and 1.1 message serialization. (

if ($this->getVersion() == "1.1") {
)

When the GELF 2.0 spec is finalized, we need a better way to support multiple GELF standards.

Achieving this without breaking BC would be optimal. I'd rather not force GELF 2.0 users to a 2.0 upgrade, but if there is no way around so be it.

Too simple check in Gelf/Message leads to RuntimeException

It seems that i hit a rare condition in Gelf\Message::setAdditional:

if the contextPrefix in the GelfMessageFormatter is an empty string - no prefixing - and the context is an associative array (like from a doctrine select statement):

array:7 [
  "message" => "SELECT u0_.uuid AS uuid_0, u0_.username AS username_1, u0_.password AS password_2, u0_.roles AS roles_3, u0_.expired AS expired_4, u0_.locked AS locked_5, u0_.enabled AS enabled_6, u0_.credentials_expired AS credentials_expired_7 FROM "user" u0_ WHERE u0_.username = ?"
  "context" => array:1 [
    0 => "test"
  ]
  "level" => 100
  "level_name" => "DEBUG"
  "channel" => "doctrine"
  "datetime" => "1524690309.189944"
  "extra" => []
]

the condition if(!$key) will raise the RuntimeException (since !0 == true).

PHP errors for non-string context values

When the log() $context array contains non-string values (such as other arrays), a PHP Notice and PHP Warning are generated as the values are treated as if they will always be strings.

PSR-3 §1.3 states that the context array can contain anything, and the implementation "MUST NOT (...) raise any php error, warning or notice".

It seems that the notice arises from the interpolate() method which is a copy of the FIG example code (shame!) and the warning from a specific implementation in Message::toArray() which filters out non-strings.

If a non-string is encountered it would be good to modify it, such as running arrays through json_encode()

GELF v1.1 compatibility

This library does not work when using against a Graylog2 v0.20 server, because the GELF specification has changed.
http://graylog2.org/gelf#specs

These fields are now deprecated: facility, line, file

Also, there seems to be a error when elasticsearch tries to index fields, that do not conform the the spec. For example, if "line" has the string value "null", the message will be dropped.

Update PhpUnit version (dependency + tests)

Tests for this library rely on PhpUnit 4.x (via composer.json) at max 5.x (usage of getMock()). It'd make sense in the long run (e.g. 2.x) to update + refactor to a newer supported PhpUnit version (>= 7) as a dependency.

Get messages

Can this library GET/search messages from Graylog or do we need to go directly to elasticsearch?

Wish: GelfPublisher should have an option to ignore transport errors

I am using the GelfPublisher with UdpTransport in a website combination with Monolog to log to an logstash/elasticsearch server (ELK) and it is working great!

There is only one thing missing:
If a target server is not available the logging attempt terminates with a PHP error.
In this case I would prefer to have my website do its function as before, even if Gelf logging is not available.
This could be configured using an "ignore_error" option.

To avoid the need to do it in every transport it could be done in Publisher::publish if the foreach-loop is changed like this:

foreach ($this->transports as $transport) {
/* @var $transport TransportInterface */

    try {
        $transport->send($message);
    } catch (ExceptionInterface $e) {
        if (!$this->options['ignore_error']) {
            throw new \RuntimeException("Error sending messages to transport", 0, $e);
        }
    }
}

Or, if it is preferred to enable this per transport it could go in AbstractTransport

Failed to write to socket: fwrite()

I use this package to send logs via monolog logger to Graylog2 server via UDP. I also use tunelling from my machine to this server, cause I cannot reach it directly. I've configured it with socat based on this example:

http://zarb.org/~gc/html/udp-in-ssh-tunneling.html

Basically, everything works as a charm when the tunel is created.
Although when the tunel is not there, then fwrite raises exception (what's more interesning: every 2nd time):

Exception raised 'Failed to write to socket: fwrite(): send of 361 bytes failed with errno=111 Connection refused (8) File: /var/www/paymentdating/vendor/graylog2/gelf-php/src/Gelf/Transport/StreamSocketClient.php, line# 225 (code 0)

so if my code looks like this:

$myLogger->alert('karamba'); $myLogger->alert('karamba'); $myLogger->alert('karamba'); $myLogger->alert('karamba');

The error is raised only for 2nd and 4th call.
I thought that because of UDP protocol there will be no exceptions. In the end I like them even, cause I can check the Graylog server is unreachable, although in most cases the script is gonna log only once and then unfortunately no exception is raised by fwrite.

Make buildSocket exceptions catchable from the initialization of the StreamSocketClient

Hello everyone, and thank you for your great tool :)

Here is the use case we are dealing with right now:

We have our php-application which uses monolog for logging, and the Gelf\Publisher as publisher for GelfHandler.

It is initialized like this, and it works fine:

$logger->pushHandler(new GelfHandler(new Gelf\Publisher(new Gelf\HttpTransport('graylogserver',12201)),Logger::INFO));

The problem is that http communications are not reliable. The server might be down or someone can change the settings or whatever, causing an exception to be thrown, crashing the application because of logging. I noticed that the socket gets created the moment we try to send our first log, but that feels a little too late.

May I suggest some possible solutions:

  1. Create the socket the moment we initialize the HttpTransport, making the exception catchable the moment we initialize our handler. That way we won't have to try/catch on every $logger->log() call and still have a way to know of things going wrong
  2. Add a $HttpTransport->socketExists() that just tries to open the socket
  3. Simply set an option that disables the exception throwing for this specific case

If you agree I can make a pull request for this :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.