Git Product home page Git Product logo

log4mongo-python's Introduction

log4mongo-python

log4mongo-python is mongo database handler for python logging, part of log4mongo.org project. log4mongo-python is using pymongo driver - http://github.com/mongodb/mongo-python-driver

Requirements

  • python 3.6.2+
  • pymongo 4.0+
  • mongo database

For more information see debian_requirements.txt and requirements.txt files.

Configuration

Example handler python configuration:

import logging
from log4mongo.handlers import MongoHandler

logger = logging.getLogger('test')
logger.addHandler(MongoHandler(host='localhost'))
logger.warning('test')

Contextual information

It is possible to decorate you document with contextual information. There are tow approaches.

1.) approach

import logging
from log4mongo.handlers import MongoHandler

handler = MongoHandler(host='localhost')
logger = logging.getLogger('test')
logger.addHandler(handler)
logging.LoggerAdapter(logger, {'ip': '127.0.0.1'}).info('test')

2.) approach

import logging
from log4mongo.handlers import MongoHandler

handler = MongoHandler(host='localhost')
logger = logging.getLogger('test')
logger.addHandler(handler)
logger.info('test', extra={'ip': '127.0.0.1'})

As you can see, second approach is more straightforward and there is no need to use LoggerAdapter.

Capped collections

Capped collections are fixed-size collections that support high-throughput operations that insert, retrieve, and delete documents based on insertion order. Capped collections work in a way similar to circular buffers: once a collection fills its allocated space, it makes room for new documents by overwriting the oldest documents in the collection.

Before switching to capped collections, read this document please: http://docs.mongodb.org/manual/core/capped-collections/

This behaviour is disabled by default. You can enable this behaviour in constructor with capped=True:

import logging
from log4mongo.handlers import MongoHandler

handler = MongoHandler(host='localhost', capped=True)

Buffered handler

BufferedMongoHandler is a subclass of MongoHandler allowing to buffer log messages and write them all at once to the database. The goal is to avoid too many writes to the database, thus avoiding too frequent write-locks. Log message buffer flush happens when the buffer is full, when a critical log message is emitted, and also periodically. An early buffer flush can happen when a critical message is emitted. And in order to avoid messages to stay indefinitively in the buffer queue before appearing in database, a periodical flush happens every X seconds.

This periodical flush can also be deactivated with buffer_periodical_flush_timing=False, thus avoiding the timer thread to be created.

Buffer size is configurable, as well as the log level for early flush (default is logging.CRITICAL):

import logging
from log4mongo.handlers import BufferedMongoHandler

handler = BufferedMongoHandler(host='localhost',                          # All MongoHandler parameters are valid
                               capped=True,
                               buffer_size=100,                           # buffer size.
                               buffer_periodical_flush_timing=10.0,       # periodical flush every 10 seconds
                               buffer_early_flush_level=logging.CRITICAL) # early flush level

logger = logging.getLogger().addHandler(handler)

Test

** Tested on evnironment **

  • Ubuntu 18.04
  • python >=3.6.4
  • pymongo >=3.9.0
  • mongod - db version 4.0.13
  • pytest

Running tests

Before you run the test you must start mongo database. You will do so by this command:

$ mongod --dbpath /tmp/

To run the test run command:

$ python3 setup.py test

See vagrant file to quickly setup the test environment.

Original Author

Current Maintainer

Oz Nahum Tiram
web: oz123.github.io

References

log4mongo-python's People

Contributors

char0n avatar chatterbox-machine avatar coca099 avatar drcolossos avatar drorasaf avatar gsmafra avatar jsk avatar mjbommar avatar oz123 avatar ronhanson avatar sadikkuzu avatar starenka avatar tiendan avatar twmr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

log4mongo-python's Issues

PyPi version does not reflect code

I have encountered an authentication error and I was unable to resolve it. I checked the main repository and found out that the version 1.7.0 on Pypi does not match the master branch.

I think it would be better to update the version number and Pypi accordingly.

BufferedMongoHandler (with periodic flushing enabled) can't be initialized outside of main-thread

If the BufferedMonogHandler is initialized in a thread that is not alive for the whole runtime of the script, the periodic flushing stops working once the initializer thread is not alive anymore.
This is due to the main_thread code in https://github.com/log4mongo/log4mongo-python/blob/master/log4mongo/handlers.py#L251

As a workaround we've removed the main_thread.is_alive() code. Do you have a better solution?

Authentication issue

MongoDB uses the admin database as the default user manager, log4mongo does not support this option.

Another question, why does the connection is not being created with the MongoClient API?

Error when installing log4mongo when LANG is not en_US.UTF-8

How to reproduce:

export LANG=""
pip install log4mongo

Error Log:
Collecting log4mongo
  Downloading log4mongo-1.5.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-pys6bi5t/log4mongo/setup.py", line 20, in <module>
        long_description=read('README.rst'),
      File "/tmp/pip-build-pys6bi5t/log4mongo/setup.py", line 13, in read
        return open(os.path.join(os.path.dirname(__file__), fname)).read()
      File "/home/dror/anaconda3/lib/python3.4/encodings/ascii.py", line 26, in decode
        return codecs.ascii_decode(input, self.errors)[0]
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 2557: ordinal not in range(128)

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-pys6bi5t/log4mongo/

Not standard conform document fields

I think it would have been a good idea to use the attributes name as provided by the logging module and to name the fields of the stored MongoDB documents in the same way.

See this table:
http://docs.python.org/2/library/logging.html#logrecord-attributes

Maybe it would be a nice feature to add a parameter to MongoHandler.init which allows to select custom fields which are stored in the DB. E.g. levelno is a very important property because it allows easy filtering with a DB-query (levelname does not because it is a string).

how to log to file and as well to mongodb

I have a situation to log to file and same time to write to mongodb log with different logging.basicConfig level of Info and Error.
Any idea how can achieve this? If I set basic config to Error I can't log as Info to file.

Use of deprecated pymongo-3 call save()

With pymongo > 3 one get:

log4mongo.py:184: DeprecationWarning: save is deprecated. Use insert_one or replace_one instead
self.collection.save(self.format(record))

logger.info

handler = MongoHandler(host='localhost')
logger = logging.getLogger('test')
logger.info("test", extra={'ip': '127.0.0.1'}) <--- not working.....
logger.warning("test")
image

Why just .info not working ???

Connection error with Mongo Atlas

Hi,
I have a database in Mongo Atlas but cannot connect.

My connection code:

mongo = MongoHandler(host='46.222.73.115', 
                     username='testeko', 
                     password='aSd1234', 
                     database_name='TestDB')
logger.addHandler(mongo)

The original connection string
"mongodb+srv://testeko:[email protected]/TestDB?retryWrites=true&w=majority"

It gives this error when trying to connect.
pymongo.errors.ServerSelectionTimeoutError: connection closed

Python : 3.7.4,
log4mongo : 1.7.0,
pymongo : 3.9.0

What should I do?

Thank you.

Batch insert

Hi,
To avoid write-locking the mongo DB with constant log writes, I'd like to implement some kind of "batch insert". Something like buffering the logs and writing them every 10 lines or so. And maybe periodically emptying the buffer too.
Has this already been voiced or tried by anyone?
Just checking if the idea is valid or if I'm being stupid.
Cheers,
Ronan

Support MongoDB URI format

If the host is in MongoDB URI format, e.g. 'mongodb://localhost:27017/', the port and username and password should override the defaults. MongoClient supports these URIs.

Couldn't find index page for 'pytest-runner' (maybe misspelled?)

I'm making a project which includes log4mongo, and received this error. Was curious to see if you can replicate on your end.

  Downloading log4mongo-1.6.1.tar.gz
    Complete output from command python setup.py egg_info:
    Download error on https://pypi.python.org/simple/pytest-runner/: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661) -- Some packages may not be found!
    Couldn't find index page for 'pytest-runner' (maybe misspelled?)
    Download error on https://pypi.python.org/simple/: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661) -- Some packages may not be found!
    No local packages or working download links found for pytest-runner
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-vBZFq0/log4mongo/setup.py", line 46, in <module>
        'Topic :: System :: Monitoring'
      File "/usr/lib/python2.7/distutils/core.py", line 111, in setup
        _setup_distribution = dist = klass(attrs)
      File "/usr/lib/python2.7/site-packages/setuptools/dist.py", line 315, in __init__
        self.fetch_build_eggs(attrs['setup_requires'])
      File "/usr/lib/python2.7/site-packages/setuptools/dist.py", line 361, in fetch_build_eggs
        replace_conflicting=True,
      File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 850, in resolve
        dist = best[req.key] = env.best_match(req, ws, installer)
      File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1122, in best_match
        return self.obtain(req, installer)
      File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 1134, in obtain
        return installer(requirement)
      File "/usr/lib/python2.7/site-packages/setuptools/dist.py", line 429, in fetch_build_egg
        return cmd.easy_install(req)
      File "/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 659, in easy_install
        raise DistutilsError(msg)
    distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('pytest-runner')

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-vBZFq0/log4mongo/
You are using pip version 9.0.0, however version 9.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
The command '/bin/sh -c pip install --compile -r requirements.txt' returned a non-zero code: 1
make: *** [dev] Error 1```

_connect error about authentication

I got an error like this:

/Users/lamter/anaconda/envs/public/lib/python3.5/site-packages/log4mongo/handlers.py in _connect(self, **kwargs)
    143                                              **kwargs)
    144                 try:
 --> 145                     self.connection.is_locked
    146                 except ServerSelectionTimeoutError:
    147                     if self.fail_silently:
...

OperationFailure: not authorized on admin to execute command { currentOp: 1, $all: false }

MongoClient.is_locked need auth of 'admin'. That will be correct without non-auth situation and with auth of database 'admin'. But when I pass 'username' and 'password' for database 'logs', it raised above error.

I deal with a non-recommendable way like this:

import pymongo
import log4mongo.handlers
import logging


log4mongo.handlers._connection = pymongo.MongoClient(
    host='localhost',
    port=30020,
)

mh = log4mongo.handlers.MongoHandler(
    host='localhost',
    port=30020,
    username='slavel',
    password='slavel',
    database_name='log',
    collection='testlog',
    authentication_db='log',
)

logger = logging.getLogger()
logger.addHandler(mh)

logger.warning('qwe')

how to log connection error

I am unable to log into a log file for any connection error, while it prints to stdout

--- Logging error ---
Traceback (most recent call last):
lib/python3.11/site-packages/log4mongo/handlers.py", line 295, in flush_to_mongo
getattr(self.collection, write_many_method)(self.buffer)

Please let me know if anyone has already solved this.

version 1.6.2 tag?

The version has been bumped to 1.6.2 in setup.py last year but the repo has not been tagged with 1.6.2. Therefore github lists 1.6.1 as the latest release, but the latest release on pypi is 1.6.2.

Debian packages

Hey Oz,
I can see that there is no log4mongo debian package available on public repos, neither in python 2 nor in 3.
From what I saw on your nice personal website, you seem to be a debian fan, so I'm being curious: have you ever worked on that part? Is this something we should consider?
I have some, not much, but still some experience in building packages for debian/ubuntu, so I might be able to help. Still I can build some .deb packages easily, I will definitively for myself, but I have no standard workflow for creating it.
Tell me what you think about that.
Cheers,
Ronan

Admin access for OZ

@oz123 it seems I cannot grant you admin privileges because I don't have them either. I've requested admin access for me and if I get it I will grant you also admin privileges.

General question

Hi. I have some experience in MongoDB

Since Atlas provides some free cluster,
I am looking for some correct way that logs to the database.
However, does MongoDB suitable for storing logs from python?
Also due to the write lock contention,
how could I solve this issue when using your library?

Thanks! I love python. I love logging. I love mongodb.

Utterly broken with pymongo 3.0

Hi,
The newly released pymongo driver is breaking a lot of things. I would like to know if you intended to maintain the log4mongo driver further since it seems quite abandoned.

I would like to fix things and upload a new version to pypi.

Thanks, in advance.
Oz

Can't get it work

When using pymongo 2.6.3 according to the requirements.txt, I receive this error:
Unable to connect to the database. command SON([('authenticate', 1), ('user', u'ads'), ('nonce', u'8607e5da456556b5'), ('key', u'd13b8199999884353743a93e7d739')]) failed: auth failed

But as soon as I upgrade to 3.0.3. the error disappears, but below code returns a None:

MONGOLAB_URI_PARSED = urlparse('mongodb://ads:[email protected]:41484/heroku_b985544')
    MONGOLAB_CONF_DICT = dict(
        host = MONGOLAB_URI_PARSED.hostname,
        port = MONGOLAB_URI_PARSED.port,
        database_name = MONGOLAB_URI_PARSED.path[1:],
        username = MONGOLAB_URI_PARSED.username,
        password = MONGOLAB_URI_PARSED.password
    )

    logger = logging.getLogger(name)

    logger.addHandler(MongoHandler(level=logging.DEBUG, collection='logs', **MONGOLAB_CONF_DICT))
    print logger.warning('test')

Can you help?

OperationFailure when trying to connect to an authenticated database

I am trying to connect to an authenticated MongoDB instance where I don't have access to the admin database. I don't know if I'm misusing the package or this is a bug related to my specific configurations.

This is the most simple code to reproduce this behavior:

import logging
import log4mongo.handlers


logger = logging.getLogger('test')

handler = log4mongo.handlers.MongoHandler(
    host='host',
    port=27017,
    username='username',
    password='password',
    database_name='database_name',
    authentication_db='database_name',
)

logger.warning('test')

And this is the error:

/usr/local/lib/python3.6/dist-packages/log4mongo/handlers.py in __init__(self, level, host, port, database_name, collection, username, password, authentication_db, fail_silently, formatter, capped, capped_max, capped_size, reuse, **kwargs)
    121         self.capped_size = capped_size
    122         self.reuse = reuse
--> 123         self._connect(**kwargs)
    124 
    125     def _connect(self, **kwargs):

/usr/local/lib/python3.6/dist-packages/log4mongo/handlers.py in _connect(self, **kwargs)
    143                                              **kwargs)
    144                 try:
--> 145                     self.connection.is_locked
    146                 except ServerSelectionTimeoutError:
    147                     if self.fail_silently:

(...)

OperationFailure: not authorized on admin to execute command { currentOp: 1, $all: false }

I'm omitting the PyMongo stack trace for clarity. Any help would be appreciated.

Remove support for pymongo2

The first version of pymongo3 was released on Apr 2015. Would you agree on removing support for pymongo2 (the last version was released on Jun 2017) in 2020?

Inserting into a particular document

Hi

I was wondering about the idea of inserting the log messages into a particular document in a given collection.

In terms of design I see a downfall, it requires explicitly the document id. For instance via dependency injection, but I'm failing to see to do this in a transparent way (disable / enable handler under demand, without modifying the rest of the logging calls)

Kind regards

Cannot use MongoClient after close

raise InvalidOperation("Cannot use MongoClient after close")

pymongo.errors.InvalidOperation: Cannot use MongoClient after close

I am getting this error while logging from a FastAPI python client with async operation.

timestamp is of type BSON Timestamp, instead it should be of type BSON Date

Setting up a TTL on log4mongo-python logs does not work on type Timestamp (which is what is logged by default in log4mongo-python). 10gen recommends Timestamp type is not used externally. Type Date is used for TTL:

https://docs.mongodb.com/manual/reference/bson-types/

Note

The BSON timestamp type is for internal MongoDB use. For most cases, in application development, you will want to use the BSON date type. See Date for more information.

https://docs.mongodb.com/manual/tutorial/expire-data/

BufferedMongoHandler calls threading.Thread with deamon=True raises TypeError

Unfortunately, calling threading.Thread with deamon=True (L254 of log4mongo/handlers.py) does not work in python 2.7.14. Initializing a BufferedMongoHandler instance raises the following error:
TypeError: __init__() got an unexpected keyword argument 'daemon'

From what I understood, adding deamon=True is only required in Python >3.3. Everything seems to run fine when removing deamon=True from the call.

Is it maybe possible to do a quick-fix and test for python version to see whether or not deamon=True should be added to the call of threading.Thread?

(I can fix it myself for local use, but it's really useful to be able to install log4mongo on a remote server using pip)

Releases

Hi,

I have created the following tags:
1.4.1 oz123@157e21d
1.4.0 oz123@30cc55e

Please add these tags here too, so users can download the package from here as well as from pypi.

Thank you.

Pymongo has removed authenticate method in Database class but log4mongo is still using it which cause exception.

I just install latest version of log4mongo which automatically installed pymongo as dependency. I got below error when instantiating MongoHandler :

TypeError: 'Collection' object is not callable. If you meant to call the 'authenticate' method on a 'Database' object it is failing because no such method exists.

Here is my code :

db_handler = MongoHandler(host=mongo_connection_params['host'], port=mongo_connection_params['port'], username=mongo_connection_params['username'], password=mongo_connection_params["password"], database_name=mongo_connection_params['db'], collection='logs')

It happens here actually :

if self.username is not None and self.password is not None: auth_db = self.connection[self.authentication_database_name] self.authenticated = auth_db.authenticate(self.username, self.password)

Looks like authenticate method has been removed in the later version of pymongo but log4mongo is still using it.
This link also might help : https://debugah.com/solved-typeerror-collection-object-is-not-callable-if-you-meant-to-call-the-authenticate-method-on-a-database-object-it-is-failing-because-no-such-method-exists-23011/

support pymongo connecting in background

hi,

in pymongo https://github.com/mongodb/mongo-python-driver/blob/master/pymongo/mongo_client.py:
"```python

Starting with version 3.0 the MongoClient constructor no longer blocks while connecting

to the server or servers, and it no longer raises ConnectionFailure if they are unavailable.

Instead, the constructor returns immediately and launches the connection process on background

threads.


so log4mongo handler could continue initialize when mongodb not running. I made a patch for this:
> import threading
4,8c15
< try:
<     from pymongo import MongoClient as Connection
< except ImportError:
<     from pymongo import Connection
< 
---
> from pymongo import MongoClient
10,18c17,19
< from pymongo.errors import OperationFailure, PyMongoError
< import pymongo
< if pymongo.version_tuple[0] >= 3:
<     from pymongo.errors import ServerSelectionTimeoutError
<     write_method = 'insert_one'
<     write_many_method = 'insert_many'
< else:
<     write_method = 'save'
<     write_many_method = 'insert'
---
> from pymongo.errors import ConfigurationError, OperationFailure, ServerSelectionTimeoutError
> 
> # pylint: disable=pointless-string-statement,invalid-name
46a48
> # pylint: disable=too-many-instance-attributes,too-many-arguments,too-many-locals
49,50c51
<     DEFAULT_PROPERTIES = logging.LogRecord(
<         '', '', '', '', '', '', '', '').__dict__.keys()
---
>     DEFAULT_PROPERTIES = logging.LogRecord("", "", "", "", "", "", "", "").__dict__.keys()  # type: ignore
56,65c57,66
<             'timestamp': dt.datetime.utcnow(),
<             'level': record.levelname,
<             'thread': record.thread,
<             'threadName': record.threadName,
<             'message': record.getMessage(),
<             'loggerName': record.name,
<             'fileName': record.pathname,
<             'module': record.module,
<             'method': record.funcName,
<             'lineNumber': record.lineno
---
>             "timestamp": dt.datetime.utcnow(),
>             "level": record.levelname,
>             "thread": record.thread,
>             "threadName": record.threadName,
>             "message": record.getMessage(),
>             "loggerName": record.name,
>             "fileName": record.pathname,
>             "module": record.module,
>             "method": record.funcName,
>             "lineNumber": record.lineno,
69,75c70,72
<             document.update({
<                 'exception': {
<                     'message': str(record.exc_info[1]),
<                     'code': 0,
<                     'stackTrace': self.formatException(record.exc_info)
<                 }
<             })
---
>             document.update(
>                 {"exception": {"message": str(record.exc_info[1]), "code": 0, "stackTrace": self.formatException(record.exc_info)}}
>             )
78,79c75
<             contextual_extra = set(record.__dict__).difference(
<                 set(self.DEFAULT_PROPERTIES))
---
>             contextual_extra = set(record.__dict__).difference(set(self.DEFAULT_PROPERTIES))
87,92c83,101
< 
<     def __init__(self, level=logging.NOTSET, host='localhost', port=27017,
<                  database_name='logs', collection='logs',
<                  username=None, password=None, authentication_db='admin',
<                  fail_silently=False, formatter=None, capped=False,
<                  capped_max=1000, capped_size=1000000, reuse=True, **kwargs):
---
>     def __init__(
>         self,
>         level=logging.NOTSET,
>         host="localhost",
>         port=27017,
>         database_name="logs",
>         collection="logs",
>         username=None,
>         password=None,
>         authentication_db="admin",
>         fail_silently=False,
>         formatter=None,
>         capped=False,
>         capped_max=1000,
>         capped_size=1000000,
>         reuse=True,
>         ttl=3600,
>         **kwargs,
>     ):
122a132,133
>         self.ttl = ttl
>         self.ttl_index = ""
127c138
<         global _connection
---
>         global _connection  # pylint: disable=global-statement
131,150c142,148
<             if pymongo.version_tuple[0] < 3:
<                 try:
<                     self.connection = Connection(host=self.host,
<                                                  port=self.port, **kwargs)
<                 # pymongo >= 3.0 does not raise this error
<                 except PyMongoError:
<                     if self.fail_silently:
<                         return
<                     else:
<                         raise
<             else:
<                 self.connection = Connection(host=self.host, port=self.port,
<                                              **kwargs)
<                 try:
<                     self.connection.is_primary
<                 except ServerSelectionTimeoutError:
<                     if self.fail_silently:
<                         return
<                     else:
<                         raise
---
>             self.connection = MongoClient(host=self.host, port=self.port, **kwargs)
>             try:
>                 self.connection.is_primary
>             except ServerSelectionTimeoutError:
>                 if self.fail_silently:
>                     return
>                 raise
151a150
>         self._setup()
153c152,153
<         self.db = self.connection[self.database_name]
---
>     def _setup(self):
>         self.db = self.connection[self.database_name]  # type: ignore
155,157c155,156
<             auth_db = self.connection[self.authentication_database_name]
<             self.authenticated = auth_db.authenticate(self.username,
<                                                       self.password)
---
>             auth_db = self.connection[self.authentication_database_name]  # type: ignore
>             self.authenticated = auth_db.authenticate(self.username, self.password)
164,166c163
<                 self.collection = Collection(self.db, self.collection_name,
<                                              capped=True, max=self.capped_max,
<                                              size=self.capped_size)
---
>                 self.collection = Collection(self.db, self.collection_name, capped=True, max=self.capped_max, size=self.capped_size)
172a170,178
>     def _ensure_log4mongo_index(self):
>         if not self.ttl_index and self.ttl > 0:
>             try:
>                 self.ttl_index = self.collection.create_index(  # type: ignore
>                     "timestamp", expireAfterSeconds=self.ttl, background=True
>                 )
>             except (TypeError, ConfigurationError, ServerSelectionTimeoutError):
>                 pass
> 
178c184
<             self.db.logout()
---
>             self.db.logout()  # type: ignore
183a190,197
> 
>         if self.collection is None:
>             try:
>                 self._setup()
>             except ServerSelectionTimeoutError:
>                 pass
>         self._ensure_log4mongo_index()
> 
186,187c200,201
<                 getattr(self.collection, write_method)(self.format(record))
<             except Exception:
---
>                 self.collection.insert_one(self.format(record))
>             except Exception:  # pylint: disable=broad-except
191c205
<     def __exit__(self, type, value, traceback):
---
>     def __exit__(self, type, value, traceback):  # pylint: disable=redefined-builtin
196,203c210,231
< 
<     def __init__(self, level=logging.NOTSET, host='localhost', port=27017,
<                  database_name='logs', collection='logs',
<                  username=None, password=None, authentication_db='admin',
<                  fail_silently=False, formatter=None, capped=False,
<                  capped_max=1000, capped_size=1000000, reuse=True,
<                  buffer_size=100, buffer_periodical_flush_timing=5.0,
<                  buffer_early_flush_level=logging.CRITICAL, **kwargs):
---
>     def __init__(
>         self,
>         level=logging.NOTSET,
>         host="localhost",
>         port=27017,
>         database_name="logs",
>         collection="logs",
>         username=None,
>         password=None,
>         authentication_db="admin",
>         fail_silently=False,
>         formatter=None,
>         capped=False,
>         capped_max=1000,
>         capped_size=1000000,
>         reuse=True,
>         ttl=3600,
>         buffer_size=100,
>         buffer_periodical_flush_timing=5.0,
>         buffer_early_flush_level=logging.CRITICAL,
>         **kwargs,
>     ):
219,222c247,265
<         MongoHandler.__init__(self, level=level, host=host, port=port, database_name=database_name, collection=collection,
<                               username=username, password=password, authentication_db=authentication_db,
<                               fail_silently=fail_silently, formatter=formatter, capped=capped, capped_max=capped_max,
<                               capped_size=capped_size, reuse=reuse, **kwargs)
---
>         MongoHandler.__init__(
>             self,
>             level=level,
>             host=host,
>             port=port,
>             database_name=database_name,
>             collection=collection,
>             username=username,
>             password=password,
>             authentication_db=authentication_db,
>             fail_silently=fail_silently,
>             formatter=formatter,
>             capped=capped,
>             capped_max=capped_max,
>             capped_size=capped_size,
>             reuse=reuse,
>             ttl=ttl,
>             **kwargs,
>         )
227c270
<         self.last_record = None #kept for handling the error on flush
---
>         self.last_record = None  # kept for handling the error on flush
230c273,274
<         self._buffer_lock = None
---
>         self.buffer_lock = threading.RLock()
> 
237,238c281
<             import atexit
<             atexit.register(self.destroy)
---
>             import atexit  # pylint: disable=import-outside-toplevel
240,241c283
<             import threading
<             self._buffer_lock = threading.RLock()
---
>             atexit.register(self.destroy)
258c300,302
<             self._timer_stopper, self.buffer_timer_thread = call_repeatedly(self.buffer_periodical_flush_timing, self.flush_to_mongo)
---
>             self._timer_stopper, self.buffer_timer_thread = call_repeatedly(
>                 self.buffer_periodical_flush_timing, self.flush_to_mongo
>             )
262,263c306,315
< 
<         self.add_to_buffer(record)
---
>         if self.collection is None:
>             try:
>                 MongoHandler._setup(self)
>             except ServerSelectionTimeoutError:
>                 pass
>         MongoHandler._ensure_log4mongo_index(self)
> 
>         with self.buffer_lock:
>             self.last_record = record
>             self.buffer.append(self.format(record))
267,287d318
<         return
< 
<     def buffer_lock_acquire(self):
<         """Acquire lock on buffer (only if periodical flush is set)."""
<         if self._buffer_lock:
<             self._buffer_lock.acquire()
< 
<     def buffer_lock_release(self):
<         """Release lock on buffer (only if periodical flush is set)."""
<         if self._buffer_lock:
<             self._buffer_lock.release()
< 
<     def add_to_buffer(self, record):
<         """Add a formatted record to buffer."""
< 
<         self.buffer_lock_acquire()
< 
<         self.last_record = record
<         self.buffer.append(self.format(record))
< 
<         self.buffer_lock_release()
292,302c323,329
<             self.buffer_lock_acquire()
<             try:
< 
<                 getattr(self.collection, write_many_method)(self.buffer)
<                 self.empty_buffer()
< 
<             except Exception as e:
<                 if not self.fail_silently:
<                     self.handleError(self.last_record) #handling the error on flush
<             finally:
<                 self.buffer_lock_release()
---
>             with self.buffer_lock:
>                 try:
>                     self.collection.insert_many(self.buffer)
>                     self.empty_buffer()
>                 except Exception:  # pylint: disable=broad-except
>                     if not self.fail_silently:
>                         self.handleError(self.last_record)  # type: ignore
315,316d341
< 
< 

Not authorized on admin [ Mongo version : 3.4.4 ]

Issue :

File "/usr/local/lib/python2.7/dist-packages/log4mongo/handlers.py", line 123, in __init__
    self._connect(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/log4mongo/handlers.py", line 145, in _connect
    self.connection.is_locked
  File "/home/sreenadh/.local/lib/python2.7/site-packages/pymongo/mongo_client.py", line 1186, in is_locked
    ops = self._database_default_options('admin').current_op()
  File "/home/sreenadh/.local/lib/python2.7/site-packages/pymongo/database.py", line 620, in current_op
    return sock_info.command("admin", cmd)
  File "/home/sreenadh/.local/lib/python2.7/site-packages/pymongo/pool.py", line 239, in command
    read_concern)
  File "/home/sreenadh/.local/lib/python2.7/site-packages/pymongo/network.py", line 102, in command
    helpers._check_command_response(response_doc, None, allowable_errors)
  File "/home/sreenadh/.local/lib/python2.7/site-packages/pymongo/helpers.py", line 205, in _check_command_response
    raise OperationFailure(msg % errmsg, code, response)
OperationFailure: not authorized on admin to execute command { currentOp: 1, $all: false }

What am trying to do with log4mongo :

I am writing a scrapy spider in which I need the log to be sent to MongoDB. My other mongo connections using MongoClient auth uri works fine. (ie.: client=MongoClient('mongodb://username:password@localhost:27045') ) with auth db as admin that has roles granted accordingly.

I followed the README, but I can't get the Auth part to work, when the MongoDB is with auth disabled, the connection works.

handler = MongoHandler(
level=logging.DEBUG,
host='localhost',
port=27045,
database_name='SPIDER_LOGS',
collection='logs',
username='username_here',
password='password_here',
authentication_db='admin'
)

Versions used:

python : 2.7
mongodb : 3.4.4
pymongo : 3.4.0

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.