Registre ràpid: NSHipster

El 2002 va aprovar-se el Congrés dels Estats Units Llei Sarbanes-Oxley, que va introduir una supervisió generalitzada de les empreses en resposta als escàndols comptables en empreses com
Enron i
MCI WorldCom
en aquest moment. Aquest acte,

PCI

i

HIPAA

, constitueix un fons normatiu per a una nova generació
A empreses derivades de globus dot-com.

Al mateix temps, vam veure l’aparició d’una efímera infraestructura distribuïda, el que ara anomenem La computació en núvol – Un paradigma que ha fet que els sistemes siguin més capaços però també més complexos.

Abordar els reptes tant reguladors com logístics de 21c segle, el nostre camp ha establert les millors pràctiques al voltant del registre de sol·licituds. I moltes de les mateixes eines i estàndards s’utilitzen encara avui.


Aquesta setmana a NSHipster ho mirem
SwiftLog: un estàndard d’entrada Swift de codi obert dirigit per la comunitat.

Desenvolupat per la comunitat Swift on Server i aprovat per
SSWG (grup de treball de servidor ràpid), la seva utilitat no es limita a l’ús del servidor. De fet, qualsevol codi Swift dissenyat per executar-se des de la línia d’ordres es beneficiaria de l’acceptació SwiftLog. Seguiu llegint per saber com fer-ho.


Com sempre, un exemple seria útil per guiar la nostra discussió. En esperit de transparència i nostàlgia, imaginem-nos escrivint un programa Swift que auditi les finances d’una empresa Fortune 500 de 00 anys.

import Foundation

struct Auditor {
    func watch(_ directory: URL) throws {  }
    func cleanup() {  }
}

do {
    let auditor = Auditor()

    defer { auditor.cleanup() }
    try auditor.watch(directory: URL(string: "ftp:///reports")!,
                     extensions: ["xls", "ods", "qdf"]) // poll for changes
} catch {
    print("error: (error)")
}

An Auditor tipus d’enquestes per als canvis de directori
(Servidor FTP, perquè recordeu: és el 2003). Cada vegada que s’afegeix, s’elimina o modifica un fitxer, es comprova si hi ha discrepàncies sobre el seu contingut. Si es produeix cap problema financer, es registren amb l’ajuda de print funció. El mateix passa amb els problemes relacionats amb FTP o altres problemes amb què es pugui trobar el programa: tot està registrat print.

Prou senzill. El podem iniciar des de la línia d’ordres de la següent manera:

$ swift run audit
starting up...
ERROR: unable to reconnect to FTP

# (try again after restarting PC under our desk)

$ swift run audit
+ connected to FTP server
! accounting discrepancy in balance sheet 
** Quicken database corruption! **
^C
shutting down...

Aquest programa pot ser tècnicament compatible, però deixa molt marge de millora:

  • En primer lloc, la nostra sortida no té marques de temps associades. No hi ha manera de saber si es va descobrir un problema fa una hora o la setmana passada.
  • Un altre problema és que la nostra producció no té cap estructura consistent. A simple vista, no hi ha una manera clara d’aïllar el soroll del programa de problemes reals.
  • I finalment, –
    i això es deu principalment a un exemple insuficientment donat – no està clar com es processa aquesta sortida. On va aquesta sortida? Com es recull, es resumeix i s’analitza?

La bona notícia és que tots aquests problemes (i molts altres) es poden solucionar adoptant una infraestructura de registre formal per al vostre projecte.


POSIX sistemes, els programes funcionen en tres, predefinits
fluxos:

Tirador d’arxiu Descripció Nom
0 stdin Entrada estàndard
1 stdout Sortida estàndard
2 stderr Error comú

Per defecte,
Logger utilitza la funció integrada StreamLogHandler tipus per enregistrar missatges registrats a la sortida estàndard (stdout). Podem substituir aquest comportament en lloc d’escriure un error estàndard (stderr) mitjançant l’inicialitzador més complex, que necessita un factory paràmetre: tancament que requereix una sola String paràmetre (etiqueta) i retorna un objecte corresponent a LogHandler.

let logger = Logger(label: "com.NSHipster.Auditor2000",
                    factory: StreamLogHandler.standardError)

Aplicació 12 Factor principis:

syslog missatges – i gràcies a
aquest paquet d’Ian PartridgeSwift també pot.

No obstant això, pocs enginyers han pogut extreure aquesta informació Splunk
i va viure per explicar la història. Per a nosaltres, els mortals, podríem preferir-ho
aquest paquet de Will Lisakque envia missatges de registre a
Relaxat.

La bona notícia és que podem utilitzar les dues coses alhora sense canviar la manera de registrar els missatges al lloc de trucades, utilitzant una altra part de Logging mòdul:
MultiplexLogHandler.

import struct Foundation.ProcessInfo
import Logging
import LoggingSyslog
import LoggingSlack

LoggingSystem.bootstrap { label in
    let webhookURL = URL(string:
        ProcessInfo.processInfo.environment["SLACK_LOGGING_WEBHOOK_URL"]!
    )!
    var slackHandler = SlackLogHandler(label: label, webhookURL: webhookURL)
    slackHandler.logLevel = .critical

    let syslogHandler = SyslogLogHandler(label: label)

    return MultiplexLogHandler([
        syslogHandler,
        slackHandler
    ])
}

let logger = Logger(label: "com.NSHipster.Auditor2000")

Amb tot això al nostre lloc, el nostre sistema registrarà tot en format syslog per sortir de sèrie (stdout), on pot ser recollit i analitzat per un altre sistema.


Però la força real d’aquest enfocament de registre és que es pot ampliar per satisfer les necessitats específiques de cada entorn. En lloc d’escriure syslog in stdout o missatges Slack, el vostre sistema pot enviar correus electrònics, obrir entrades SalesForce o activar un ganxo web per activar-ne alguns
IoT dispositiu.

A continuació s’explica com podeu ampliar SwiftLog per satisfer les vostres necessitats, escrivint un controlador de revistes personalitzat:

manipulador d’usuaris
que dóna format als missatges de registre d’accions de GitHub perquè apareguin a la interfície d’usuari de GitHub de la manera següent:

Si esteu interessats en crear el vostre propi controlador de registre, podeu aprendre moltes coses només navegant
el codi d’aquest projecte. Però volia assenyalar alguns punts interessants aquí:

@testable import

de la declaració del mòdul GitHubActionsLogHandler, hi podem tenir accés internal inicialitzador d’abans i passa una instància a MockTextOutputStream per interceptar missatges registrats.

import Logging
@testable import LoggingGitHubActions

final class MockTextOutputStream: TextOutputStream {
    public private(set) var lines: [String] = []

    public init(_ body: (Logger) -> Void) {
        let logger = Logger(label: #file) { label in
            GitHubActionsLogHandler(outputStream: self)
        }

        body(logger)
    }

    // MARK: - TextOutputStream

    func write(_ string: String) {
        lines.append(string)
    }
}

Amb aquestes peces al seu lloc, finalment podem comprovar si el nostre manipulador funciona com s’esperava:

func testLogging() {
    var logLevel: Logger.Level?
    let expectation = MockTextOutputStream { logger in
        logLevel = logger.handler.logLevel

        logger.trace("🥱")
        logger.error("😱")
    }

    XCTAssertGreaterThan(logLevel!, .trace)
    XCTAssertEqual(expectation.lines.count, 1) // trace log is ignored
    XCTAssertTrue(expectation.lines[0].hasPrefix("::error "))
    XCTAssertTrue(expectation.lines[0].hasSuffix("::😱"))
}

Add a Comment

Your email address will not be published. Required fields are marked *