{"id":352,"date":"2012-02-15T11:59:14","date_gmt":"2012-02-15T16:59:14","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=352"},"modified":"2016-08-23T09:49:31","modified_gmt":"2016-08-23T14:49:31","slug":"separating-errors-from-output-in-a-deployed-application","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2012\/02\/15\/separating-errors-from-output-in-a-deployed-application\/","title":{"rendered":"Separating Errors from Output in a Deployed Application"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>Guest blogger <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/4660\">Peter Webb<\/a> returns with another in an <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/\">occasional series<\/a> of postings about application deployment.\r\n      <\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">Errors are Different!<\/a><\/li>\r\n         <li><a href=\"#2\">A Brief Review of the Application<\/a><\/li>\r\n         <li><a href=\"#3\">Splitting the Error and Output Streams<\/a><\/li>\r\n         <li><a href=\"#4\">Emphasizing Error Messages<\/a><\/li>\r\n         <li><a href=\"#5\">Seeing the Differences<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>Errors are Different!<a name=\"1\"><\/a><\/h3>\r\n   <p>By default, standalone applications display both ordinary output and and errors via the same channel. This can be convenient,\r\n      as it makes capturing all the output relatively simple. With this simplicity comes a hidden danger: error messages may get\r\n      lost if the application prints out a lot of messages. In this final installment of my <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/\">series of posts<\/a> about redirecting program output, I'm going to show you how to treat <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/error.html\">errors<\/a> differently than other types of messages. One reason for doing so is to make error messages more obvious, so they are easier\r\n      to find. When I'm looking through a long listing of  program output, I'm often scanning primarily for error messages, because\r\n      errors indicate some intervention is necessary. I'd like the errors to be emphasized or decorated so I'll spot them quickly.\r\n   <\/p>\r\n   <p>Applications and shared libraries created by <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/br5w5e9-1.html\">MATLAB Compiler<\/a> split the output from <a href=\"https:\/\/www.mathworks.com\/products\/matlab\">MATLAB<\/a> <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/function.html\">functions<\/a>, into two <i>streams<\/i>, one for errors and one for all other types of output, including warnings. Since MATLAB Compiler-generated components allow\r\n      you to <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f2-998954.html#f2-1008529\">install a separate handler<\/a> for each of these streams, it is conceptually simple to emphasize error messages.\r\n   <\/p>\r\n   <h3>A Brief Review of the Application<a name=\"2\"><\/a><\/h3>\r\n   <p><tt>monitor<\/tt> is a C program that calls a single MATLAB function, <tt>sendmessages<\/tt>. The MATLAB function displays three kinds of output: some informational text, a warning message and an error message. <tt>monitor.c<\/tt> relies on three monitoring functions, <tt>StartMonitoring<\/tt>, <tt>MonitorHandler<\/tt> and <tt>StopMonitoring<\/tt>, to redirect its output to a user-visible window. Separate, platform-specific files contain different sets of monitoring\r\n      functions.\r\n   <\/p>\r\n   <p><a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/32598-liberating-deployed-application-output-from-the-console-window\">Download the source code<\/a> for the <tt>monitor<\/tt> program from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/\">MATLAB Central<\/a>. See the <tt>monitorREADME<\/tt> in the ZIP file for a description of each of the downloaded files and complete directions for building the application.\r\n   <\/p>\r\n   <h3>Splitting the Error and Output Streams<a name=\"3\"><\/a><\/h3>\r\n   <p>The generated library initialization function <tt>libmsgfcnInitializeWithHandlers<\/tt> takes two input arguments: an error message handler and a print message handler. The example <tt>monitor.c<\/tt> I discussed in last week's post installs the same handler, the function <tt>MonitorHandler<\/tt>, for both the <i>error<\/i> and the <i>print<\/i> output streams:\r\n   <\/p><pre> if (!libmsgfcnInitializeWithHandlers(MonitorHandler, MonitorHandler))<\/pre><p>Change the first parameter to a specialized error handler, the <tt>ErrorHandler<\/tt> function, and the <tt>monitor<\/tt> program decorates the error messages it displays, making them easier to see.\r\n   <\/p><pre> if (!libmsgfcnInitializeWithHandlers(ErrorHandler, MonitorHandler))<\/pre><h3>Emphasizing Error Messages<a name=\"4\"><\/a><\/h3>\r\n   <p>I've chosen to emphasize error messages in two different ways. On UNIX the monitor window displays error messages in red.\r\n      The UNIX <tt>ErrorHandler<\/tt> function uses X terminal <a href=\"http:\/\/www.frexx.de\/xterm-256-notes\/\">escape codes<\/a> to set the color of the displayed text. <tt>ErrorHandler<\/tt> sends the sequence <tt>ESC [ 1;31m<\/tt> to set the text to red, outputs the error message, and then restores the foreground color to black with the sequence <tt>ESC [ 1;30m<\/tt>.\r\n   <\/p><pre>int ErrorHandler(const char *s)\r\n{\r\n    const int csi = 0x9b;\r\n    const char *redOn = \"1;31m\";\r\n    const char *redOff = \"1;30m\";<\/pre><pre>    time_t now = time(NULL);\r\n    char nowIsTheHour[128];\r\n    fwrite(&amp;csi, sizeof(int), 1, tmpLog);\r\n    fprintf(tmpLog, \"%s\", redOn);\r\n    sprintf(nowIsTheHour, \"%s\", ctime(&amp;now));\r\n    fprintf(tmpLog, nowIsTheHour);\r\n    fprintf(tmpLog, \"%s\\n\", s);\r\n    fwrite(&amp;csi, sizeof(int), 1, tmpLog);\r\n    fprintf(tmpLog, \"%s\", redOff);\r\n    return strlen(s)+strlen(nowIsTheHour)+1;\r\n}<\/pre><p>The UNIX monitoring mechanism sends its output to a temporary file, the contents of which are displayed in an X terminal running\r\n      <tt>tail -f<\/tt>. Refer to the <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=320\">previous post<\/a> in this series for complete details of the implementation.\r\n   <\/p>\r\n   <p>The monitoring mechanism in the Windows program <tt>monitorWinDialog<\/tt> uses a dialog box containing a <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/bb775146(VS.85).aspx\"><tt>ListBox<\/tt><\/a>. The <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms645469(VS.85).aspx\"><tt>DialogProc<\/tt><\/a> function (the function that handles events directed at the dialog box), prefixes a line of five asterixes to error messages\r\n      before displaying them:\r\n   <\/p><pre>case ERROR_MESSAGE:\r\n    strcpy(buffer, \"***** \");\r\n    strcat(buffer, (const char *)lParam);\r\n    ListBox_AddString(GetDlgItem(box, IDC_LIST1),\r\n                      (const char *)buffer);\r\n    break;<\/pre><p>The error handler function <tt>ErrorHandler<\/tt> in the <a title=\"http:\/\/support.microsoft.com\/kb\/308427 (link no longer works)\">Microsoft Windows event log<\/a> version, <tt>monitorWinEvents<\/tt> calls <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa363679%28VS.85%29.aspx\"><tt>ReportEvent<\/tt><\/a> with an event type of <tt>EVENTLOG_ERROR_TYPE<\/tt>.\r\n   <\/p><pre>if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, EXAMPLE_CATEGORY,\r\n                 INFORMATIONAL_MESSAGE, NULL, 1, 0,\r\n                 (LPCSTR*)pInsertStrings, NULL))<\/pre><p>In response, the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Event_Viewer\">event log viewer<\/a> displays a stop-sign icon next to the event. The print handler <tt>MonitorHandler<\/tt> creates events with an event type of <tt>EVENTLOG_INFORMATION_TYPE<\/tt>, causing the event logger to display a \"talk bubble\" icon next to the event.\r\n   <\/p>\r\n   <h3>Seeing the Differences<a name=\"5\"><\/a><\/h3>\r\n   <p>Once you've changed <tt>monitor.c<\/tt> to install separate handlers on the error and print message streams, build and run the application.\r\n   <\/p>\r\n   <p>First use MATLAB Compiler to create the shared library containing <tt>sendmessages<\/tt>:\r\n   <\/p><pre>&gt;&gt; mcc -W lib:libmsgfcn -T link:lib sendmessages.m<\/pre><p>Then, use <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/mbuild.html\"><tt>mbuild<\/tt><\/a> to build the main program and link it with the shared library:\r\n   <\/p>\r\n   <p>(UNIX): <tt>mbuild -g monitor.c monitorUNIX.c -L. -lmsgfcn<\/tt><\/p>\r\n   <p>(Windows) -- two commands because there are two programs:<\/p><pre>mbuild -g monitorWinDialog.c monitor.c WinLogger.rc libmsgfcn.lib<\/pre><pre>mbuild -g monitorWinEvents.c monitor.c libmsgfcn.lib<\/pre><p>The first command builds the dialog box version (<tt>monitorWinDialog.exe<\/tt>) and the second command builds the event log version (<tt>monitorWinEvents.exe<\/tt>).\r\n   <\/p>\r\n   <p>Now run it. The program takes three input arguments: the informational message, the warning and the error message.<\/p>\r\n   <p>(UNIX):    <tt>.\/monitor information \"look out!\" oops<\/tt><\/p>\r\n   <p>(Windows): <tt>monitorWinDialog.exe information \"look out!\" oops<\/tt><\/p>\r\n   <p>It should be easy to pick out the error message in the program output.<\/p>\r\n   <p>That's all I've got to say about managing errors and output in a deployed application. Do your applications do things differently?\r\n      Are any of these ideas going to be useful to you? What would you like to see the Compiler do differently? <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=352#respond\">Let me know<\/a>.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_1036c44880d64e4aa4d72a1ca620200b() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='1036c44880d64e4aa4d72a1ca620200b ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 1036c44880d64e4aa4d72a1ca620200b';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Peter Webb';\r\n        copyright = 'Copyright 2012 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_1036c44880d64e4aa4d72a1ca620200b()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.13<br><\/p>\r\n<\/div>\r\n<!--\r\n1036c44880d64e4aa4d72a1ca620200b ##### SOURCE BEGIN #####\r\n%% Separating Errors from Output in a Deployed Application\r\n% Guest blogger \r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/4660 Peter Webb>\r\n% returns with another in an \r\n% <https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/ occasional series>\r\n% of postings about application deployment. \r\n%% Errors are Different!\r\n% By default, standalone applications display both ordinary output and \r\n% and errors via the same channel. This can be convenient, as it makes\r\n% capturing all the output relatively simple. With this simplicity comes a\r\n% hidden danger: error messages may get lost if the application prints out\r\n% a lot of messages. In this final installment of my \r\n% <https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/ series of posts>\r\n% about redirecting program output, I'm going to show you how to treat \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/error.html errors> differently\r\n% than other types of messages. One reason for doing so is to make error\r\n% messages more obvious, so they are easier to find. When I'm looking \r\n% through a long listing of  program output, I'm often scanning primarily\r\n% for error messages, because errors indicate some intervention is necessary. \r\n% I'd like the errors to be emphasized or decorated so I'll spot them\r\n% quickly.\r\n%\r\n% Applications and shared libraries created by \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/br5w5e9-1.html \r\n% MATLAB Compiler> split the\r\n% output from\r\n% <https:\/\/www.mathworks.com\/products\/matlab MATLAB>\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/function.html functions>,\r\n% into two _streams_, one for errors and one\r\n% for all other types of output, including warnings. Since MATLAB \r\n% Compiler-generated components allow you to \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/f2-998954.html#f2-1008529 \r\n% install a separate handler> for\r\n% each of these streams, it is conceptually simple to emphasize error\r\n% messages.\r\n%\r\n%% A Brief Review of the Application\r\n% |monitor| is a C program that calls a single MATLAB function,\r\n% |sendmessages|. The MATLAB function displays three kinds of output: some\r\n% informational text, a warning message and an error message. |monitor.c|\r\n% relies on three monitoring functions, |StartMonitoring|, |MonitorHandler|\r\n% and |StopMonitoring|, to redirect its output to a user-visible window.\r\n% Separate, platform-specific files contain different sets of monitoring\r\n% functions. \r\n%\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/32598-liberating-deployed-application-output-from-the-console-window \r\n% Download the source code> for the |monitor| program \r\n% from <https:\/\/www.mathworks.com\/matlabcentral\/ MATLAB Central>. See the\r\n% |monitorREADME| in the ZIP file for a description of each of the downloaded \r\n% files and complete directions for building the application.\r\n%\r\n%% Splitting the Error and Output Streams\r\n% The generated library initialization function\r\n% |libmsgfcnInitializeWithHandlers| takes two input arguments: an error\r\n% message handler and a print message handler. The example |monitor.c| I\r\n% discussed in last week's post installs the same handler, the function\r\n% |MonitorHandler|, for both the _error_ and the _print_ output streams:\r\n%\r\n%   if (!libmsgfcnInitializeWithHandlers(MonitorHandler, MonitorHandler)) \r\n%\r\n% Change the first parameter to a specialized error handler, the\r\n% |ErrorHandler| function, and the |monitor| program decorates the error\r\n% messages it displays, making them easier to see.\r\n% \r\n%   if (!libmsgfcnInitializeWithHandlers(ErrorHandler, MonitorHandler)) \r\n%\r\n%% Emphasizing Error Messages\r\n% I've chosen to emphasize error messages in two different ways. On UNIX \r\n% the monitor window displays error messages in red. The UNIX\r\n% |ErrorHandler| function uses X terminal \r\n% <http:\/\/www.frexx.de\/xterm-256-notes\/ escape codes> to set the color of\r\n% the displayed text. |ErrorHandler| sends the sequence |ESC [ 1;31m| \r\n% to set the text to red, outputs the error message, and then restores \r\n% the foreground color to black with the sequence |ESC [ 1;30m|. \r\n%\r\n%  int ErrorHandler(const char *s)\r\n%  {\r\n%      const int csi = 0x9b;\r\n%      const char *redOn = \"1;31m\";\r\n%      const char *redOff = \"1;30m\";\r\n%  \r\n%      time_t now = time(NULL);\r\n%      char nowIsTheHour[128];\r\n%      fwrite(&csi, sizeof(int), 1, tmpLog);\r\n%      fprintf(tmpLog, \"%s\", redOn);\r\n%      sprintf(nowIsTheHour, \"%s\", ctime(&now));\r\n%      fprintf(tmpLog, nowIsTheHour);\r\n%      fprintf(tmpLog, \"%s\\n\", s);\r\n%      fwrite(&csi, sizeof(int), 1, tmpLog);\r\n%      fprintf(tmpLog, \"%s\", redOff);\r\n%      return strlen(s)+strlen(nowIsTheHour)+1;\r\n%  }\r\n%\r\n% The UNIX monitoring mechanism sends its output to a temporary file, the\r\n% contents of which are displayed in an X terminal running |tail -f|.\r\n% Refer to the \r\n% <http:\/\/blogs\/mathworks.com\/loren\/?p=320 previous post>\r\n% in this series for complete details of the\r\n% implementation.\r\n%\r\n% The monitoring mechanism in the Windows program |monitorWinDialog| \r\n% uses a dialog box containing a \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/bb775146%28VS.85%29.aspx\r\n% |ListBox|>. The \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/ms645469%28VS.85%29.aspx |DialogProc|>\r\n% function (the function that handles events directed at the dialog box),\r\n% prefixes a line of five asterixes to error messages before displaying \r\n% them: \r\n%\r\n%  case ERROR_MESSAGE:\r\n%      strcpy(buffer, \"***** \");\r\n%      strcat(buffer, (const char *)lParam);\r\n%      ListBox_AddString(GetDlgItem(box, IDC_LIST1), \r\n%                        (const char *)buffer);\r\n%      break;\r\n%\r\n% The error handler function |ErrorHandler| in the \r\n% <http:\/\/support.microsoft.com\/kb\/308427 Microsoft Windows event log>\r\n% version, |monitorWinEvents| calls \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/aa363679%28VS.85%29.aspx \r\n% |ReportEvent|> with an event type of |EVENTLOG_ERROR_TYPE|.\r\n%\r\n%  if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, EXAMPLE_CATEGORY, \r\n%                   INFORMATIONAL_MESSAGE, NULL, 1, 0, \r\n%                   (LPCSTR*)pInsertStrings, NULL))\r\n%\r\n% In response, the \r\n% <http:\/\/en.wikipedia.org\/wiki\/Event_Viewer event log viewer>\r\n% displays a stop-sign icon next to \r\n% the event. The print handler |MonitorHandler| creates events with an\r\n% event type of |EVENTLOG_INFORMATION_TYPE|, causing the event logger to\r\n% display a \"talk bubble\" icon next to the event. \r\n%\r\n%% Seeing the Differences\r\n% Once you've changed |monitor.c| to install separate handlers on the error\r\n% and print message streams, build and run the application.\r\n%\r\n% First use MATLAB Compiler to create the shared library containing \r\n% |sendmessages|:\r\n%\r\n%  >> mcc -W lib:libmsgfcn -T link:lib sendmessages.m\r\n%\r\n% Then, use \r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/compiler\/mbuild.html \r\n% |mbuild|> to build the main program and link it with the \r\n% shared library:\r\n%\r\n% (UNIX): |mbuild -g monitor.c monitorUNIX.c -L. -lmsgfcn|\r\n%\r\n% (Windows) REPLACE_WITH_DASH_DASH two commands because there are two programs: \r\n%\r\n%  mbuild -g monitorWinDialog.c monitor.c WinLogger.rc libmsgfcn.lib\r\n%\r\n%  mbuild -g monitorWinEvents.c monitor.c libmsgfcn.lib\r\n%\r\n% The first command builds the dialog box version (|monitorWinDialog.exe|)\r\n% and the second command builds the event log version \r\n% (|monitorWinEvents.exe|).\r\n% \r\n% Now run it. The program takes three input arguments: the informational\r\n% message, the warning and the error message.\r\n%\r\n% (UNIX):    |.\/monitor information \"look out!\" oops|\r\n%\r\n% (Windows): |monitorWinDialog.exe information \"look out!\" oops|\r\n%\r\n% It should be easy to pick out the error message in the program output.\r\n%\r\n% That's all I've got to say about managing errors and output in a deployed\r\n% application. Do your applications do things differently? Are any of these\r\n% ideas going to be useful to you? What would you like to see the Compiler\r\n% do differently? <http:\/\/blogs\/mathworks.com\/loren\/?p=352#respond Let me\r\n% know>.\r\n\r\n\r\n##### SOURCE END ##### 1036c44880d64e4aa4d72a1ca620200b\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment.\r\n      \r\n   \r\n   Contents\r\n   \r\n      \r\n   ... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2012\/02\/15\/separating-errors-from-output-in-a-deployed-application\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[24],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/352"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=352"}],"version-history":[{"count":12,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/352\/revisions"}],"predecessor-version":[{"id":2018,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/352\/revisions\/2018"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=352"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=352"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=352"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}