[erlang-questions] Fail politely, fail noisily

51 views
Skip to first unread message

Joe Armstrong

unread,
Aug 29, 2012, 3:36:43 AM8/29/12
to Erlang
As I was revising my Erlang book I came up with a new slogan (like the
old "let it crash") ... I like slogans they are
easy to remember - here's a new one.

Fail politely, fail noisily means the user should get a polite error message
and the programmer should get an informative error message when an
application crashes.

There should be TWO error messages not one.

I want to collect examples of polite and noisy error messages for a
future lecture.

Today I got this error message - which I consider not just noisy but
bordering upon downright rude - all
I did was click on a button - I didn't want to unleash the wrath of
the java monster - I was required to tell the system
how many hours I had worked but the java monster spake thus, and there
was fear and trembling in the land
and all that read what was writ were sore afraid:

---

com.sap.mw.jco.JCO$Exception: (103) RFC_ERROR_LOGON_FAILURE: System
received an expired SSO ticket
at com.sap.mw.jco.MiddlewareJRfc.generateJCoException(MiddlewareJRfc.java:555)
at com.sap.mw.jco.MiddlewareJRfc$Client.connect(MiddlewareJRfc.java:1099)
at com.sap.mw.jco.JCO$Client.connect(JCO.java:3644)
at com.sap.mw.jco.JCO$Pool.getClient(JCO.java:5904)
at com.sap.mw.jco.JCO$PoolManager.getClient(JCO.java:7081)
at com.sap.mw.jco.JCO$PoolManager.getClient(JCO.java:7030)
at com.sap.tc.webdynpro.serverimpl.core.sl.AbstractJCOClientConnection.getClient(AbstractJCOClientConnection.java:444)
at com.sap.pcuigp.xssfpm.wd.BackendConnections.connectModelInternal(BackendConnections.java:326)
at com.sap.pcuigp.xssfpm.wd.BackendConnections.initBackend(BackendConnections.java:266)
at com.sap.pcuigp.xssfpm.wd.BackendConnections.connectModel(BackendConnections.java:167)
at com.sap.pcuigp.xssfpm.wd.wdp.InternalBackendConnections.connectModel(InternalBackendConnections.java:229)
at com.sap.pcuigp.xssfpm.wd.FPMComponent$FPM.connectModel(FPMComponent.java:864)
at com.sap.pcuigp.xssfpm.wd.FPMComponent$FPMProxy.connectModel(FPMComponent.java:1094)
at com.sap.pcuigp.xssfpm.wd.BackendConnections.init(BackendConnections.java:155)
at com.sap.pcuigp.xssfpm.wd.wdp.InternalBackendConnections.init(InternalBackendConnections.java:225)
at com.sap.pcuigp.xssfpm.wd.FPMComponent.wdDoInit(FPMComponent.java:204)
at com.sap.pcuigp.xssfpm.wd.wdp.InternalFPMComponent.wdDoInit(InternalFPMComponent.java:105)
at com.sap.tc.webdynpro.progmodel.generation.DelegatingComponent.doInit(DelegatingComponent.java:161)
at com.sap.tc.webdynpro.progmodel.controller.Controller.initController(Controller.java:227)
at com.sap.tc.webdynpro.progmodel.components.Component.initController(Component.java:258)
at com.sap.tc.webdynpro.progmodel.controller.Controller.init(Controller.java:206)
at com.sap.tc.webdynpro.clientserver.cal.ClientApplication.init(ClientApplication.java:590)
at com.sap.tc.webdynpro.clientserver.cal.ClientApplication.doPreprocessing(ClientApplication.java:1457)
at com.sap.tc.webdynpro.clientserver.session.ApplicationSession.doPreprocessing(ApplicationSession.java:660)
at com.sap.tc.webdynpro.clientserver.session.ApplicationSession.doProcessing(ApplicationSession.java:349)
at com.sap.tc.webdynpro.clientserver.session.RequestManager.doProcessing(RequestManager.java:326)
at com.sap.tc.webdynpro.serverimpl.core.sessionctx.AbstractExecutionContextDispatcher.delegateToRequestManager(AbstractExecutionContextDispatcher.java:62)
at com.sap.tc.webdynpro.serverimpl.wdc.sessionctx.DispatchHandlerForRequestManager.service(DispatchHandlerForRequestManager.java:39)
at com.sap.tc.webdynpro.serverimpl.wdc.sessionctx.DispatchHandlerForRequestManager.service(DispatchHandlerForRequestManager.java:46)
at com.sap.engine.services.servlets_jsp.server.deploy.impl.module.IRequestDispatcherImpl.dispatch(IRequestDispatcherImpl.java:270)
at com.sap.tc.webdynpro.serverimpl.wdc.sessionctx.ExecutionContextDispatcher.dispatchToAppContext(ExecutionContextDispatcher.java:68)
at com.sap.tc.webdynpro.serverimpl.core.sessionctx.AbstractExecutionContextDispatcher.dispatch(AbstractExecutionContextDispatcher.java:53)
at com.sap.tc.webdynpro.clientserver.session.RequestManager.doProcessing(RequestManager.java:245)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy$Runner.callRequestManager(JavaApplicationProxy.java:1244)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy$Runner.callEmbeddedApplication(JavaApplicationProxy.java:1122)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy$StartCommand.doExecute(JavaApplicationProxy.java:1575)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy$AbstractCommand.execute(JavaApplicationProxy.java:1488)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy$Runner.execute(JavaApplicationProxy.java:1028)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy.execute(JavaApplicationProxy.java:859)
at com.sap.tc.webdynpro.clientserver.embedding.JavaApplicationProxy.start1(JavaApplicationProxy.java:637)
at com.sap.tc.webdynpro.portal.pb.impl.JavaApplicationProxyAdapter.create(JavaApplicationProxyAdapter.java:166)
at com.sap.portal.pb.PageBuilder.updateApplications(PageBuilder.java:1691)
at com.sap.portal.pb.PageBuilder.createPage(PageBuilder.java:411)
at com.sap.portal.pb.PageBuilder.init(PageBuilder.java:655)
at com.sap.portal.pb.PageBuilder.wdDoInit(PageBuilder.java:227)
at com.sap.portal.pb.wdp.InternalPageBuilder.wdDoInit(InternalPageBuilder.java:137)
at com.sap.tc.webdynpro.progmodel.generation.DelegatingComponent.doInit(DelegatingComponent.java:161)
at com.sap.tc.webdynpro.progmodel.controller.Controller.initController(Controller.java:227)
at com.sap.tc.webdynpro.progmodel.components.Component.initController(Component.java:258)
at com.sap.tc.webdynpro.progmodel.controller.Controller.init(Controller.java:206)
at com.sap.tc.webdynpro.clientserver.cal.ClientApplication.init(ClientApplication.java:590)
at com.sap.tc.webdynpro.clientserver.cal.ClientApplication.doPreprocessing(ClientApplication.java:1457)
at com.sap.tc.webdynpro.clientserver.session.ApplicationSession.doPreprocessing(ApplicationSession.java:660)
at com.sap.tc.webdynpro.clientserver.session.ApplicationSession.doProcessing(ApplicationSession.java:349)
at com.sap.tc.webdynpro.clientserver.session.RequestManager.doProcessing(RequestManager.java:326)
at com.sap.tc.webdynpro.serverimpl.core.AbstractDispatcherServlet.doContent(AbstractDispatcherServlet.java:87)
at com.sap.tc.webdynpro.serverimpl.wdc.DispatcherServlet.doContent(DispatcherServlet.java:89)
at com.sap.tc.webdynpro.serverimpl.core.AbstractDispatcherServlet.doPost(AbstractDispatcherServlet.java:62)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at com.sap.engine.services.servlets_jsp.server.Invokable.invoke(Invokable.java:152)
at com.sap.engine.services.servlets_jsp.server.Invokable.invoke(Invokable.java:38)
at com.sap.engine.services.servlets_jsp.server.HttpHandlerImpl.runServlet(HttpHandlerImpl.java:457)
at com.sap.engine.services.servlets_jsp.server.HttpHandlerImpl.handleRequest(HttpHandlerImpl.java:210)
at com.sap.engine.services.httpserver.server.RequestAnalizer.startServlet(RequestAnalizer.java:441)
at com.sap.engine.services.httpserver.server.RequestAnalizer.startServlet(RequestAnalizer.java:430)
at com.sap.engine.services.servlets_jsp.filters.DSRWebContainerFilter.process(DSRWebContainerFilter.java:38)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.servlets_jsp.filters.ServletSelector.process(ServletSelector.java:81)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.servlets_jsp.filters.ApplicationSelector.process(ApplicationSelector.java:276)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.WebContainerInvoker.process(WebContainerInvoker.java:81)
at com.sap.engine.services.httpserver.chain.HostFilter.process(HostFilter.java:9)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.ResponseLogWriter.process(ResponseLogWriter.java:60)
at com.sap.engine.services.httpserver.chain.HostFilter.process(HostFilter.java:9)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.DefineHostFilter.process(DefineHostFilter.java:27)
at com.sap.engine.services.httpserver.chain.ServerFilter.process(ServerFilter.java:12)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.MonitoringFilter.process(MonitoringFilter.java:29)
at com.sap.engine.services.httpserver.chain.ServerFilter.process(ServerFilter.java:12)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.SessionSizeFilter.process(SessionSizeFilter.java:26)
at com.sap.engine.services.httpserver.chain.ServerFilter.process(ServerFilter.java:12)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.MemoryStatisticFilter.process(MemoryStatisticFilter.java:57)
at com.sap.engine.services.httpserver.chain.ServerFilter.process(ServerFilter.java:12)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.filters.DSRHttpFilter.process(DSRHttpFilter.java:43)
at com.sap.engine.services.httpserver.chain.ServerFilter.process(ServerFilter.java:12)
at com.sap.engine.services.httpserver.chain.AbstractChain.process(AbstractChain.java:78)
at com.sap.engine.services.httpserver.server.Processor.chainedRequest(Processor.java:475)
at com.sap.engine.services.httpserver.server.Processor$FCAProcessorThread.process(Processor.java:269)
at com.sap.engine.services.httpserver.server.rcm.RequestProcessorThread.run(RequestProcessorThread.java:56)
at com.sap.engine.core.thread.execution.Executable.run(Executable.java:122)
at com.sap.engine.core.thread.execution.Executable.run(Executable.java:101)
at com.sap.engine.core.thread.execution.CentralExecutor$SingleThread.run(CentralExecutor.java:328)
Caused by:
RfcException:
message: System received an expired SSO ticket
Return code: RFC_SYS_EXCEPTION(3)
error group: 103
key: RFC_ERROR_LOGON_FAILURE
at com.sap.mw.rfc.api.RfcApi.RfcOpen(RfcApi.java:831)
at com.sap.mw.jco.MiddlewareJRfc$Client.connect(MiddlewareJRfc.java:1092)
... 97 more

-- there was also a one liner

System received an Expired SSO ticket

(I guess this is the meaning of the longer message)

-

(I think the old BSD crashed with the epic words "pointers bungled,
sorry" and then just immediately halted - but that was from
memory - can anybody remember this)


/Joe
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://erlang.org/mailman/listinfo/erlang-questions

Thomas Elsgaard

unread,
Aug 29, 2012, 3:47:01 AM8/29/12
to Joe Armstrong, Erlang
Hi Joe

There is also PHK's concept of "guru meditation" in the varnish http accelerator..


Basically the idea is: the user cannot do anything about the error, so let it fail, but provide the transaction Id (xid) so the admin can can troubleshoot...

Thomas

Jesper Louis Andersen

unread,
Aug 30, 2012, 10:52:53 AM8/30/12
to Thomas Elsgaard, Erlang

On Aug 29, 2012, at 9:47 AM, Thomas Elsgaard <thomas....@gmail.com> wrote:

> Hi Joe
>
> There is also PHK's concept of "guru meditation" in the varnish http accelerator..
>
> http://www.version2.dk/blog/guru-meditation-9738
>
> Basically the idea is: the user cannot do anything about the error, so let it fail, but provide the transaction Id (xid) so the admin can can troubleshoot...

I did this in erlang. It is very easy. When the web server crashes on the message, you grab Trace = erlang:get_stacktrace(), and Now = erlang:now(). Then you generate a unique token: crypto:sha(term_to_binary({Trace, Now})) and you put that token to the user as well as in the crash log of the server.

Now any bug reported with a proper token just requires a grep on the logs to find the exact error the user had.

I think it took me 1-2 hours to write and test.

Erik Søe Sørensen

unread,
Sep 2, 2012, 3:25:33 AM9/2/12
to Jesper Louis Andersen, Erlang

We used a similar, though more lightweight and probably less thought-through version of this: use make_ref() and show the reference both to the user and in the logs.
(Compared to Jesper's approach, this has potential uniqueness issues, and gives less control over display form, unless you really work for it. On the other hand, Jesper's function technically has a uniqueness problem wrt. multiple nodes - so it'd make sense to add a node() component there.)

Reply all
Reply to author
Forward
0 new messages