doctype html html head title Source Route Result link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" script src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js" script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js" css: .call-level-1 {} .call-level-2 { margin-left: 50px } .call-level-3 { margin-left: 100px } .call-level-4 { margin-left: 150px } body(ng-app="SourceRoute" ng-controller="MainCtrl") nav.navbar.navbar-default.navbar-static-top .container .container-fluid .navbar-header a.navbar-brand(href="#" ng-click="::resetTraceFilter()") ALL ul.nav.navbar-nav li(ng-repeat="event in tpEvents" ng-class="{active: event == traceFilter.event}") a(href="#" ng-click="traceFilter.event = event" ng-bind="::event") ul.nav.navbar-nav.navbar-right li a(disabled) span Current Trace Count span.badge<(ng-bind="currentCounter()") .clearfix .container .trace-flow .row .left-info.col-sm-4(ng-if="false") .btn-group-vertical button.btn.btn-default(ng-repeat="klass in ::definedClasses" ng-click="traceFilter.defined_class = klass" style="height: 60px") span(ng-bind="klass.substring(0, 40)" popover="{{klass}}" popover-trigger="mouseenter" popover-placement="bottom") .traces.center-info.col-sm-12(ng-class="{{traceFilter.event}}") .trace.well.well-lg.call-level.call-level(ng-repeat="trace in traces | filter:traceFilter:true" ng-class="callLevelClass(trace)") .header(ng-click="showMoreDetail = !showMoreDetail") span(ng-bind="trace.defined_class") span | . mark.method-value(ng-bind="trace.method_id") / workaround for return_value is 'false' and return_value always to be string when existed div(ng-if="trace.hasOwnProperty('return_value')") span | => span<(ng-bind="trace.return_value.substring(0, 150)") .details(ng-if="showMoreDetail") .local-vars.well.well-sm(ng-if="trace.local_var" style="color: green; margin-bottom: 0") span Local Var .local-values(ng-repeat="(key, value) in trace.local_var") span<>(ng-bind="key") span<> | => / ? could inspect repaire it ? span<>(ng-bind="value | json") .ins-vars.well.well-sm(ng-if="trace.instance_var" style="color: blue; margin-bottom: 0") span Instance Var .ins-values(ng-repeat="(key, value) in trace.instance_var") span<>(ng-bind="key") span<> | => span<>(ng-bind="value | json") .path-value.well.well-sm(ng-if="trace.path") span Path div span<>(ng-bind="trace.path") span<>(ng-bind="trace.lineno") .right-info.col-sm-2 script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js" script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.2/ui-bootstrap-tpls.min.js" javascript: sourceRoute = angular.module('SourceRoute', ['ui.bootstrap']) sourceRoute.controller('MainCtrl', function($scope, $filter) { $scope.traces = angular.element("#trace-data").data('trace') $scope.tpEvents = angular.element("#trace-data").data('tp-events') $scope.traceFilter = {event: $scope.tpEvents[0]} if ($scope.tpEvents.length == 1 && angular.isUndefined($scope.traces[0].event)) { _.each($scope.traces, function(trace) { trace.event = $scope.tpEvents[0] }) } $scope.definedClasses = _.uniq(_.map($scope.traces, 'defined_class')) $scope.callLevelClass = function(trace) { if (trace.parent_length > 4) { return 'call-level-4' } else { return 'call-level-' + trace.parent_length } } $scope.resetTraceFilter = function() { $scope.traceFilter = {} } $scope.currentCounter = function() { return $filter('filter')($scope.traces, $scope.traceFilter, true).length } }) ruby: local_trace_data = @tp_result_chain.map do |tp_result| if tp_result.key?(:defined_class) tp_result[:defined_class] = tp_result[:defined_class].to_s tp_result[:return_value] = tp_result[:return_value].inspect if tp_result.key?(:return_value) end tp_result end .data-collect / dont use local_trace_data.to_json, because ActiveSupport override it and can introduce unexpected crash for some data #trace-data(data-trace="#{JSON.dump(local_trace_data)}" data-tp-events="#{JSON.dump(@condition.events)}")