DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on

Electron Adventures: Episode 91: Application Logs

I wanted to add some more OS integrations, but a few of them only work with packaged app.

Developing an app and then packaging it is fine, but functionality that only works when packaged is a huge pain to test. First big issue is that there's no console.log from the backend process.

There are a few ways to get around this, let's try electron-log package to log things to a text file.

Installing

$ npm install electron-log
Enter fullscreen mode Exit fullscreen mode

Using the logger

After that we can edit index.js and replace console.log with log.info. There are other log levels too, if you need this distinction. Only two lines here are new, but here's the whole file:

let { app, BrowserWindow, dialog, Menu } = require("electron")
let settings = require("electron-settings")
let log = require("electron-log")

let isOSX = (process.platform === "darwin")

function createWindow(path) {
  log.info("Creating window for", path)
  let key = `windowState-${path}`
  let windowState = settings.getSync(key) || { width: 1024, height: 768 }

  let qs = new URLSearchParams({ path }).toString();
  let win = new BrowserWindow({
    ...windowState,
    webPreferences: {
      preload: `${__dirname}/preload.js`,
    },
  })

  function saveSettings() {
    windowState = win.getBounds()
    log.info("Saving window position", path, windowState)
    settings.setSync(key, windowState)
  }

  win.on("resize", saveSettings)
  win.on("move", saveSettings)
  win.on("close", saveSettings)

  win.loadURL(`http://localhost:5000/?${qs}`)
}

async function openFiles() {
  let { canceled, filePaths } = await dialog.showOpenDialog({
    properties: ["openFile", "multiSelections", "showHiddenFiles"],
    filters: [
      { name: "CSV files", extensions: ["csv"] },
      { name: "All Files", extensions: ["*"] }
    ],
    message: "Select a CSV file to open",
    defaultPath: `${__dirname}/samples`,
  })
  if (canceled && !isOSX) {
    app.quit()
  }
  for (let path of filePaths) {
    createWindow(path)
  }
}

let dockMenu = Menu.buildFromTemplate([
  {
    label: "Open files",
    click() { openFiles() }
  }
])

async function startApp() {
  if (isOSX) {
    app.dock.setMenu(dockMenu)
  }
  await openFiles()
  if (isOSX) {
    app.on("activate", function() {
      if (BrowserWindow.getAllWindows().length === 0) {
        openFiles()
      }
    })
  }
}

app.on("window-all-closed", () => {
  if (!isOSX) {
    app.quit()
  }
})

app.on("ready", startApp)
Enter fullscreen mode Exit fullscreen mode

Viewing the logs

The logs are saved in different location dependig on the operating system. For OSX, they will be at ~/Library/Logs/<application_name>/main.log - main being the Electron word for backend.

If you use the logger from another process (frontend/renderer, or a worker process), it will go to a different file.

So let's take a look at ~/Library/Logs/episode-91-application-logs/main.log:

[2021-11-09 11:55:16.344] [info]  Creating window for /Users/taw/electron-adventures/episode-91-application-logs/samples/06-reputation.csv
[2021-11-09 11:55:37.027] [info]  Saving window position /Users/taw/electron-adventures/episode-91-application-logs/samples/06-reputation.csv { x: 1116, y: 661, width: 1024, height: 768 }
[2021-11-09 11:55:37.129] [info]  Saving window position /Users/taw/electron-adventures/episode-91-application-logs/samples/06-reputation.csv { x: 812, y: 601, width: 1024, height: 768 }
[2021-11-09 11:55:37.235] [info]  Saving window position /Users/taw/electron-adventures/episode-91-application-logs/samples/06-reputation.csv { x: 768, y: 589, width: 1024, height: 768 }
[2021-11-09 11:55:37.348] [info]  Saving window position /Users/taw/electron-adventures/episode-91-application-logs/samples/06-reputation.csv { x: 767, y: 588, width: 1024, height: 768 }
Enter fullscreen mode Exit fullscreen mode

Results

Now that we have logging working even from a packaged app, let's see if we can integrate drag and dropping files onto Dock in the next episode.

As usual, all the code for the episode is here.

Discussion (0)