Parse, contract-check, redact, profile, and diff logfmt data in MoonBit
moon add sqhyyy/moonlogfmt-lenslet parsed = @lens.parse(
"level=info msg=\"service ready\" request_id=req-42",
)
if parsed.is_valid() {
println(parsed.get("msg"))
println(parsed.normalized())
}
let audit = @lens.audit_line_with_policy(
"level=warn msg=one msg=two dry_run",
@lens.AuditPolicy::ci(),
)
println(audit.text_report())inspect(@lens.classify_value("503"), content="ValueInteger")
inspect(@lens.classify_value("1.5s"), content="ValueDuration")
inspect(@lens.classify_value("2026-07-29T12:30:00Z"), content="ValueTimestamp")let contract = @lens.LogContract::new(
"api-service",
[
@lens.FieldRule::typed("level", @lens.ValueIdentifier, required=true)
.with_allowed_values(["info", "warn", "error"]),
@lens.FieldRule::text("msg", required=true).with_max_length(240),
@lens.FieldRule::typed("status", @lens.ValueInteger),
@lens.FieldRule::typed("duration", @lens.ValueDuration),
],
unknown_fields=@lens.UnknownReject,
)
let report = @lens.validate_contract(
"level=info msg=ready status=200 duration=12ms",
contract,
)
println(report.decision())let inference = @lens.infer_schema([
"level=info status=200 duration=12ms",
"level=warn status=503 duration=1.5s",
"level=info status=201 duration=9ms",
])
println(inference.text_report())
let candidate = inference.contract()let result = @lens.redact_line(
"level=info email=user@example.com api_token=secret peer=10.0.0.8",
policy=@lens.RedactionPolicy::strict(),
)
println(result.safe_line())
println(result.json_report())let batch = @lens.analyze_batch(
[
"level=info msg=ready status=200",
"level=warn msg=slow status=503",
],
policy=@lens.BatchPolicy::ci(),
)
let decision = @lens.evaluate_batch(
batch,
policy=@lens.BatchGatePolicy::ci(),
)
println(decision.label())let baseline = @lens.analyze_batch([
"level=info msg=ready status=200 duration=12ms",
"level=warn msg=slow status=503 duration=80ms",
])
let current = @lens.analyze_batch([
"level=info msg=ready status=ok region=us",
"level=warn msg=slow status=failed region=eu",
])
let drift = @lens.compare_batches(
baseline,
current,
policy=@lens.DriftPolicy::ci(),
)
println(drift.text_report())moon run cmd/main -- audit level=info msg="service ready"
moon run cmd/main -- contract level=info msg=ready service=api
moon run cmd/main -- privacy level=info api_token=secret
moon run cmd/main -- profile status=503 duration=12ms
moon run cmd/main -- template level=info msg=ready status=200moon run examples/basic
moon run examples/advanced
moon run examples/privacy
moon run examples/driftmoon fmt
moon check
moon build
moon test
moon package --listfn BatchGatePolicy::with_error_budget(self : BatchGatePolicy, max_invalid_percent : Int, max_high_risk_percent : Int) -> BatchGatePolicyfn BatchGatePolicy::with_required_keys(self : BatchGatePolicy, required_keys : Array[String], min_prevalence? : Int) -> BatchGatePolicypub struct BatchPolicy {
audit_policy : AuditPolicy
skip_blank_lines : Bool
max_distinct_shapes : Int
} derive(Debug)pub struct BatchReport {
input_lines : Int
processed_lines : Int
skipped_blank_lines : Int
valid_lines : Int
invalid_lines : Int
clean_lines : Int
low_risk_lines : Int
medium_risk_lines : Int
high_risk_lines : Int
aggregate_risk_score : Int
reviews : Array[LineReview]
profiles : Array[FieldProfile]
shapes : Array[ShapeStat]
shape_limit_exceeded : Bool
} derive(Debug)pub struct ContractReport {
contract_name : String
parsed : ParseResult
violations : Array[ContractViolation]
} derive(Debug)pub struct ContractViolation {
kind : ContractViolationKind
severity : Severity
key : String
expected : String
actual : String
message : String
offset : Int
} derive(Eq, Debug)fn DriftPolicy::with_retired_shapes(self : DriftPolicy, report_retired_shapes : Bool) -> DriftPolicypub struct DriftReport {
baseline_lines : Int
current_lines : Int
findings : Array[DriftFinding]
} derive(Eq, Debug)pub struct FieldProfile {
key : String
lines_seen : Int
values_seen : Int
max_length : Int
distinct_values : Array[String]
distribution : ValueDistribution
} derive(Eq, Debug)pub struct Finding {
kind : FindingKind
severity : Severity
key : String
message : String
offset : Int
} derive(Eq, Debug)fn Finding::new(kind : FindingKind, severity : Severity, key : String, message : String, offset? : Int) -> Findingpub struct InferencePolicy {
required_percent : Int
type_confidence_percent : Int
enum_cardinality_limit : Int
unknown_fields : UnknownFieldPolicy
} derive(Eq, Debug)pub struct LineReview {
line_number : Int
shape : String
fingerprint : String
report : AuditReport
} derive(Debug)pub struct LogContract {
name : String
rules : Array[FieldRule]
unknown_fields : UnknownFieldPolicy
max_fields : Int
} derive(Debug)fn LogContract::new(name : String, rules : Array[FieldRule], unknown_fields? : UnknownFieldPolicy, max_fields? : Int) -> LogContractpub struct ParseResult {
source : String
fields : Array[Field]
errors : Array[ParseError]
} derive(Debug)pub struct PrivacyFinding {
key : String
kind : SensitiveKind
reason : String
offset : Int
} derive(Eq, Debug)fn RedactionPolicy::with_allow_keys(self : RedactionPolicy, allow_keys : Array[String]) -> RedactionPolicyfn RedactionPolicy::with_network_values(self : RedactionPolicy, redact_network_values : Bool) -> RedactionPolicyfn RedactionPolicy::with_value_detection(self : RedactionPolicy, detect_values : Bool) -> RedactionPolicypub struct RedactionResult {
parsed : ParseResult
safe_line : String
findings : Array[PrivacyFinding]
redacted_keys : Array[String]
} derive(Debug)pub struct SchemaInference {
total_lines : Int
valid_lines : Int
invalid_lines : Int
profiles : Array[FieldProfile]
contract : LogContract
} derive(Debug)pub struct ValueDistribution {
flag_count : Int
empty_count : Int
boolean_count : Int
integer_count : Int
decimal_count : Int
duration_count : Int
byte_size_count : Int
timestamp_count : Int
ipv4_count : Int
uuid_count : Int
email_count : Int
hex_count : Int
identifier_count : Int
text_count : Int
} derive(Eq, Debug)fn compare_batches(baseline : BatchReport, current : BatchReport, policy? : DriftPolicy) -> DriftReportfn contract_from_batch(report : BatchReport, name? : String, required_percent? : Int, unknown_fields? : UnknownFieldPolicy) -> LogContractfn shape_fingerprint(shape : String) -> Stringfn structural_template(line : String) -> StringParse, contract-check, redact, profile, and diff logfmt data in MoonBit