Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce explicit command logging methods and deprecate stdout / stderr Command attrs #257

Merged
merged 5 commits into from
May 26, 2015

Conversation

robd
Copy link
Contributor

@robd robd commented May 20, 2015

At the moment, one of the hardest bits of code to understand, and the source of some historical bugs, is the @stdout, @stderr attributes on command. These are used as a temporary buffer of the latest unconsumed output lines by the formatters. The backends append to the buffer (netssh, local) via the on_stdout and on_stderr methods, and then the pretty formatter clears the buffers via the clear_stdout_lines and clear_stderr_lines methods.

As well as being hard to understand, it makes integrating with SSHKit harder. For example, Airbrussh has to dup the Command in order to make sure that stdout/stderr are not cleared by the pretty formatter.

In order to fix this, I propose to widen the Formatter API and include 3 specific methods (log_command_start, log_command_data, log_command_exit) for logging the different command states rather than switching on the internal state in Command.

The other state on Command (ie :started_at, :started, :exit_status, :full_stdout, :full_stderr) is less confusing because at least this state is all being set by the backends, and simply read by the formatters (rather than mutated). I propose to leave these for the moment.

As part of this, I'd like to deprecate @stdout and @stderr on Command to explain the changes to people who use the stdout / stderr accessors. (I deleted these previously, but I will reinstate them with deprecation warnings). In order to do this, I am intending to write a de-duplicating deprecator and introduce a new config option - SSHKit.config.deprecation_output which takes the same sort of object as the normal output (ie one which implements <<). By default, I propose to log deprecation directly to stderr. This means deprecation errors will show up for people using formatters which hide normal warnings (eg Dot or BlackHole). Deprecation warnings can easily be disabled:

# Supress deprecation warnings
SSHKit.config.deprecation_output = nil

SSHKit.config.deprecation_output = File.open('log/dep_warnings.log', 'wb')

@mattbrictson I discussed I had some ideas for this a while ago. If you don't mind, can you look at the new formatter methods and see what you think?

@leehambley Would value your thoughts on this as always.

@robd robd changed the title Proposal deprecate command stdout / stderr attribute state Proposal: Deprecate command stdout / stderr attribute state May 20, 2015
@leehambley
Copy link
Member

@robd the two methods clear_stdout_lines and clear_stderr_lines existed as a horrible way to try and clear the duplicate content that was sometimes seen in the race condition which was recently fixed regarding receiving the :on_exit event before the last chunk of data (where maybe the last chunk was whitespace) it's quite some time since I wrote that part though, so it's entirely possible I'm mis-remembering.

I'd be thrilled to see this merged, it's a drastic clean up, and I like the deprecation solution you've proposed, let's build it.

@mattbrictson
Copy link
Member

@robd This looks very nice. 👍 to merge.

My only nitpick would be I think the meta-programming you've used to define methods in abstract.rb might be a little too "fancy". The primary purpose of abstract is to serve as documentation for extension authors, so I think sacrificing some DRY-ness for readability may be warranted here.

Edit: I realize this is not ready to merge yet, but I like the direction it is going!

@robd
Copy link
Contributor Author

robd commented May 20, 2015

OK great.

Re the clear_stdout_lines and clear_stderr_lines, I added these to replace the stdout="", stderr="" writers which were there before. However I now think this was a bit dangerous, because other formatters may be relying on these writers (in fact we saw this with Airbrussh, but I wasn't thinking properly about deprecation at that point). Therefore, I propose to reinstate command.stdout= and command.stdout= with deprecation warnings, to be removed next major release.

I think it would be OK to just delete the new clear_stdout_lines and clear_stderr_lines methods I added which are now no longer needed, because these haven't ever been released. No one will be using these (unless they are developing against master). @mattbrictson there will be rework needed for Aribrussh, but I will try to put together a PR once the API changes have landed. (Welcome feedback about fancy dynamic methods. These things are a bit hard to call when you're working by yourself - will fix).

First of all I want to add support for showing deprecation warnings safely as a separate PR. I propose to add this as a separate logger to the main formatter for the following reasons:

  • I tried a solution to add a warn_deprecated method to Formatter, but I ended up with an infinite loop because the method I was deprecating was being called as part of logging the deprecation warning!
  • People may want to disable deprecation logging without affecting the normal logging (eg if they don't have time to fix deprecation problems)
  • I want to only show each deprecation warning once per run, and I don't want the de-duping to get tangled up with the main formatters.
  • We should show people deprecation warnings (which they can disable) even if they have a formatter which hides normal warnings (eg Dot) so that things don't just break without warning in a subsequent release.

I will rework the existing deprecation call we have and update the docs.

robd added 4 commits May 21, 2015 10:12
Try to expose when changes may break a ‘typical’ custom formatter which has been implemented based on the Pretty formatter
No longer rely on state in Command for determining log message type or std stream data
@robd robd force-pushed the deprecate-command-stdstream-state branch from 6ad3871 to 36b7c6a Compare May 21, 2015 10:42
@robd robd changed the title Proposal: Deprecate command stdout / stderr attribute state Introduce explicit command logging methods and deprecate stdout / stderr Command attrs May 21, 2015
@robd robd force-pushed the deprecate-command-stdstream-state branch 4 times, most recently from 423a022 to 747711e Compare May 21, 2015 10:59
Remove unused clear_stdout_lines / clear_stderr_lines methods which were never released
@robd robd force-pushed the deprecate-command-stdstream-state branch from 747711e to fb19c38 Compare May 21, 2015 11:09
@robd
Copy link
Contributor Author

robd commented May 21, 2015

OK, I have incorporated the feedback, deprecated the old std_out, std_err accessors and updated the docs.

From my perspective this is ready to merge.

@mattbrictson Do you want me to look at integrating this into Airbrussh? Once this PR is merged, Airbrussh will be broken again against master. I'm not quite sure what your policy is on SSHKit version support, but I think the CommandOutput facade might not be needed any more, since the version of SSHKit master with clear_#{stream}_lines was never released.

I guess we will want to override log_command_start, log_command_data and log_command_exit in the Airbrussh Formatter where appropriate, but obviously old versions of SSHKit won't call these.

Let me know if I can help.

@mattbrictson
Copy link
Member

@robd if you want to take a stab at a PR for airbrussh, that would be fantastic. Ideally I would like airbrussh to continue working with any version of sshkit >= 1.6.1. But if the conditional code to do that is too complicated (i.e. worse than CommandOutput), I'll consider revising the minimum sshkit requirement.

@robd
Copy link
Contributor Author

robd commented May 21, 2015

@mattbrictson No probs - I'll see what I can do :)

robd added a commit to robd/airbrussh that referenced this pull request May 26, 2015
The log_command_start, log_command_data and log_command_exit methods will be supported when PR257 is merged - capistrano/sshkit#257
@robd
Copy link
Contributor Author

robd commented May 26, 2015

The necessary Airbrussh changes are in mattbrictson/airbrussh#17.

@leehambley I wondered, would you be up for merging the Airbrussh formatter into SSHKit? This would dramatically ease maintenance of Airbrussh, because at the moment trying to support various versions of SSHKit as the formatter API changes requires quite a bit of care and effort. I don't propose to do this right now, because I want to get back to finishing up support for interactive sudo, but I wanted to find out your thoughts on this..

@leehambley
Copy link
Member

I'd be more than happy to make it the default formatter, but I wouldn't want to put @mattbrictson in a position where his work is under appreciated, and he's insufficiently credited for it.

Open to anything, give me a break though, I'm travelling a lot this week, and next week when I'm back we're launching a new company >_<, but yeah - would love to if @mattbrictson is up for it.

@mattbrictson actually heads-up I'm in SFO the next 4 days for IO if you feel like letting me buy you a beer.

leehambley added a commit that referenced this pull request May 26, 2015
Introduce explicit command logging methods and deprecate stdout / stderr Command attrs
@leehambley leehambley merged commit 6c49de9 into capistrano:master May 26, 2015
robd added a commit to robd/airbrussh that referenced this pull request May 26, 2015
robd added a commit to robd/airbrussh that referenced this pull request May 26, 2015
The log_command_start, log_command_data and log_command_exit methods are supported since capistrano/sshkit#257
@robd
Copy link
Contributor Author

robd commented May 27, 2015

@leehambley OK great. I don't think the Airbrussh merge is urgent - we can pick this up at some later stage once things have calmed down at your end. Have a good IO and good luck with the launch.

jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Dec 14, 2015
## 1.8.1

  * Change license to MIT, thanks to all the patient contributors who gave
    their permissions.

## 1.8.0

  * add SSHKit::Backend::ConnectionPool#close_connections
    [PR #285](capistrano/sshkit#285)
    @akm
  * Clean up rubocop lint warnings
    [PR #275](capistrano/sshkit#275)
    @cshaffer
    * Prepend unused parameter names with an underscore
    * Prefer “safe assignment in condition”
    * Disambiguate regexp literals with parens
    * Prefer `sprintf` over `String#%`
    * No longer shadow `caller_line` variable in `DeprecationLogger`
    * Rescue `StandardError` instead of `Exception`
    * Remove useless `private` access modifier in `TestAbstract`
    * Disambiguate block operator with parens
    * Disambiguate between grouped expression and method params
    * Remove assertion in `TestHost#test_assert_hosts_compare_equal` that compares something with itself
  * Export environment variables and execute command in a subshell.
    [PR #273](capistrano/sshkit#273)
    @kuon
  * Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
    [PR #257](capistrano/sshkit#257)
    @robd
    * Deprecate `@stdout` and `@stderr` accessors on `Command`
  * Add support for deprecation logging options.
    [README](README.md#deprecation-warnings),
    [PR #258](capistrano/sshkit#258)
    @robd
  * Quote environment variable values.
    [PR #250](capistrano/sshkit#250)
    @Sinjo - Chris Sinjakli
  * Simplified formatter hierarchy.
    [PR #248](capistrano/sshkit#248)
    @robd
    * `SimpleText` formatter now extends `Pretty`, rather than duplicating.
  * Hide ANSI color escape sequences when outputting to a file.
    [README](README.md#output-colors),
    [Issue #245](capistrano/sshkit#245),
    [PR #246](capistrano/sshkit#246)
    @robd
    * Now only color the output if it is associated with a tty,
      or the `SSHKIT_COLOR` environment variable is set.
  * Removed broken support for assigning an `IO` to the `output` config option.
    [Issue #243](capistrano/sshkit#243),
    [PR #244](capistrano/sshkit#244)
    @robd
    * Use `SSHKit.config.output = SSHKit::Formatter::SimpleText.new($stdin)` instead
  * Added support for `:interaction_handler` option on commands.
    [PR #234](capistrano/sshkit#234),
    [PR #242](capistrano/sshkit#242)
    @robd
  * Removed partially supported `TRACE` log level.
    [2aa7890](capistrano/sshkit@2aa7890)
    @robd
  * Add support for the `:strip` option to the `capture` method and strip by default on the `Local` backend.
    [PR #239](capistrano/sshkit#239),
    [PR #249](capistrano/sshkit#249)
    @robd
    * The `Local` backend now strips by default to be consistent with the `Netssh` one.
    * This reverses change [7d15a9a](capistrano/sshkit@7d15a9a) to the `Local` capture API to remove stripping by default.
    * If you require the raw, unstripped output, pass the `strip: false` option: `capture(:ls, strip: false)`
  * Simplified backend hierarchy.
    [PR #235](capistrano/sshkit#235),
    [PR #237](capistrano/sshkit#237)
    @robd
    * Moved duplicate implementations of `make`, `rake`, `test`, `capture`, `background` on to `Abstract` backend.
    * Backend implementations now only need to implement `execute_command`, `upload!` and `download!`
    * Removed `Printer` from backend hierarchy for `Local` and `Netssh` backends (they now just extend `Abstract`)
    * Removed unused `Net::SSH:LogLevelShim`
  * Removed dependency on the `colorize` gem. SSHKit now implements its own ANSI color logic, with no external dependencies. Note that SSHKit now only supports the `:bold` or plain modes. Other modes will be gracefully ignored. [#263](capistrano/sshkit#263)
  * New API for setting the formatter: `use_format`. This differs from `format=` in that it accepts options or arguments that will be passed to the formatter's constructor. The `format=` syntax will be deprecated in a future release. [#295](capistrano/sshkit#295)
  * SSHKit now immediately raises a `NameError` if you try to set a formatter that does not exist. [#295](capistrano/sshkit#295)
jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Dec 14, 2015
## 1.8.1

  * Change license to MIT, thanks to all the patient contributors who gave
    their permissions.

## 1.8.0

  * add SSHKit::Backend::ConnectionPool#close_connections
    [PR #285](capistrano/sshkit#285)
    @akm
  * Clean up rubocop lint warnings
    [PR #275](capistrano/sshkit#275)
    @cshaffer
    * Prepend unused parameter names with an underscore
    * Prefer “safe assignment in condition”
    * Disambiguate regexp literals with parens
    * Prefer `sprintf` over `String#%`
    * No longer shadow `caller_line` variable in `DeprecationLogger`
    * Rescue `StandardError` instead of `Exception`
    * Remove useless `private` access modifier in `TestAbstract`
    * Disambiguate block operator with parens
    * Disambiguate between grouped expression and method params
    * Remove assertion in `TestHost#test_assert_hosts_compare_equal` that compares something with itself
  * Export environment variables and execute command in a subshell.
    [PR #273](capistrano/sshkit#273)
    @kuon
  * Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
    [PR #257](capistrano/sshkit#257)
    @robd
    * Deprecate `@stdout` and `@stderr` accessors on `Command`
  * Add support for deprecation logging options.
    [README](README.md#deprecation-warnings),
    [PR #258](capistrano/sshkit#258)
    @robd
  * Quote environment variable values.
    [PR #250](capistrano/sshkit#250)
    @Sinjo - Chris Sinjakli
  * Simplified formatter hierarchy.
    [PR #248](capistrano/sshkit#248)
    @robd
    * `SimpleText` formatter now extends `Pretty`, rather than duplicating.
  * Hide ANSI color escape sequences when outputting to a file.
    [README](README.md#output-colors),
    [Issue #245](capistrano/sshkit#245),
    [PR #246](capistrano/sshkit#246)
    @robd
    * Now only color the output if it is associated with a tty,
      or the `SSHKIT_COLOR` environment variable is set.
  * Removed broken support for assigning an `IO` to the `output` config option.
    [Issue #243](capistrano/sshkit#243),
    [PR #244](capistrano/sshkit#244)
    @robd
    * Use `SSHKit.config.output = SSHKit::Formatter::SimpleText.new($stdin)` instead
  * Added support for `:interaction_handler` option on commands.
    [PR #234](capistrano/sshkit#234),
    [PR #242](capistrano/sshkit#242)
    @robd
  * Removed partially supported `TRACE` log level.
    [2aa7890](capistrano/sshkit@2aa7890)
    @robd
  * Add support for the `:strip` option to the `capture` method and strip by default on the `Local` backend.
    [PR #239](capistrano/sshkit#239),
    [PR #249](capistrano/sshkit#249)
    @robd
    * The `Local` backend now strips by default to be consistent with the `Netssh` one.
    * This reverses change [7d15a9a](capistrano/sshkit@7d15a9a) to the `Local` capture API to remove stripping by default.
    * If you require the raw, unstripped output, pass the `strip: false` option: `capture(:ls, strip: false)`
  * Simplified backend hierarchy.
    [PR #235](capistrano/sshkit#235),
    [PR #237](capistrano/sshkit#237)
    @robd
    * Moved duplicate implementations of `make`, `rake`, `test`, `capture`, `background` on to `Abstract` backend.
    * Backend implementations now only need to implement `execute_command`, `upload!` and `download!`
    * Removed `Printer` from backend hierarchy for `Local` and `Netssh` backends (they now just extend `Abstract`)
    * Removed unused `Net::SSH:LogLevelShim`
  * Removed dependency on the `colorize` gem. SSHKit now implements its own ANSI color logic, with no external dependencies. Note that SSHKit now only supports the `:bold` or plain modes. Other modes will be gracefully ignored. [#263](capistrano/sshkit#263)
  * New API for setting the formatter: `use_format`. This differs from `format=` in that it accepts options or arguments that will be passed to the formatter's constructor. The `format=` syntax will be deprecated in a future release. [#295](capistrano/sshkit#295)
  * SSHKit now immediately raises a `NameError` if you try to set a formatter that does not exist. [#295](capistrano/sshkit#295)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants