Какая структура ведения журналов лучше использовать в коде F #
Мне нужно добавить журнал в мой проект F #.
Для кода С# мы использовали: Log4net или NLog (возможны две из самых популярных фреймворков регистрации для .Net).
Каков наилучший выбор для использования в коде F #?
Я имею в виду, есть ли какая-либо конкретная структура ведения журнала, написанная для использования в коде F #?
Ответы
Ответ 1
Использовать Logary
https://github.com/logary/logary
Logary - это высокопроизводительная многоцелевая библиотека регистрации, метрики и проверки работоспособности для моно и .Net. Цели включают в себя: текстовый редактор, консоль, отладчик, nlog, zipkin, nimrod, riemann, logstash, sqlite, sql-сервер, графит, loggr, elmah.io, logentries. Адаптеры для: suave, topshelf.
Логарифм записывается в F # для F # в первую очередь.
Install-Package Logary
docs here
Ответ 2
Насколько я знаю, они одинаковы для F #, т.е. ничего особенного F # о них (хорошо или плохо). Помимо конфигурации, использование практически одинаково для всех журнальных библиотек.
То, что вы можете добавить, - это журналирование с поддержкой printf, поэтому вместо logger.DebugFormat("Hello {0}", "world")
или logger.Debug(sprintf "Hello %s" "world")
вы можете просто сделать logger.Debugf "Hello %s" "world"
. Используйте типы расширений и kprintf, чтобы сделать это.
Ответ 3
Я сделал код примерно так (используя словесный синтаксис):
#light "off"
open System.Runtime.CompilerServices
let inline (|?) (a: 'a option) b = if a.IsSome then a.Value else b; // coalesce operator
type T() = class
static member private printLog(par) =
match ( par) with
| msg, Some m, Some p, Some l -> (
let pl = Array.head (Array.rev( string(p).Split([|'\\';'/'|]))) in
printfn "at %s(%s: line %d) %s" m pl l msg
)
| msg, _,_,_ -> printfn "at ?? %s" msg
static member LOG(msg: string, ?a:obj,
[<CallerMemberName>] ?memberName: string,
[<CallerFilePath>] ?path: string,
[<CallerLineNumber>] ?line: int) = match a with
| Some a -> (match a with
| :? int as i -> T.printLog((sprintf "%s %d" msg i), memberName, path,line)
| :? float as f -> T.printLog((sprintf "%s %f" msg f), memberName, path,line)
| _ -> T.printLog((sprintf "%s %A" msg a), memberName, path,line)
)
| None -> T.printLog(msg, memberName, path,line)
static member EXIT(?msg:string, [<CallerMemberName>] ?memberName: string,
[<CallerFilePath>] ?path: string,
[<CallerLineNumber>] ?line: int) =
printf "Exiting ... ";
T.printLog((msg |? "Giving up!"), memberName, path,line);
exit 1
end
использование:
"text pushed in" |> T.LOG;
T.LOG "just text at line ";
T.LOG ("just text at line in par");
T.LOG ("string ", "text i got");
T.LOG ("int ", 1);
T.LOG ("tuple ", (1,2));
let msg = Some "existing optional value" in
printfn """ (msg |? "this is default value\") ---> %A""" (msg |? "d
T.EXIT( "after all test done no TODO new extentions");
производит:
at testit(TautoLogics.fs: line 49) text pushed in
at testit(TautoLogics.fs: line 52) just text at line
at testit(TautoLogics.fs: line 53) just text at line in par
at testit(TautoLogics.fs: line 54) string "text i got"
at testit(TautoLogics.fs: line 55) int 1
at testit(TautoLogics.fs: line 56) tuple (1, 2)
'(msg |? "this is default value\") ---> "existing optional value"
Exiting ... at testit(TautoLogics.fs: line 63) after all test done
просто и удобно для меня.