diff --git a/chronicles.nim b/chronicles.nim index 5dce48b..950d784 100644 --- a/chronicles.nim +++ b/chronicles.nim @@ -176,7 +176,6 @@ macro expandIt*(T: type, expandedProps: untyped): untyped = record = ident "record" it = ident "it" it_name = ident "it_name" - value = ident "value" setPropertyCalls = newStmtList() for prop in expandedProps: @@ -260,7 +259,7 @@ macro logIMPL(lineInfo: static InstInfo, else: for topic in enabledTopics: if topic.name == t: - if topic.logLevel != NONE: + if topic.logLevel != LogLevel.NONE: if severity >= topic.logLevel: enabledTopicsMatch = true elif severity >= enabledLogLevel: @@ -268,7 +267,10 @@ macro logIMPL(lineInfo: static InstInfo, if t in requiredTopics: dec requiredTopicsCount - if severity != NONE and not enabledTopicsMatch or requiredTopicsCount > 0: + if requiredTopicsCount > 0: + return + + if enabledTopics.len > 0 and not enabledTopicsMatch: return # Handling file name and line numbers on/off (lineNumbersEnabled) for particular log statements @@ -282,7 +284,7 @@ macro logIMPL(lineInfo: static InstInfo, var code = newStmtList() when runtimeFilteringEnabled: - if severity != NONE: + if severity != LogLevel.NONE: code.add runtimeTopicFilteringCode(severity, activeTopics) # The rest of the code selects the active LogRecord type (which can @@ -290,10 +292,6 @@ macro logIMPL(lineInfo: static InstInfo, # translates the log statement to a set of calls to `initLogRecord`, # `setProperty` and `flushRecord`. let - recordTypeSym = skipTypedesc(RecordType.getTypeImpl()) - recordTypeNodes = recordTypeSym.getTypeImpl() - recordArity = if recordTypeNodes.kind != nnkTupleConstr: 1 - else: recordTypeNodes.len record = genSym(nskVar, "record") expandItIMPL = bindSym("expandItIMPL", brForceOpen) diff --git a/chronicles/dynamic_scope.nim b/chronicles/dynamic_scope.nim index 482e4dc..82f2996 100644 --- a/chronicles/dynamic_scope.nim +++ b/chronicles/dynamic_scope.nim @@ -1,5 +1,5 @@ import - macros, log_output, scope_helpers, options, dynamic_scope_types + macros, log_output, scope_helpers, dynamic_scope_types proc appenderIMPL[LogRecord, PropertyType](log: var LogRecord, keyValuePair: ptr ScopeBindingBase[LogRecord]) = diff --git a/chronicles/js_json_records.nim b/chronicles/json_records.nim similarity index 77% rename from chronicles/js_json_records.nim rename to chronicles/json_records.nim index 9d316ba..b090f43 100644 --- a/chronicles/js_json_records.nim +++ b/chronicles/json_records.nim @@ -10,11 +10,13 @@ when not defined(js): outputs, json_serialization type - LogRecord*[Output; timestamps: static[TimestampScheme]] = object + LogRecord*[Output; + timestamps: static[TimestampScheme], + colors: static[ColorScheme]] = object output*: OutputStream jsonWriter: JsonWriter - template setProperty(r: var LogRecord, key: string, val: auto) = + template setProperty*(r: var LogRecord, key: string, val: auto) = writeField(r.jsonWriter, key, val) template flushRecord*(r: var LogRecord) = @@ -33,7 +35,9 @@ else: JsonString* = distinct string type - LogRecord*[Output; timestamps: static[TimestampScheme]] = object + LogRecord*[Output; + timestamps: static[TimestampScheme], + colors: static[ColorScheme]] = object output*: Output record: js @@ -44,10 +48,18 @@ else: r.output.append JSON.stringify(r.record) flushOutput r.output +import typetraits + +template initOutputStream(x: auto): auto = + static: echo type(x).name + memoryOutput() + proc initLogRecord*(r: var LogRecord, level: LogLevel, topics: string, msg: string) = + r.output = initOutputStream r.Output + when defined(js): r.record = newJsObject() else: diff --git a/chronicles/log_output.nim b/chronicles/log_output.nim index 04ca00d..2fb3c54 100644 --- a/chronicles/log_output.nim +++ b/chronicles/log_output.nim @@ -34,18 +34,8 @@ type PassThroughOutput*[FinalOutputs: tuple] = object finalOutputs: FinalOutputs - BufferedOutput*[FinalOutputs: tuple] = object - finalOutputs: FinalOutputs - buffer: string - AnyFileOutput = FileOutput|StdOutOutput|StdErrOutput - AnyOutput = AnyFileOutput|SysLogOutput|BufferedOutput|PassThroughOutput - - LogRecord*[Writer; Output; - timestamps: static[TimestampScheme], - colors: static[ColorScheme]] = object - writer*: Writer - output*: Output + AnyOutput = AnyFileOutput|SysLogOutput|PassThroughOutput StreamOutputRef*[Stream; outputId: static[int]] = object @@ -61,8 +51,9 @@ when defined(posix): proc syslog(priority: int, format: cstring, msg: cstring) {.syslog_h.} # proc closelog() {.syslog_h.} - var LOG_EMERG {.syslog_h.}: int - var LOG_ALERT {.syslog_h.}: int + # Unused syslog levels: + # var LOG_EMERG {.syslog_h.}: int + # var LOG_ALERT {.syslog_h.}: int var LOG_CRIT {.syslog_h.}: int var LOG_ERR {.syslog_h.}: int var LOG_WARNING {.syslog_h.}: int @@ -261,7 +252,8 @@ proc selectRecordType(s: var StreamCodeNodes, sink: SinkSpec): NimNode = # The LogRecord types are parametric on their Output and this is how we # can support arbitrary combinations of log formats and destinations. -template activateOutput*(o: var (StdOutOutput|StdErrOutput), level: LogLevel) = +template activateOutput*(o: var (StdOutOutput|StdErrOutput|OutputStream), + level: LogLevel) = discard template activateOutput*(o: var FileOutput, level: LogLevel) = @@ -273,13 +265,12 @@ template activateOutput*(o: var StreamOutputRef, level: LogLevel) = template activateOutput*(o: var (SysLogOutput|DynamicOutput), level: LogLevel) = o.currentRecordLevel = level -template activateOutput*(o: var BufferedOutput|PassThroughOutput, level: LogLevel) = +template activateOutput*(o: var PassThroughOutput, level: LogLevel) = for f in o.finalOutputs.fields: activateOutput(f, level) template prepareOutput*(r: var auto, level: LogLevel) = mixin activateOutput - r = default(type(r)) # Remove once nim is updated past #9790 when r is tuple: for f in r.fields: @@ -287,6 +278,9 @@ template prepareOutput*(r: var auto, level: LogLevel) = else: activateOutput(r.output, level) +template initOuputStream(T: type): OutputStream = + + proc writeOutStr(f: File, s: OutStr) = # TODO: error handling discard f.writeBuffer(unsafeAddr s, s.len) @@ -357,21 +351,6 @@ template append*(o: var DynamicOutput, s: OutStr) = template flushOutput*(o: var (SysLogOutput|DynamicOutput)) = discard -# The buffered Output works in a very simple way. The log message is first -# buffered into a sting and when it needs to be flushed, we just instantiate -# each of the Output types and call `append` and `flush` on the instance: - -template append*(o: var BufferedOutput, s: OutStr) = - o.buffer.add(s) - -template flushOutput*(o: var BufferedOutput) = - for f in o.finalOutputs.fields: - append(f, o.buffer) - flushOutput(f) - -template getOutputStream(o: BufferedOutput|PassThroughOutput): File = - getOutputStream(o.finalOutputs[0]) - # The pass-through output just acts as a proxy, redirecting a single `append` # call to multiple destinations: diff --git a/chronicles/textblocks.nim b/chronicles/textblocks.nim index 73a25a9..2054d14 100644 --- a/chronicles/textblocks.nim +++ b/chronicles/textblocks.nim @@ -17,8 +17,11 @@ type const arrayOpenBracket = "[" & newLine arrayCloseBracket = "]" & newLine - objectOpenBracket = "[" & newLine - objectCloseBracket = "]" & newLine + +const + # We work-around a Nim bug: + # The compiler claims that the `terminal` module is unused + styleBright = terminal.styleBright proc appendIndent(output: var auto, depthLevel: int) = for i in 0 .. depthLevel: @@ -92,6 +95,8 @@ proc initLogRecord*(r: var LogRecord, topics, msg: string) = mixin append + r.output = initOutputStream r.Output + appendLogLevelMarker(r, level) writeTs(r) diff --git a/chronicles/textformats.nim b/chronicles/textformats.nim index 6827cef..a0011a2 100644 --- a/chronicles/textformats.nim +++ b/chronicles/textformats.nim @@ -1,5 +1,5 @@ import - strutils, terminal, + strutils, faststreams/outputs, options, log_output diff --git a/chronicles/textlines.nim b/chronicles/textlines.nim index 5260c8b..ba6621a 100644 --- a/chronicles/textlines.nim +++ b/chronicles/textlines.nim @@ -1,5 +1,5 @@ import - times, strutils, terminal, typetraits, + times, strutils, typetraits, terminal, serialization/object_serialization, faststreams/[outputs, textio], options, log_output, textformats @@ -12,6 +12,11 @@ type when stackTracesEnabled: exception*: ref Exception +const + # We work-around a Nim bug: + # The compiler claims that the `terminal` module is unused + styleBright = terminal.styleBright + proc appendValueImpl[T](r: var LogRecord, value: T) = mixin formatItIMPL @@ -100,6 +105,7 @@ proc initLogRecord*(r: var LogRecord, level: LogLevel, topics, msg: string) = r.level = level + r.output = initOutputStream r.Output # Log level comes first - allows for easy regex match with ^ appendLogLevelMarker(r, level)