Introduksjon til Logging

Skip to content

Info

Logging er en universell ferdighet som gjelder alle programmeringsspråk og rammeverk! Konseptene du lærer her kan du ta med deg til Java, JavaScript, C#, Go, Rust - you name it. Vi bruker Python som hovedeksempel, men prinsippene er de samme overalt. 🌍

Hvorfor logging? 🤔

Har du noen gang brukt print() for å finne ut hva som skjer i programmet ditt? Det fungerer kanskje greit når du sitter og koder alene, men hva skjer når programmet kjører på en server? Eller når du skal feilsøke noe som skjedde i går? Da trenger du noe bedre enn print() - da trenger du logging! 📋

Del 1 - Hva er Logging?

Logging handler om å skrive ned hva et program gjør mens det kjører. Tenk på det som en dagbok for programmet ditt. Hver gang noe viktig skjer - en bruker logger inn, en feil oppstår, en beregning fullføres - så skriver programmet en logg-melding.

Hvorfor ikke bare bruke print()?

La oss sammenligne:

print() logging
Nivåer (info, error, debug)
Tidsstempel
Skrive til fil
Slå av/på enkelt
Bruke i produksjon
Filtrere meldinger

Med andre ord: print() er greit for rask debugging, men logging er det profesjonelle valget! 💼

Logging-nivåer

De fleste logging-systemer (uansett språk!) har disse nivåene, fra minst til mest alvorlig:

Nivå Beskrivelse Eksempel
DEBUG Detaljert info, mest for feilsøking “Bruker sendte request med data: {…}”
INFO Generell info om at ting fungerer “Server startet på port 8000”
WARNING Noe uventet, men programmet kjører fortsatt “Disk er 90% full”
ERROR Noe gikk galt “Kunne ikke koble til database”
CRITICAL Alvorlig feil, programmet kan kræsje “Ut av minne, avslutter”

Tommelfingerregel 👍

  • DEBUG - Ting du bare trenger under utvikling
  • INFO - Ting du vil vite om i produksjon
  • WARNING - Ting som kanskje blir et problem
  • ERROR - Ting som er et problem
  • CRITICAL - Ting som er et STORT problem

Del 2 - Python sin logging-modul

Python har en innebygd modul som heter logging. Den trenger ikke installeres - den følger med Python!

Her er et grunnleggende eksempel:

import logging

# Sett opp grunnleggende logging
logging.basicConfig(level=logging.DEBUG)

# Lag en logger
logger = logging.getLogger(__name__)

# Bruk de forskjellige nivåene
logger.debug("Dette er en debug-melding")
logger.info("Serveren startet!")
logger.warning("Pass på, disken er nesten full!")
logger.error("Kunne ikke koble til databasen!")
logger.critical("Alt har gått galt! 💀")
Hva er __name__?

__name__ er en spesiell variabel i Python som inneholder navnet på den nåværende modulen. Hvis du kjører filen direkte, vil __name__ være "__main__". Hvis filen importeres fra en annen fil, vil den ha filnavnet.

Dette er nyttig fordi du kan se hvilken fil en logg-melding kommer fra! 🔍

Del 3 - Et eksempel i et annet språk

Bare for å vise at logging er universelt - her er det samme konseptet i JavaScript (Node.js):

// JavaScript bruker ofte 'console' som en enkel logger
console.debug("Debug-melding");
console.info("Info-melding");
console.warn("Advarsel!");
console.error("Feil!");

// Men i produksjon bruker man gjerne et bibliotek som 'winston' eller 'pino'

Og i Java:

import java.util.logging.Logger;

Logger logger = Logger.getLogger("MinApp");
logger.info("Serveren startet!");
logger.warning("Noe rart skjedde...");
logger.severe("Kritisk feil!"); // Java bruker "severe" istedenfor "critical"

Legg merke til at konseptene er nesten identiske - det er bare syntaksen som er forskjellig! 😎


Oppgaver

Easy Oppgave 1.1 - Første Logger

Lag et Python-program som bruker logging-modulen til å logge meldinger på alle fem nivåer.

  1. Importer logging
  2. Sett opp basicConfig med level=logging.DEBUG
  3. Lag en logger med getLogger()
  4. Logg en melding på hvert nivå (debug, info, warning, error, critical)
  5. Kjør programmet og se hva som skrives ut i terminalen
Hva bør outputen se ut som?

Du bør se noe sånt som:

DEBUG:__main__:Dette er en debug-melding
INFO:__main__:Server startet
WARNING:__main__:Advarsel!
ERROR:__main__:Noe gikk galt
CRITICAL:__main__:Alt kræsjet!

Easy Oppgave 1.2 - Endre nivå

Prøv å endre level i basicConfig til logging.WARNING.

  • Hva skjer med debug og info meldingene?
  • Hvorfor er dette nyttig?
Svar

Når du setter nivået til WARNING, vil bare meldinger på WARNING, ERROR og CRITICAL vises. DEBUG og INFO meldingene blir filtrert bort. Dette er nyttig fordi du kan ha masse debug-meldinger i koden som kun vises når du trenger dem, uten å “rote til” output i produksjon!

Medium Oppgave 1.3 - Logging med kontekst

Lag et lite program med en funksjon som deler to tall. Bruk logging til å:

  1. Logge på DEBUG-nivå hva tallene er
  2. Logge på INFO-nivå hva resultatet er
  3. Logge på ERROR-nivå dersom brukeren prøver å dele på null
Tips

Bruk try/except for å fange ZeroDivisionError. Du kan bruke f-strings i logg-meldinger:

logger.debug(f"Deler {a}{b}")
Eksempel på løsning
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

def divide(a, b):
    logger.debug(f"Forsøker å dele {a}{b}")
    try:
        result = a / b
        logger.info(f"Resultat: {a} / {b} = {result}")
        return result
    except ZeroDivisionError:
        logger.error(f"Kan ikke dele {a} på null!")
        return None

divide(10, 2)
divide(10, 0)

Medium Oppgave 1.4 - Logging til fil

Nå skal vi skrive loggen til en fil i tillegg til terminalen! Endre basicConfig til å inkludere en filename:

logging.basicConfig(
    level=logging.DEBUG,
    filename="app.log",
    filemode="w",  # "w" = overskriv, "a" = legg til
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
  1. Kjør programmet ditt fra forrige oppgave med denne konfigurasjonen
  2. Åpne app.log og se hva som står der
  3. Hva gjør format-parameteren? Prøv å endre den!

Merk!

Når du setter filename vil meldingene kun skrives til filen, ikke til terminalen. I neste level skal vi se på hvordan vi kan gjøre begge deler! 🔥