How to silence DataMapper in Sinatra - sinatra

So, a simple little question. Every time I perform some transaction with DataMapper inside one of my "get" or "post" blocks, I get output looking something like this...
core.local - - [19/Sep/2012:09:04:54 CEST] "GET /eval_workpiece/state?id=24 HTTP/1.1" 200 4
- -> /eval_workpiece/state?id=24
It's a little too verbose for my liking. Can I turn this feedback off?

This isn’t Datamapper logging, this is the logging done by the WEBrick server, which logs all requests using these two formats by default.
(Note this isn’t Rack logging either, although the Rack::CommonLogger uses the same (or at least very similar) format).
The simplest way to stop this would be to switch to another server that doesn’t add its own logging, such as Thin.
If you want to continue using WEBrick, you’ll need to find a way to pass options to it from your Sinatra app. The current released Sinatra gem (1.3.3) doesn’t allow an easy way to do this, but the current master allows you to set the :server_options setting which Sinatra will then pass on. So in the future you should be able to do this:
set :server_settings, {:AccessLog => []}
in order to silence WEBrick.
For the time being you can add something like this to the end of your app file (I’m assuming you’re launching your app with something like ruby my_app_file.rb):
disable :run
Sinatra::Application.run! do |server|
server.config[:AccessLog] = []
end

To cut off all logging:
DataMapper.logger = nil
To change verbosity:
DataMapper.logger.set_log(logger, :warn) # where logger is Sinatra's logging object
Other levels are :fatal => 7, :error => 6, :warn => 4, :info => 3, :debug => 0 (http://rubydoc.info/gems/dm-core/1.1.0/DataMapper/Logger)

If you're running with ActiveSupport, you can use the Kernel extension:
quietly { perform_a_noisy_task }
This temporarily binds STDOUT and SDTERR to /dev/null for the duration of the block. Since you may not want to suppress all output, theoretically you can do:
with_warnings(:warn) { # or :fatal or :error or :info or :debug
perform_a_noisy_task
}
and appropriate messages will be suppressed. (NB: I say 'theoretically' because using with_warnings gave me a seemingly unrelated error in my Padrino/DataMapper environment. YMMV.)

Related

Stop huge error output from testing-library

I love testing-library, have used it a lot in a React project, and I'm trying to use it in an Angular project now - but I've always struggled with the enormous error output, including the HTML text of the render. Not only is this not usually helpful (I couldn't find an element, here's the HTML where it isn't); but it gets truncated, often before the interesting line if you're running in debug mode.
I simply added it as a library alongside the standard Angular Karma+Jasmine setup.
I'm sure you could say the components I'm testing are too large if the HTML output causes my console window to spool for ages, but I have a lot of integration tests in Protractor, and they are SO SLOW :(.
I would say the best solution would be to use the configure method and pass a custom function for getElementError which does what you want.
You can read about configuration here: https://testing-library.com/docs/dom-testing-library/api-configuration
An example of this might look like:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
You can then put this in any single test file or use Jest's setupFiles or setupFilesAfterEnv config options to have it run globally.
I am assuming you running jest with rtl in your project.
I personally wouldn't turn it off as it's there to help us, but everyone has a way so if you have your reasons, then fair enough.
1. If you want to disable errors for a specific test, you can mock the console.error.
it('disable error example', () => {
const errorObject = console.error; //store the state of the object
console.error = jest.fn(); // mock the object
// code
//assertion (expect)
console.error = errorObject; // assign it back so you can use it in the next test
});
2. If you want to silence it for all the test, you could use the jest --silent CLI option. Check the docs
The above might even disable the DOM printing that is done by rtl, I am not sure as I haven't tried this, but if you look at the docs I linked, it says
"Prevent tests from printing messages through the console."
Now you almost certainly have everything disabled except the DOM recommendations if the above doesn't work. On that case you might look into react-testing-library's source code and find out what is used for those print statements. Is it a console.log? is it a console.warn? When you got that, just mock it out like option 1 above.
UPDATE
After some digging, I found out that all testing-library DOM printing is built on prettyDOM();
While prettyDOM() can't be disabled you can limit the number of lines to 0, and that would just give you the error message and three dots ... below the message.
Here is an example printout, I messed around with:
TestingLibraryElementError: Unable to find an element with the text: Hello ther. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
...
All you need to do is to pass in an environment variable before executing your test suite, so for example with an npm script it would look like:
DEBUG_PRINT_LIMIT=0 npm run test
Here is the doc
UPDATE 2:
As per the OP's FR on github this can also be achieved without injecting in a global variable to limit the PrettyDOM line output (in case if it's used elsewhere). The getElementError config option need to be changed:
dom-testing-library/src/config.js
// called when getBy* queries fail. (message, container) => Error
getElementError(message, container) {
const error = new Error(
[message, prettyDOM(container)].filter(Boolean).join('\n\n'),
)
error.name = 'TestingLibraryElementError'
return error
},
The callstack can also be removed
You can change how the message is built by setting the DOM testing library message building function with config. In my Angular project I added this to test.js:
configure({
getElementError: (message: string, container) => {
const error = new Error(message);
error.name = 'TestingLibraryElementError';
error.stack = null;
return error;
},
});
This was answered here: https://github.com/testing-library/dom-testing-library/issues/773 by https://github.com/wyze.

Sinatra Error log integration with sentry

Below are my config.ru file
require 'raven'
require './managers/log_manager.rb'
logger = LogManager.create_logger('/error.log')
logger.log(Logger::ERROR, "********** just testing **********")
puts "#{logger.inspect}"
Raven.configure do |config|
config.dsn = 'https://secrect'
config.logger = logger
config.environments = 'development'
end
use Raven::Rack
Only exceptions got notify. My problem is to get notify for Error log data, but currently it didn't.
Because Ruby doesn't have a consistent logging solution you'll probably have to write your own handler.
If, i.e. the logging helper gives you an Event, you'd probably do something like this:
def my_log_helper(event)
if event.really_is_an_exception
Raven.capture_exception(event.message)
else
Raven.capture_message(event.message)
end
end
p.s. sorry about my awful ruby, I'm not fluent
The main thing is that Raven tries to be magical when it can, but outside of that it tends to explicitness.
There's many other things you can do with integration, such as sending localized context, and things that are generally environment-specific, but the basics are mostly straightforward.

How to redirect category page to first child in Umbraco without a ThreadAbortException

(I'm about to answer this question as well, because I've found the solution, but Google didn't really help, so hopefully this will gain some PageRank for the search terms I was using.)
We have a big Umbraco site with several sections, but most locales don't have section homepages. So if the structure looks like:
- Homepage
- Section1
- Page1-1
- Page1-2
- Section2
- Page2-1
- Page2-2
and so on, then going to ~/section1/ would redirect you to ~/section1/page1-1/ (and, likewise ~/section2/ redirects you to ~/section2/page2-1/).
At the moment, we use a macro that checks a property in the locale homepage and then redirects:
var node = Model.AncestorOrSelf("SiteHome");
var useCSSV2 = node.GetProperty("useCSSV2").Value;
if (useCSSV2 == "1")
{
Response.Redirect(Model.Children.First().Url);
}
We're seeing a bunch of occasions where macros don't load properly, with errors like
Error loading MacroEngine script (file: PrimaryNavigationSwitcher.cshtml)
displaying instead. Looking at the UmbracoTraceLog, I can see things like:
2014-11-25 00:11:28,226 [5] WARN umbraco.macro - [Thread 39] Error loading MacroEngine script (file: PrimaryNavigationSwitcher.cshtml, Type: ''. Exception: System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.AbortInternal()
at System.Threading.Thread.Abort(Object stateInfo)
at System.Web.HttpResponse.AbortCurrentThread()
at System.Web.HttpResponseWrapper.Redirect(String url)
at ASP._Page_macroScripts_SecondLevelPageRedirection_cshtml.Execute() in d:\webroot\www.mysite.com\macroScripts\SecondLevelPageRedirection.cshtml:line 8
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.WebPages.WebPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at umbraco.MacroEngines.RazorMacroEngine.ExecuteRazor(MacroModel macro, INode currentPage)
at umbraco.MacroEngines.RazorMacroEngine.Execute(MacroModel macro, INode currentPage)
at umbraco.macro.loadMacroScript(MacroModel macro)
at umbraco.macro.renderMacro(Hashtable pageElements, Int32 pageId)
(where line 8 of SecondLevelPageRedirection.cshtml is the Response.Redirect).
That problem and the ThreadAbortException itself are strongly suggesting to me that Response.Redirect is the problem here and I should be using some other means of performing this redirect. (And even if this weren't a problem I'd prefer to avoid the performance impact of a bunch of exceptions being thrown.)
How should we be performing this redirect to have the same effect (so anyone going to ~/section1/ will be redirected to ~/section1/page1-1/ and so on), without having to add an umbracoRedirect or umbracoInternalRedirectId to each node and without having these damn ThreadAbortExceptions thrown all the time?
As detailed in a handful of places (notably Why Response.Redirect causes System.Threading.ThreadAbortException? here on Stack Overflow and PRB: ThreadAbortException Occurs If You Use Response.End, Response.Redirect, or Server.Transfer on the MSKB), Response.Redirect(string) is only present in ASP.Net for backwards compatibility.
To quote from Joel Fillmore in his answer to the Stack Overflow question linked above:
The correct pattern is to call the Redirect overload with endResponse=false and make a call to tell the IIS pipeline that it should advance directly to the EndRequest stage once you return control:
Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();
This blog post from Thomas Marquardt provides additional details, including how to handle the special case of redirecting inside an Application_Error handler.
Note that code after the Context.ApplicationInstance.CompleteRequest call will execute, so may need handling separately.
Incidentally, as the problem stems from Response.End, which includes the code
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
then Server.Transfer will have precisely the same problem. There is more information at Is Response.End() considered harmful?

Redmine REST API called from Ruby is ignoring updates to some fields

I have some code which was working at one point but no longer works, which strongly suggests that the redmine configuration is involved somehow (I'm not the redmine admin), but the lack of any error messages makes it hard to determine what is wrong. Here is the code:
#!/usr/bin/env ruby
require "rubygems"
gem "activeresource", "2.3.14"
require "active_resource"
class Issue < ActiveResource::Base
self.site = "https://redmine.mydomain.com/"
end
Issue.user = "myname"
Issue.password = "mypassword" # Don't hard-code real passwords :-)
issue = Issue.find 19342 # Created manually to avoid messing up real tickets.
field = issue.custom_fields.select { |x| x.name == "Release Number" }.first
issue.notes = "Testing at #{Time.now}"
issue.custom_field_values = { field.id => "Release-1.2.3" }
success = issue.save
puts "field.id: #{field.id}"
puts "success: #{success}"
puts "errors: #{issue.errors.full_messages}"
When this runs, the output is:
field.id: 40
success: true
errors: []
So far so good, except that when I go back to the GUI and look at this ticket, the "notes" part is updated correctly but the custom field is unchanged. I did put some tracing in the ActiveRecord code and that appears to be sending out my desired updates, so I suspect the problem is on the server side.
BTW if you know of any good collections of examples of accessing Redmine from Ruby using the REST API that would be really helpful too. I may just be looking in the wrong places, but all I've found are a few trivial ones that are just enough to whet one's appetite for more, and the docs I've seen on the redmine site don't even list all the available fields. (Ideally, it would be nice if the examples also specified which version of redmine they work with.)

How Does the ActiveResource Get Call show find(:first) or find(:last) requests?

I am developing a Sinatra server that can accept calls from ActiveResource, but can"t determine how to identify Get calls specificying :first or :last.
In Rails 3
User.find(:first) => localhost.com/user.xml
User.find(:last) => localhost.com/user.xml
This works exactly as it should according to the examples in the ActiveResource documentation.
It is clear what path they request (the same one), but it is not clear what happens to the :first or :last elements. I can not find them in the request object on the Sinatra server. Does anyone know what happened to those references?
Thanks for your help.
Code from ActiveResource library
def find(*arguments)
scope = arguments.slice!(0)
options = arguments.slice!(0) || {}
case scope
when :all then find_every(options)
when :first then find_every(options).first
when :last then find_every(options).last
when :one then find_one(options)
else find_single(scope, options)
end
end
last and first just methods from Enumerable module