Does it strictly need a WSGI middleware?
What I have done isn't strictly a WSGI middleware as it just passes things
through and doesn't need to wrap access to wsgi.input nor do anything with the
response.
It could easily be modified to do that though if needed.
You can find an example of a quite deeming logging middleware at:
http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Tracking_Request_and_Response
Instead of just having:
return wrapped(*args, **kwargs)
you would have something like:
return LoggingMiddleware(wrapped, '/tmp/wsgi')(*args, **kwargs)
Graham
On 05/07/2014, at 8:07 AM, theliuy <[email protected]> wrote:
> Hi Graham,
>
> I tried to implement it as you described. It really helps. Thanks a lot.
>
> What I am trying to do is, I want to listen and log every requests coming to
> my applications. I have already made some scripts to analyze the log and find
> some interesting requests from specific user, and also built a tool to mock
> what he/she did. It is used to reproduce some bugs caused by consequent
> calls. I am looking for a way to implement this procedure into other
> projects. Since log analyzer and mock tool are offline and flexible, one of
> the difficulties is how to log coming requests. Registering it to every flask
> app or wsgis needs lots of work, that's why I am looking for a way to
> implement a "middleware" between apache/wsgi_mod and flask app.
>
> Thanks,
> Yang
>
>
> On Friday, July 4, 2014 5:14:49 AM UTC-7, Graham Dumpleton wrote:
> Okay, seems you can now use WSGIImportScript inside of VirtualHost.
>
> A long long time ago this wasn't the case. Seems I fixed it at some point so
> that it is now possible but the docs weren't updated. I did look at the code
> to try and work it out when I responded but was looking in the wrong place
> for what dictates whether the directive can be used in a VirtualHost.
>
> So you don't need to worry about using WSGIScriptAlias at all. You can always
> use WSGIImportScript, placing it after the WSGIDaemonProcess directive for
> the daemon process group that the WSGIImportScript needs to refer to, even
> inside of the VirtualHost.
>
> Graham
>
> On 04/07/2014, at 9:25 PM, Graham Dumpleton <[email protected]> wrote:
>
>>
>> On 04/07/2014, at 7:58 PM, Graham Dumpleton <[email protected]> wrote:
>>> On 04/07/2014, at 5:52 PM, theliuy <[email protected]> wrote:
>>>> I have several web services using Apache + mod_wsgi + Flask. For some
>>>> debug purpose, I want to listen the incoming requests and log them. I
>>>> don't want to modify flask applications, or wsgi scripts neither. Because
>>>> there are too many existing projects, I can't do it one by one. And they
>>>> are going to be deployed in multiple environment, I just need this feature
>>>> in one or two of them.
>>>>
>>>> One possible solution come to my mind is to modify Flask framework.
>>>> Implement a "logger" inside flask. I think it will be better if I can find
>>>> a way to register a script in mod_wsgi. Let mod_wsgi run it whenever
>>>> requests are coming.
>>>>
>>>> I don't know if there is any better way to make it. Please give me some
>>>> hint.
>>>
>>> What about the request are you wanting to log exactly and for what purpose?
>>>
>>> I can explain a way of doing what you want which avoids you needing to
>>> change either the code of your application, Flask or any other package, but
>>> the context of what you are trying to capture and why will help as I will
>>> then know what sort of WSGI middleware I will need to employ to capture
>>> what you need.
>>>
>>> So if you can respond with that extra information and in the mean time I
>>> will validate that my idea for how to do it will work.
>>
>> I would still like to know what you are trying to capture, but if you really
>> want to avoid making changes to any existing code or third party modules,
>> you can do the following. The technique uses monkey patching, employing the
>> `wrapt` library to simplify the process and ensure how the monkey patching
>> is done is correct.
>>
>> First up, you need to have the `wrapt` module installed.
>>
>> pip install wrapt
>>
>> Next, create a file called 'patch.py' which contains:
>>
>> from __future__ import print_function
>>
>> from wrapt import when_imported, wrap_function_wrapper
>>
>> def flask_wsgi_app_wrapper(wrapped, instance, args, kwargs):
>> def bind_call_args(environ, *args, **kwargs):
>> return environ
>>
>> environ = bind_call_args(*args, **kwargs)
>>
>> print(10*'>')
>> for key in sorted(environ.keys()):
>> print('%s: %s' % (key, repr(environ[key])))
>> print(10*'<')
>>
>> return wrapped(*args, **kwargs)
>>
>> @when_imported('flask.app')
>> def instrument_flask_app(module):
>> wrap_function_wrapper(module, 'Flask.wsgi_app', flask_wsgi_app_wrapper)
>>
>> What needs to be done now is that this 'patch.py' file has to be imported
>> somehow and it ideally needs to be imported before the actual WSGI
>> application script file is imported. It preferably would just have been
>> imported at the start of the specific WSGI script file for the application
>> you want to add debugging to. But since you don't want to do that, then you
>> will need to modify the Apache configuration file and use mod_wsgi to
>> preload it.
>>
>> What exactly you need to do here may depend on whether you are using
>> mod_wsgi embedded mode or daemon mode. If using daemon mode, it may also
>> depend on whether the WSGIDaemonProcess directives are specified inside of
>> the context of a VirtualHost, or outside at global server scope.
>>
>> The problem here is that the WSGIImportScript can only be defined at global
>> server scope. That is, it cannot be specified inside of a VirtualHost, but
>> has to be outside.
>>
>> Right now I can't remember the rules about whether a WSGIImportScript can
>> refer to a daemon process group specified using WSGIDaemonProcess directive
>> inside of a VirtualHost.
>>
>> If it can, then the WSGIImportScript directive will at least have to be
>> added after the VirtualHost containing the WSGIDaemonProcess.
>>
>> Anyway, if you are using embedded mode at least, then you need to use the
>> WSGIImportScript directive as:
>>
>> WSGIImportScript /some/path/patch.py process-group=%{GLOBAL}
>> application-group=%{GLOBAL}
>>
>> The application-group option should be set to the specific application group
>> context that the WSGI application you want to debug, is running in.
>>
>> What will happen is that when the Apache child worker processes are started
>> up and Python gets initialised, mod_wsgi will preload the patch.py file into
>> the Python interpreter.
>>
>> In being imported, the @with_imported decorator will register that the
>> instrument_flask_app() function should be called when the 'flask.app' module
>> is imported by the WSGI application.
>>
>> When the module is the flask.app module is import, the
>> instrument_flask_app() function is executed at that point, it will be passed
>> the flask.app module before the import even returns the module to the code
>> that imported it. The Flask.wsgi_app() method will then have a function
>> wrapper applied using wrap_function_wrapper().
>>
>> Later when handling a WSGI request, the Flask.wsgi_app() will be called. At
>> that point the flask_wsgi_app_wrapper() wrapper will actually be called.
>> Inside of that we bind the function arguments to extract the 'environ'
>> argument passed to the WSGI application entry point for Flask. The wrapper
>> function can then print out what it wants from 'environ'. Finally, the
>> wrapper will call the original wrapped Flask.wsgi_app() method so the WSGI
>> application can handle the request.
>>
>> So that is the principle of how it works, but that Apache configuration only
>> works with embedded mode for sure. If using daemon mode we may not be able
>> to use WSGIImportScript however and may have to use another trick.
>>
>> For daemon mode therefore, if the WSGIDaemonProcess directive is actually
>> specified outside of any VirtualHost, then we can still use
>> WSGIImportScript. Thus you would use:
>>
>> WSGIImportScript /some/path/patch.py process-group=group
>> application-group=%{GLOBAL}
>>
>> The process-group option would be set to the daemon process group name, and
>> application-group option again set to the specific application group context
>> that the WSGI application you want to debug, is running in.
>>
>> The WSGIImportScript in this case should come after the WSGIDaemonProcess
>> directive it is referring to.
>>
>> Now if the WSGIDaemonProcess group directive is inside of the VirtualHost, I
>> am not sure if one can do:
>>
>> <VirtualHost *:80>
>> ...
>> WSGIDaemonProcess group
>> ...
>> </VirtualHost>
>>
>> WSGIImportScript /some/path/patch.py process-group=group
>> application-group=%{GLOBAL}
>>
>> If that doesn't work, we have to cheat a bit and do:
>>
>> <VirtualHost *:80>
>> ...
>> WSGIDaemonProcess group
>> WSGIScriptAlias /.patch /some/path/patch.py process-group=group
>> application-group=%{GLOBAL}
>> <Location /.patch>
>> Deny from all
>> </Location>
>> ...
>> </VirtualHost>
>>
>> In other words, we actually use WSGIScriptAlias and the fact that if both
>> process-group and application-group are specified, that the WSGI script file
>> would normally be preloaded.
>>
>> Since we have to specify a URL as the mount point and there will be no
>> actual WSGI application in the script file, then we use a Location block to
>> block access to the URL to force a forbidden HTTP response if someone tries
>> to access that URL.
>>
>> That therefore represents a technical solution for what I believe you want.
>> The question now is if you really need to do what you think you do.
>>
>> Note that if you are really after a monitoring solution for evaluating
>> application performance, then there are better ways of doing what you want.
>>
>> If you do try it and have the case of using WSGIDaemonProcess inside of a
>> VirtualHost, do tell me if WSGIImportScript outside of the VirtualHost can
>> still refer to it. I will try and test it myself, but it isn't convenient to
>> do so right now.
>>
>> Graham
>>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "modwsgi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/modwsgi.
> For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.