문제

I'm using mongodb to store application error logs as json documents. I want to be able to format the error logs as HTML rather than returning the plain json to the browser. The logs are properly schemaless - they could change at any time, so it's no use trying to do this (in Jade):

    - var items = jsonResults

    - each item in items
        h3 Server alias: #{item.ServerAlias}
        p UUID: #{item.UUID}
        p Stack trace: #{item.StackTrace}
            h3 Session: #{item.Session}
            p URL token: #{item.Session.UrlToken}
            p Session messages: #{item.Session.SessionMessages}

as I don't know what's actually going to be in the JSON structure ahead of time. What I want is surely possible, though? Everything I'm reading says that the schema isn't enforced by the database but that your view code will outline your schema anyway - but we've got hundreds of possible fields that could be removed or added at any time so managing the views in this way is fairly unmanageable.

What am I missing? Am I making the wrong assumptions about the technology? Going at this the wrong way?


Edited with extra info following comments:

The json docs look something like this

{
   "ServerAlias":"GBIZ-WEB",
   "Session":{
      "urltoken":"CFID=10989&CFTOKEN=f07fe950-53926E3B-F33A-093D-3FCEFB&jsessionid=84303d29a229d1",
      "captcha":{

      },
      "sessionmessages":{

      },
      "sessionid":"84197a667053f63433672873j377e7d379101"
   },
   "UUID":"53934LBB-DB8F-79T6-C03937JD84HB864A338",
   "Template":"\/home\/vagrant\/dev\/websites\/g-bis\/code\/webroot\/page\/home\/home.cfm, line 3",
   "Error":{
      "GeneratedContent":"",
      "Mailto":"",
      "RootCause":{
         "Message":"Unknown tag: cfincflude.",
         "tagName":"cfincflude",
         "TagContext":[
            {
               "RAW_TRACE":"\tat cfhome2ecfm1296628853.runPage(\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/home\/home.cfm:3)",
               "ID":"CFINCLUDE",
               "TEMPLATE":"\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/home\/home.cfm",
               "LINE":3,
               "TYPE":"CFML",
               "COLUMN":0
            },
            {
               "RAW_TRACE":"\tat cfdisplay2ecfm1093821753.runPage(\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/display.cfm:6)",
               "ID":"CFINCLUDE",
               "TEMPLATE":"\/home\/vagrant\/dev\/websites\/nig-bis\/code\/webroot\/page\/display.cfm",
               "LINE":6,
               "TYPE":"CFML",
               "COLUMN":0
            }
         ]
       }
   }

... etc, but is likely to change depending on what the individual project that generates the log is configured to trigger.

What I want to end up with is a formatted HTML page with headers for each parent and the children listed below, iterating right through the data structure. The Jade sample above is effectively what we need to output, but without hard-coding that in the view.

Mike's analysis in the comments of the problem being that of creating a table-like structure from a bunch of collections that haven't really got a lot in common is bang-on. The data is relational, but only within individual documents - so hard-coding the schema into anything is virtually impossible as it requires you to know what the data structure looks like first.

도움이 되었습니까?

해결책

The basic idea is what @Gates VP described. I use underscore.js to iterate through the arrays/objects.

function formatLog(obj){
  var log = "";
  _.each(obj, function(val, key){ 
    if(typeof(val) === "object" || typeof(val) === "array"){
      // if we have a new list
      log += "<ul>";
      log += formatLog(val);
      log += "</ul>";
    }
    else{
      // if we are at an endpoint
      log += "<li>";
      log += (key + ": " + val);
      log += "</li>";
    }
  });
  return log;
}

If you call formatLog()on the example data you gave it returns

  • ServerAlias: GBIZ-WEB
    • urltoken: CFID=10989&CFTOKEN=f07fe950-53926E3B-F33A-093D-3FCEFB&jsessionid=84303d29a229d1
        • sessionid: 84197a667053f63433672873j377e7d379101
      • UUID: 53934LBB-DB8F-79T6-C03937JD84HB864A338
      • Template: /home/vagrant/dev/websites/g-bis/code/webroot/page/home/home.cfm, line 3
        • GeneratedContent:
        • Mailto:
          • Message: Unknown tag: cfincflude.
          • tagName: cfincflude
              • RAW_TRACE: at cfhome2ecfm1296628853.runPage(/home/vagrant/dev/websites/nig-bis/code/webroot/page/home/home.cfm:3)
              • ID: CFINCLUDE
              • TEMPLATE: /home/vagrant/dev/websites/nig-bis/code/webroot/page/home/home.cfm
              • LINE: 3
              • TYPE: CFML
              • COLUMN: 0
              • RAW_TRACE: at cfdisplay2ecfm1093821753.runPage(/home/vagrant/dev/websites/nig-bis/code/webroot/page/display.cfm:6)
              • ID: CFINCLUDE
              • TEMPLATE: /home/vagrant/dev/websites/nig-bis/code/webroot/page/display.cfm
              • LINE: 6
              • TYPE: CFML
              • COLUMN: 0

      How to format it then is up to you.

      다른 팁

      This is basically a recursive for loop.

      To do this with Jade you will need to use mixins so that you can print nested objects by calling the mixin with a deeper level of indentation.

      Note that this whole thing is a little ugly as you won't get guaranteed ordering of fields and you may have to implement some logic to differentiate looping on arrays vs. looping on JSON objects.

      You can try util.inspect. In your template:

      pre
        = util.inspect(jsonResults)
      
      라이센스 : CC-BY-SA ~와 함께 속성
      제휴하지 않습니다 StackOverflow
      scroll top