#i would like to draft a log handler

1 messages · Page 1 of 1 (latest)

fading temple
#

But am stuck designing it properly.

the goal is to lift logging up to the api layer. so that one can rely on serverless architecture.

should it have a protocol?

conform your struct, a representable of your log message,

  • have the option to construct my catalogue of logs.
  • deterministic cases, deterministic behaviour
  • keep the logging behaviour centralized.
  • simply interact with other apis.
  • register the handler, and pass the array of logs to create/ingest along

heres the gist:


extension LogType {
  enum Base: String, Sendable {
    case authentication
  }

  public static let generic = Self(.generic)
}


struct MyLog: Encodable {
  let timestamp: Date
  let message: String

  private enum CodingKeys: String, CodingKey {
    case timestamp = "@timestamp"
    case message
  }

  // let the log handler create a log entry
  public static func authentication(timestamp: String, message: String) -> Self {
    .init(backing: .init(logType: .generic, timestamp: timestamp, message: message))
  }

  // other functions.
}

// call it
...somecode
  MyLog.authentication("\(personID) has authenticated")
... so on and so forth

but to interface with a database or another medium of storage is a bit trickier. any suggestions?

muted notch
#

What exactly do you mean by "the goal is to lift logging up to the api layer"

fading temple
#

have routes accepting log messages from clients into the log handler down to storage... somewhere... in nevada

muted notch
#

Use Swift Log for the logging API then you can choose whatever backend you want

fading temple
#

which is the part i try to to write

fading temple
#

i am having trouble servicing the proper type requirements for a protocol.

//
public protocol LogServiceable: Sendable {
    
    var id: LogIdentifier { get }
    
    var handler: LogHandler { get }
    
    func log(
        action: any LogAction,
        entry: LogEntry
    ) async throws
}

#
public struct ClientLogService: LogServiceable {
...
    //
    public func log<Entry>(
        action: ClientAction,
        entry: Entry
    ) async throws where Entry: LogEntry {
        
        var _entry: LogEntry = entry
        _entry.metadata = prepareMetadata(entry.metadata)
        
        let entry = _entry
        if action == .clientAuthenticated {
            try await entry.log() }
        
        if action == .clientDeAuthenticated {
            
        }
        
        throw LogError.invalidEntry("clientEntry")
    }
#

it keeps demanding me to implement a different function

public func log(
        action: any LogAction,
        entry: any LogEntry
    ) async throws`

even though i am of the opinion to have fullfilled the type constraints fromt he protocol

#

i do need the protocol though

#

id call it like.

let entry = ClientEntry(...fields blah)
app.loggerX.log(.clientAuthenticated, entry)
spring ibex
fading temple
#

awesome, it does have features i can include in feature revisions.
idk about multiplexer, but sure am curious as looking forward to get my hands on distributed actors.

#

i understand your concerns. yet still looking forward to resolve
the error in type restrictions i have

fading temple
muted notch
#

What are you trying to achieve with this I'm a bit unclear

fading temple
#

just coding a wrapper

muted notch
#

What actual problem are you trying to solve

#

Because anything that doesn't use the SwiftLog API is not gonna be helpful because your app can use your custom logger but nothing else will, no dependencies will etc. so you'll have logs going to 2 different places

#

The ecosystem has centralised on SwiftLog as the logging API to use and everything logs to that. The end application then bootstraps a LogHandler that conforms to SwiftLog's protocol and can decide how to handle log messages and what to do with them (format them, print them to a console, send them to an API, write to a file, all of the above etc)

fading temple
#

idkwym, i do use the logging api as defined and built a thin wrapper.
create an object with fields, instead of passing a string, including a customized log function. which gets called equally,
if the objects comes from request or programatically

#

i admin. it is a really thin wrapper

#

but the goal is to have instead of

logger.info("some info")
...
app.logger.info(.clientAuthenticated, clientEntry)
#

which is expected to be cleaner

toxic gazelle
#

well ur protocol defines that function so thats why its asking to define it it seems

#

You have LogEntry defined in the protocol and Entry in the imp. that seems to be where the issue is.

#

so i guess its not seeing this ```swift
associatedtype Entry: LogKitEntry

fading temple
#

oh, i updated the repo you might have missed it

#

i lifted generic constraints to serviceable, as of before it has been located within the function.
that seems to have resolved the issue.

#

but admittetly i just brute forced configuration around until it compiled.
quite some time.

toxic gazelle
#

well if it was in the function i guess it was a scope issue