diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 6506b6c3a5257818341fca6d2484cd62713af465..69328bd5fe0b0e395432d09c6de258b8009581d0 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -83,6 +83,7 @@ import { DialogEditParamComputedComponent } from "./components/dialog-edit-param
 import { DialogEditParamValuesComponent } from "./components/dialog-edit-param-values/dialog-edit-param-values.component";
 import { DialogGeneratePABComponent } from "./components/dialog-generate-pab/dialog-generate-pab.component";
 import { DialogLoadSessionComponent } from "./components/dialog-load-session/dialog-load-session.component";
+import { DialogLogEntriesDetailsComponent } from "./components/dialog-log-entries-details/dialog-log-entries-details.component";
 import { DialogSaveSessionComponent } from "./components/dialog-save-session/dialog-save-session.component";
 
 import { JalhydAsyncModelValidationDirective } from "./directives/jalhyd-async-model-validation.directive";
@@ -154,6 +155,7 @@ const appRoutes: Routes = [
     DialogEditParamValuesComponent,
     DialogGeneratePABComponent,
     DialogLoadSessionComponent,
+    DialogLogEntriesDetailsComponent,
     DialogSaveSessionComponent,
     FieldSetComponent,
     FieldsetContainerComponent,
@@ -193,7 +195,8 @@ const appRoutes: Routes = [
     DialogEditParamValuesComponent,
     DialogGeneratePABComponent,
     DialogSaveSessionComponent,
-    DialogLoadSessionComponent
+    DialogLoadSessionComponent,
+    DialogLogEntriesDetailsComponent
   ],
   providers: [ // services
     ApplicationSetupService,
diff --git a/src/app/components/dialog-log-entries-details/dialog-log-entries-details.component.html b/src/app/components/dialog-log-entries-details/dialog-log-entries-details.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..ef999517ca0d7675b13b92ec6901b3dac51f2805
--- /dev/null
+++ b/src/app/components/dialog-log-entries-details/dialog-log-entries-details.component.html
@@ -0,0 +1,10 @@
+<h1 mat-dialog-title [innerHTML]="uitextLogEntriesDetailsTitle"></h1>
+<div mat-dialog-content>
+    <!-- entrées du journal -->
+    <log-entry *ngFor="let m of data.messages" [_message]="m"></log-entry>
+</div>
+<div mat-dialog-actions>
+  <button mat-raised-button [mat-dialog-close]="true">
+    {{ uitextClose }}
+  </button>
+</div>
diff --git a/src/app/components/dialog-log-entries-details/dialog-log-entries-details.component.ts b/src/app/components/dialog-log-entries-details/dialog-log-entries-details.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d1bf57c65b854c9ce867ab62528a135d4a6bc9a0
--- /dev/null
+++ b/src/app/components/dialog-log-entries-details/dialog-log-entries-details.component.ts
@@ -0,0 +1,24 @@
+import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";
+import { Inject, Component } from "@angular/core";
+import { I18nService } from "../../services/internationalisation/internationalisation.service";
+
+@Component({
+    selector: "dialog-log-entries-details",
+    templateUrl: "dialog-log-entries-details.component.html",
+})
+export class DialogLogEntriesDetailsComponent {
+
+    constructor(
+        public dialogRef: MatDialogRef<DialogLogEntriesDetailsComponent>,
+        private intlService: I18nService,
+        @Inject(MAT_DIALOG_DATA) public data: any
+    ) { }
+
+    public get uitextLogEntriesDetailsTitle() {
+      return this.intlService.localizeText("INFO_TITREJOURNAL");
+    }
+
+    public get uitextClose() {
+      return this.intlService.localizeText("INFO_OPTION_CLOSE");
+    }
+}
diff --git a/src/app/components/fixedvar-results/fixedvar-results.component.ts b/src/app/components/fixedvar-results/fixedvar-results.component.ts
index ca402293f108bfda22d83e7a75ea6aee5381828d..8beb3a78d380a6ed772cc4496b06b81c70ae3c38 100644
--- a/src/app/components/fixedvar-results/fixedvar-results.component.ts
+++ b/src/app/components/fixedvar-results/fixedvar-results.component.ts
@@ -111,10 +111,6 @@ export class FixedVarResultsComponent implements DoCheck {
         if (this._fixedResults) {
             this.mergeLog(this._fixedResults.result, res);
         }
-
-        if (this._varResults) {
-            this.mergeLog(this._varResults.result, res);
-        }
         return res;
     }
 
diff --git a/src/app/components/fixedvar-results/var-results.component.html b/src/app/components/fixedvar-results/var-results.component.html
index e7bbd993fc9ca551f693db5de401dc47d5430af8..252c579fca9fb572ef196ba433af7e4c00b31daa 100644
--- a/src/app/components/fixedvar-results/var-results.component.html
+++ b/src/app/components/fixedvar-results/var-results.component.html
@@ -17,9 +17,24 @@
             <div class="var-results-inner-container" #tableContainer>
 
                 <table mat-table [dataSource]="dataSet">
-                    <ng-container *ngFor="let h of headers; let i = index" [matColumnDef]="h">
+                    <!-- log messages column -->
+                    <ng-container *ngIf="hasMessages" matColumnDef="logMessagesColumn">
+                        <mat-header-cell *matHeaderCellDef>
+                            <mat-icon>info</mat-icon>
+                        </mat-header-cell>
+                        <mat-cell *matCellDef="let element">
+                            <span *ngIf="element[0].messages.length > 0" class="log-messages-column"
+                                (click)="openLogDetails(element[0].messages)">
+                                <mat-icon *ngIf="element[0].isInfo" style="color:green">check_circle</mat-icon>
+                                <mat-icon *ngIf="element[0].isWarning" style="color:orange">error_outline</mat-icon>
+                                <mat-icon *ngIf="element[0].isError" style="color:red">warning</mat-icon>
+                            </span>
+                        </mat-cell>
+                    </ng-container>
+                    <!-- generic column -->
+                    <ng-container *ngFor="let h of headersWithoutLogColumn; let i = index" [matColumnDef]="h">
                         <th mat-header-cell *matHeaderCellDef>{{ h }}</th>
-                        <td mat-cell *matCellDef="let element">{{ element[i] }}</td>
+                        <td mat-cell *matCellDef="let element">{{ element[i+1] }}</td>
                     </ng-container>
 
                     <tr mat-header-row *matHeaderRowDef="headers"></tr>
diff --git a/src/app/components/fixedvar-results/var-results.component.scss b/src/app/components/fixedvar-results/var-results.component.scss
index 12d1148fcf6f0adc02c335a3d2dc0b5b016d03b8..d897f54841d63ad93bc8847f6263ffb15c22fd9c 100644
--- a/src/app/components/fixedvar-results/var-results.component.scss
+++ b/src/app/components/fixedvar-results/var-results.component.scss
@@ -46,6 +46,10 @@ table.mat-table {
         &:nth-child(odd) {
             background-color: #f4f4f4;
         }
+
+        .log-messages-column {
+            cursor: pointer;
+        }
     }
 
     ::ng-deep .mat-cell {
@@ -56,5 +60,10 @@ table.mat-table {
         font-size: 1em;
         color: black;
         padding: 5px;
+        border: none;
+    }
+
+    ::ng-deep .mat-cell {
+        border: none;
     }
 }
diff --git a/src/app/components/fixedvar-results/var-results.component.ts b/src/app/components/fixedvar-results/var-results.component.ts
index f737e1d4c03120fa6833e76c3dd0eb8ed21093d8..a58eb8ea78d1ec086e3f4d46c860ece511256c4b 100644
--- a/src/app/components/fixedvar-results/var-results.component.ts
+++ b/src/app/components/fixedvar-results/var-results.component.ts
@@ -1,10 +1,14 @@
 import { Component, ViewChild, ElementRef } from "@angular/core";
+
+import { MatDialog } from "@angular/material";
+
 import { VarResults } from "../../results/var-results";
 import { ApplicationSetupService } from "../../services/app-setup/app-setup.service";
-import { ResultElement } from "jalhyd";
+import { ResultElement, Message, MessageSeverity } from "jalhyd";
 import { I18nService } from "../../services/internationalisation/internationalisation.service";
 import * as XLSX from "xlsx";
 import { ResultsComponent } from "./results.component";
+import { DialogLogEntriesDetailsComponent } from '../dialog-log-entries-details/dialog-log-entries-details.component';
 
 @Component({
     selector: "var-results",
@@ -27,11 +31,15 @@ export class VarResultsComponent extends ResultsComponent {
     /** entêtes des colonnes (param à varier, à calculer + extraResults) */
     protected _headers: string[];
 
+    /** messages de log issus des résultats variés */
+    protected _messages: Message[];
+
     @ViewChild("tableContainer") table: ElementRef;
 
     constructor(
         protected appSetupService: ApplicationSetupService,
-        protected intlService: I18nService
+        protected intlService: I18nService,
+        protected logEntriesDetailsDialog: MatDialog
     ) {
         super();
     }
@@ -41,11 +49,20 @@ export class VarResultsComponent extends ResultsComponent {
         this._varResults = r;
         this._results = [];
         this._headers = [];
+        this._messages = [];
 
         const nDigits = this.appSetupService.displayDigits;
 
         if (this._varResults) {
-            // A. build headers
+            // A. gather messages
+            for (const re of this._varResults.resultElements) {
+                this._messages = this._messages.concat(re.log.messages); // es6 concat;
+            }
+
+            // B. build headers
+            if (this._messages.length > 0) { // has log messages
+                this._headers.push("logMessagesColumn");
+            }
             for (let i = 0; i < this._varResults.variatedParameters.length; i++) {
                 this._headers.push(this._varResults.variableParamHeaders[i]);
             }
@@ -54,7 +71,7 @@ export class VarResultsComponent extends ResultsComponent {
             }
             this._headers = this._headers.concat(this._varResults.extraResultHeaders);
 
-            // B. pre-extract variable parameters valueslet longest = 0;
+            // C. pre-extract variable parameters valueslet longest = 0;
             const varValues = [];
             // find longest list
             this.size = 0;
@@ -75,13 +92,32 @@ export class VarResultsComponent extends ResultsComponent {
                 varValues.push(vv);
             }
 
-            // C. build dataset
+            // D. build dataset
             for (let i = 0; i < this._varResults.resultElements.length; i++) {
                 const re: ResultElement = this._varResults.resultElements[i];
                 if (re) {
                     // build ordered list of : variable params values; result; extra results
                     const list = [];
 
+                    // log messages for this computation step
+                    if (this._messages.length > 0) {
+                        if (re.log.messages.length > 0) {
+                            // find highest log level to display
+                            let highest = 100;
+                            for (const lm of re.log.messages) {
+                                highest = Math.min(highest, lm.getSeverity());
+                            }
+                            list.push({
+                                messages: re.log.messages,
+                                isInfo: (highest === MessageSeverity.INFO),
+                                isWarning: (highest === MessageSeverity.WARNING),
+                                isError: (highest === MessageSeverity.ERROR)
+                            });
+                        }
+                    } else {
+                        list.push({ messages: [] }); // empty log element to preserve row length
+                    }
+
                     // 1. variable params values for this computation step
                     for (const vv of varValues) {
                         list.push(vv[i]);
@@ -108,6 +144,10 @@ export class VarResultsComponent extends ResultsComponent {
         }
     }
 
+    public get hasMessages() {
+        return this._messages.length > 0;
+    }
+
     public get hasResults(): boolean {
         return this._varResults && this._varResults.hasResults;
     }
@@ -116,6 +156,14 @@ export class VarResultsComponent extends ResultsComponent {
         return this._headers;
     }
 
+    public get headersWithoutLogColumn() {
+        if (this.hasMessages) {
+            return this._headers.slice(1);
+        } else {
+            return this._headers;
+        }
+    }
+
     /**
      * Returns a combination of results and extraResults for mat-table
      */
@@ -131,4 +179,20 @@ export class VarResultsComponent extends ResultsComponent {
         // save and download
         XLSX.writeFile(wb, "VariableResults.xlsx");
     }
+
+    /** Shows a modal displaying the log messages details for a calcutation step */
+    public openLogDetails(messages: Message[]) {
+        if (this.isFullscreen) {
+            this.exitFullscreen();
+        }
+        this.logEntriesDetailsDialog.open(
+            DialogLogEntriesDetailsComponent,
+            {
+                data: {
+                    messages: messages
+                },
+                autoFocus: false
+            }
+        );
+    }
 }
diff --git a/src/app/components/log/log.component.ts b/src/app/components/log/log.component.ts
index bd710cb56a43ed8a4c927fe06ef90c9ae1f94c9a..6ab7883505321926fb9209f9a00bfe8c9d5938f0 100644
--- a/src/app/components/log/log.component.ts
+++ b/src/app/components/log/log.component.ts
@@ -22,7 +22,7 @@ export class LogComponent {
     ) { }
 
     private get uitextTitreJournal() {
-        return this.intlService.localizeText("INFO_REMOUSRESULTS_TITREJOURNAL");
+        return this.intlService.localizeText("INFO_TITREJOURNAL");
     }
 
     public get hasEntries(): boolean {
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 1392829d879fde9b0fde40256e036ef314b97b9e..b0c817f26119426a96ebf183e6239d049118198a 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -247,7 +247,6 @@
     "INFO_REMOUSRESULTS_TIRANT": "Draft (m)",
     "INFO_REMOUSRESULTS_TIRANTCRITIQUE": "Critical water level",
     "INFO_REMOUSRESULTS_TIRANTNORMAL": "Normal water level",
-    "INFO_REMOUSRESULTS_TITREJOURNAL": "Calculation log",
     "INFO_REPORT_BUG_BODY": "This is an issue report.\n\nPlease describe quickly the issue you encoutered, and the steps you followed:\n\n\n\n\n--- Current session state - do not modify text below ---\n------------------------------------------------------------------------\n\n",
     "INFO_REPORT_BUG_SUBJECT": "Issue report",
     "INFO_REQUIRES": "requires",
@@ -275,6 +274,7 @@
     "INFO_THEME_PASSE_A_BASSIN_TITRE": "Fish ladder",
     "INFO_THEME_PASSE_NATURELLE_DESCRIPTION": "Tools for sizing a natural fish pass also called macroroughness pass or rock-ramp fish pass",
     "INFO_THEME_PASSE_NATURELLE_TITRE": "Natural pass",
+    "INFO_TITREJOURNAL": "Calculation log",
     "INFO_WELCOME_CONTENT": "<p>The Cassiopée software was developed by <a href=\"https://www.afbiodiversite.fr\" target=\"_blank\">AFB</a> (French Agency for Biodiversity) and <a href=\"http://g-eau.fr/index.php/en/\" target=\"_blank\">UMR G-EAU</a> (Joint Research Unit \"Water Management, Actors, Territories\").</p><p>It includes tools for designing fish passes, and hydraulic calculation tools useful for environmental and agricultural engineering.</p><p>For more information, consult <a href=\"assets/docs-fr/mentions_legales.html\" target=\"_blank\">legal notice</a> and <a href=\"assets/docs-fr/index.html\" target=\"_blank\">documentation</a>.</p>",
     "INFO_WELCOME_SUBTITLE": "Hydraulic calculators",
     "WARNING_REMOUS_ARRET_CRITIQUE": "Calculation stopped: critical elevation reached at abscissa %x%",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index 16cdbe471511ef08abc998ec52456f7105fcecdd..47a63e9364b43faec33d58337cfbeeecedfce9fd 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -247,7 +247,6 @@
     "INFO_REMOUSRESULTS_TIRANT": "Tirant d'eau (m)",
     "INFO_REMOUSRESULTS_TIRANTCRITIQUE": "Tirant d'eau critique",
     "INFO_REMOUSRESULTS_TIRANTNORMAL": "Tirant d'eau normal",
-    "INFO_REMOUSRESULTS_TITREJOURNAL": "Journal de calcul",
     "INFO_REPORT_BUG_BODY": "Ceci est un rapport d'erreur.\n\nMerci de décrire rapidement ci-dessous le problème rencontré, et les étapes qui vous y ont mené :\n\n\n\n\n--- État de la session en cours - ne pas modifier le texte ci-dessous ---\n--------------------------------------------------------------------------------------------\n\n",
     "INFO_REPORT_BUG_SUBJECT": "Rapport d'erreur",
     "INFO_REQUIRES": "dépend de",
@@ -275,6 +274,7 @@
     "INFO_THEME_PASSE_A_BASSIN_TITRE": "Passe à bassins",
     "INFO_THEME_PASSE_NATURELLE_DESCRIPTION": "Outils de dimensionnement d'une passe à poissons de type passe naturelle ou encore appelée passe à macro-rugosités",
     "INFO_THEME_PASSE_NATURELLE_TITRE": "Passe naturelle",
+    "INFO_TITREJOURNAL": "Journal de calcul",
     "INFO_WELCOME_CONTENT": "<p>Le logiciel Cassiopée a été développé par l'<a href=\"https://www.afbiodiversite.fr\" target=\"_blank\">AFB</a> (Agence Française pour la Biodiversité) et <a href=\"http://g-eau.fr\" target=\"_blank\">L'UMR G-EAU</a> (UMR Gestion de l'Eau, Acteurs, Usages).</p><p>Il regroupe des outils d'aide à la conception de passes à poissons et des outils de calcul hydraulique utiles pour l'ingénierie en environnement et agriculture.</p><p>Pour plus d'informations, consulter les <a href=\"assets/docs-fr/mentions_legales.html\" target=\"_blank\">mentions légales</a> et la <a href=\"assets/docs-fr/index.html\" target=\"_blank\">documentation</a>.</p>",
     "INFO_WELCOME_SUBTITLE": "Modules de calcul d'hydraulique",
     "WARNING_REMOUS_ARRET_CRITIQUE": "Arrêt du calcul&nbsp;: hauteur critique atteinte à l'abscisse %x%",