Angular console like window - first directive
template: [
      '&lt;div class="console animated"&gt;',
      '&lt;div ng-repeat="event in events" ng-class="{\'error\': event.type == \'error\', \'log\': event.type == \'log\'}"&gt;',
      '{{event.data}}&lt;span ng-if="event.count&gt;1" class="count"&gt;{{event.count}}&lt;/span&gt;',
      '&lt;/div&gt;',
      '&lt;/div&gt;'
    ].join(''),


If you have a build step with a transpiler, or don't care about old browsers, consider using template strings instead. Template strings can multi-line, making it easy to build markup.

$rootScope.$on('Log', function(event, data) {


$rootScope is great for data relay. However, when an app grows, you will be caught in a tangle of events. You don't know who fired them, what they'll execute, their payload (unless you document them, which rarely happens). Plus, $rootScope is a global and we all know what happens to globals when they get polluted. Suggesting you use a service/factory instead. That way, it isn't global plus you have some form of control.

Also, instead of separate events, why not a single event. It seems like your logic already sorts itself out by the type property.

$scope.events[0] !== undefined


Looks like you're checking if the array contains something. It would be best expressed if you checked the array length property instead.

$scope.events.splice(0, 0, {
  type: 'log',
  data: "Log :: " + data,
  count: 1
});


There's array.unshift. It's like array.push but puts the new value at the start of the array.