# Displaying Colored Logs with Search Highlighting in Angular 6

In many applications, logging plays an essential role in debugging and monitoring. A well-formatted, readable log view can significantly improve the user experience for developers and system administrators. In this article, we'll explore how to display logs in a colored, formatted manner within an Angular 6 project. We’ll also implement functionality to highlight specific search terms within the logs.

We will achieve this using Prism.js for syntax highlighting and Angular's built-in features such as data binding, DOM sanitization, and more.

#### 1. Project Setup

Before we dive into the code, let's make sure we have everything set up correctly. We'll need to install the Prism.js dependency for syntax highlighting, along with its language-specific components.

```bash
npm install prismjs
```

In your component, import Prism.js and the necessary components:

```typescript
import * as Prism from 'prismjs';
import 'prismjs/components/prism-log'; // Prism's Log language
import 'prismjs/prism';
```

#### 2. Component HTML Template

We’ll create a simple HTML structure to display the logs. Using Angular’s `*ngIf` directive, we'll conditionally render the logs if they are available, and wrap them in a `<pre>` tag to preserve the formatting.

```html
<div *ngIf="logsByLine && logsByLine.length > 0" style="height: 80vh;">
  <pre class="language-log w-100 scroll" style="height: 100%; overflow-y: auto;">
    <code [ngClass]="{'white-space-pre-wrap': isTextWrapped}" 
          class="language-log" 
          [innerHTML]="getHighlightedContent()"></code>
  </pre>
</div>
```

* The `*ngIf` ensures the logs are only displayed when there is data to show.
* We apply syntax highlighting by using the `language-log` class and leverage Prism.js to handle the syntax highlighting.
* The `getHighlightedContent()` method will generate the highlighted log content dynamically.

We also add a search input field that allows users to filter logs based on a keyword. This will allow us to highlight specific search terms within the logs.

```html
<div class="col-md-4">
  <input type="text" style="margin-top: 2rem;" 
         class="form-control" name="searchTerm" 
         placeholder="Filter logs" [(ngModel)]="searchTerm">
</div>
```

#### 3. Component TypeScript Logic

In the TypeScript file, we have several functions to handle log parsing, syntax highlighting, and searching.

**Handling Logs**

```typescript
showLogs() {
  const lines: number = Number(this.numOfLines);
  if (isNaN(lines)) {
    this.jhiAlertService.error('Invalid input: Number of lines must be a valid number', null, null);
    return;
  }
  this.logsByLine = '';
  this.metricsService.showLogs(lines).subscribe((res: any) => {
    this.logsByLine = res.join('\n');
    this.callLogsTimeInterval();
  });
}
```

The `showLogs()` function fetches logs and stores them in the `logsByLine` variable. Once the logs are fetched, we call `callLogsTimeInterval()` to handle any periodic updates (optional).

**Highlighting Log Content**

```typescript
getHighlightedContent() {
  if (!this.logsByLine) return '';
  
  let highlighted = Prism.highlight(this.logsByLine, Prism.languages.log, 'log');
  
  // Highlight ERROR lines with a special background
  highlighted = highlighted.split('\n').map(line => {
    if (line.includes('ERROR')) {
      return `<div class="log-line error">${line}</div>`;
    }
    return `<div class="log-line">${line}</div>`;
  }).join('');
  
  // Highlight the search term if provided
  if (this.searchTerm) {
    const regex = new RegExp(this.searchTerm, 'gi');
    highlighted = highlighted.replace(regex, match => `<mark>${match}</mark>`);
  }

  return this.sanitizer.bypassSecurityTrustHtml(highlighted);
}
```

The `getHighlightedContent()` method does the following:

1. Uses Prism.js to highlight the logs.
2. Applies a background color to log lines that contain the keyword `ERROR`.
3. Highlights any search terms that match the user's input. This is done using a regular expression to replace matching terms with a `<mark>` HTML tag, which we can style further.

**Handling Search Term Change**

```typescript
onSearchTermChange(searchTerm: string) {
  this.searchTerm = searchTerm;
}
```

Whenever the search term changes (due to user input in the search field), this method updates the `searchTerm` variable.

#### 4. View Encapsulation and Sanitization

To ensure that our component styles don’t interfere with other components in the application, we use **ViewEncapsulation.None**. This allows the styles defined in the component to be global. Additionally, we use Angular’s `DomSanitizer` to securely bypass Angular’s built-in sanitization for HTML content, which is required when injecting dynamic content into the DOM.

```typescript
encapsulation: ViewEncapsulation.None, // Disable encapsulation for global styles

highlightedLogs: SafeHtml; // Holds the highlighted log content

searchTerm: string = ''; // Stores the search term entered by the user
logsTimeInterval: any; // Optional time interval for periodic log fetching

private sanitizer: DomSanitizer; // Ensures that dynamically injected HTML is safe
```

* **ViewEncapsulation.None**: Disables view encapsulation, which allows the styles to leak outside the component. This is useful for global styles like syntax highlighting.
* **SafeHtml**: The type of `highlightedLogs`, ensuring that HTML content injected dynamically into the DOM is safe.
* **DomSanitizer**: This service is used to bypass Angular’s built-in sanitization when working with dynamic HTML content to prevent potential security issues (e.g., XSS attacks).

#### 5. Component Styles (SCSS)

Now, let’s add some styles to make the log display more readable.

```scss
.card { margin-bottom: 1rem; }
.card-header { background-color: #f8f9fa; font-weight: bold; }
.alert { padding: 0.5rem 1rem; }
.btn-primary { min-width: 120px; }
.fa-sync-alt { margin-right: 8px; }
.fa-spin { animation: fa-spin 2s infinite linear; }

@keyframes fa-spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.gap-top { margin-top: 5rem; }

.white-space-pre-wrap { white-space: pre-wrap !important; }

mark { 
  background-color: rgb(244, 244, 112) !important; 
  color: black;
}

.log-line { line-height: 1.5; }

.log-line.error { 
  background-color: rgba(255, 0, 0, 0.1); 
}

.token.level { font-weight: bold; }
.token.level.info { color: #61afef; }
.token.level.error { color: #e06c75; }
.token.level.warn { color: #e5c07b; }
.token.level.debug { color: #98c379; }

code[class="language-"], pre[class*="language-"] { 
  color: #ccc;
  background: none;
  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  font-size: 1em;
  text-align: left;
  white-space: pre;
  word-spacing: normal;
  word-break: normal;
  line-height: 1.5;
  tab-size: 4;
  hyphens: none;
}
```

In this SCSS:

* `.log-line.error` styles the lines with the `ERROR` keyword, giving them a red background.
* `.white-space-pre-wrap` ensures that long lines of text wrap properly.
* We customize the appearance of highlighted code using `.token.level` classes, adding distinct colors for different log levels like `info`, `error`, `warn`, and `debug`.

#### 6. Conclusion

By integrating Prism.js with Angular 6, we can create a powerful, visually appealing log viewer that highlights important log entries (like errors) and allows the user to search through logs effectively. The flexibility of this approach allows you to extend it further with features like pagination, more sophisticated search functionality, and real-time log updates.

This solution combines Angular's reactive features with Prism.js for clean, readable log display and enhanced functionality. You can use it in your Angular 6 projects and even customize it to fit the specific needs of your logging system.

**Key Features:**

* **ViewEncapsulation.None** for global styling.
* **SafeHtml** and **DomSanitizer** for secure dynamic HTML content injection.
* Real-time search highlighting and syntax highlighting using Prism.js.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wisdom.gitbook.io/gyan/angular/displaying-colored-logs-with-search-highlighting-in-angular-6.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
