BB1
BB1

Reputation: 304

Fabric log format to display date and time

I have set Fabric up to log all SSH/Paramiko-related output with a level of INFO or higher using:

logging.basicConfig()
logging.getLogger('ssh.transport').setLevel(logging.INFO)

This results in a log looking like this:

[host1] Executing task 'task1'
[host1] Run: ls
...

Is it possible to change the formatter for the ssh.transport logger so that each line also has the date and time printed next to it?

Upvotes: 6

Views: 2004

Answers (3)

Ben
Ben

Reputation: 1670

I, too, have been unable to find a way to do this aside from replacing _flush(). I generally find it's a risky practice to replace a private method in any class, let alone a third party. Here's a solution that decorates the Fabric _flush() method and also uses the native Python time.asctime method to format the timestamp.

def time_decorator(msg):
    """
    Decorates `msg` with current timestamp
    Args:
        msg(str): The log message from fabric
    Returns: 
        str: Original message prepended with current date time
    """
    if "\n" not in msg and msg.strip():
        return "[%s] %s" % (time.asctime(), msg)

    return msg


# Compose original method inside of decorator
_original_flush = OutputLooper._flush
OutputLooper._flush = lambda self, msg: {
    _original_flush(self, time_decorator(msg))
}


@task
def uptime():
    run('uptime')

Testing it out, your output should resemble something like:

> fab uptime -H 10.0.1.3,10.0.1.2
[10.0.1.3] Executing task 'uptime'
[10.0.1.3] run: uptime
[Thu Dec 15 19:34:35 2016] [10.0.1.3] out:  19:34:35 up 69 days,  4:22,  1 user,  load average: 0.05, 0.03, 0.05
[Thu Dec 15 19:34:35 2016] [10.0.1.3] out:

[10.0.1.2] Executing task 'uptime'
[10.0.1.2] run: uptime
[Thu Dec 15 19:34:35 2016] [10.0.1.2] out:  19:34:35 up 70 days,  1:12,  1 user,  load average: 0.00, 0.01, 0.05
[Thu Dec 15 19:34:35 2016] [10.0.1.2] out:


Done.
Disconnecting from [email protected]... done.
Disconnecting from [email protected]... done.

Upvotes: 0

ArtOfWarfare
ArtOfWarfare

Reputation: 21496

As alecxe said, the format is hardcoded in Fabric 1.x (as of when I'm posting this, the only version available.) There was a rejected pull request that could have remedied this.

So instead we need a work around. This is a rather hacky solution that I wrote, but it relies on undocumented portions of Fabric, which means it may break in future versions.

from fabric.io import OutputLooper
from datetime  import datetime

def newFlush(self, text):
    stamp = datetime.now().strftime("%a %b %d %H:%M:%S - ")
    print(stamp + text)

OutputLooper._flush = newFlush

From this point forward, any output from your remote machine will have timestamps.

For example, without this code the output from sudo('echo "test"') would be:

[InteractSL-DT1.usma.ibm.com] sudo: echo "test"
[InteractSL-DT1.usma.ibm.com] out: test
[InteractSL-DT1.usma.ibm.com] out:

'test'

But after adding that, you'll now get this:

[InteractSL-DT1.usma.ibm.com] sudo: echo "test"
Fri Jan 02 12:54:49 - [InteractSL-DT1.usma.ibm.com] out:
Fri Jan 02 12:54:49 - test

Fri Jan 02 12:54:49 - [InteractSL-DT1.usma.ibm.com] out:
Fri Jan 02 12:54:49 -

'test'

You can play around with this basic idea to clean it up. The sudo line at the start of the output comes from fabric.operations._run_command, around line 900. I'm not sure of any simple way you could modify it.

Upvotes: 6

alecxe
alecxe

Reputation: 474071

It's not possible now. The format is hardcoded: see source.

FYI, there is a proposal that is asking for exactly what you are.


You can set logging format with an asctime inside, but it won't affect fabric output, only paramiko ones:

import logging
FORMAT = "%(asctime)s %(name)s %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)

example output:

[host] Executing task 'restart'
[host] sudo: ls
2013-09-23 02:36:54,800 paramiko.transport Connected (version 2.0, client OpenSSH_5.3)
2013-09-23 02:36:55,728 paramiko.transport Authentication (password) successful!
2013-09-23 02:36:55,889 paramiko.transport Secsh channel 1 opened.
...

Hope that helps.

Upvotes: 4

Related Questions