Skip to content

Verbose mode on classifier#467

Open
syp1975 wants to merge 1 commit into
bitmagnet-io:mainfrom
syp1975:verbose
Open

Verbose mode on classifier#467
syp1975 wants to merge 1 commit into
bitmagnet-io:mainfrom
syp1975:verbose

Conversation

@syp1975

@syp1975 syp1975 commented Dec 27, 2025

Copy link
Copy Markdown

I was trying to debug my classifier workflow on one of the releases I use. No information of the process is displayed anywhere so I decided to add a verbose mode on the classifier. This verbose mode is only meant to be enabled when debugging your workflows, it will generate a massive amount of log messages.

Verbose mode is enabled on config:

classifier:
  concurrency: 1
  workflow: custom
  verbose: true
...

This is an example of the classifier (runner) log output in verbose mode:

INFO	runner	classifier/runner.go:77	start	{"workflow": "custom", "hash": "***", "name": "*** *** [HDTV 1080p][Cap.999]", "files": [{"infoHash":"***","index":1,"path":"*** ***.url","extension":"url","size":999,"createdAt":"2025-12-21T00:13:09.123697+01:00","updatedAt":"2025-12-21T00:13:09.123697+01:00"},{"infoHash":"***","index":0,"path":"*** *** [HDTV 1080p][Cap.999].mkv","extension":"mkv","size":999,"createdAt":"2025-12-21T00:13:09.123697+01:00","updatedAt":"2025-12-21T00:13:09.123697+01:00"}], "createdAt": "2025-12-21T00:13:08.579+0100", "updatedAt": "2025-12-21T00:13:08.579+0100", "hint": {}}
INFO	workflows.custom.[0]	classifier/action_run_workflow.go:49	dummy
INFO	workflows.dummy.[0]	classifier/action_if_else.go:75
INFO	workflows.dummy.[0].if_else.condition	classifier/condition_and.go:44
INFO	workflows.dummy.[0].if_else.condition.and.[0]	classifier/condition_or.go:43
INFO	workflows.dummy.[0].if_else.condition.and.[0].or.[0]	classifier/condition_expression.go:84	false	{"source": "torrent.baseName.matches(keywords.dummy)"}
INFO	workflows.dummy.[0].if_else.condition.and.[0].or.[1]	classifier/condition_expression.go:84	true	{"source": "torrent.baseName.matches(\".*Cap\\\\.\\\\d+.*\")"}
INFO	workflows.dummy.[0].if_else.condition.and.[1]	classifier/condition_expression.go:84	true	{"source": "torrent.files.exists(f, f.extension in extensions.dummy)"}
INFO	workflows.dummy.[0].if_else.if_action	classifier/action_if_else.go:84
INFO	workflows.dummy.[0].if_else.if_action.[0]	classifier/action_if_else.go:75
INFO	workflows.dummy.[0].if_else.if_action.[0].if_else.condition	classifier/condition_expression.go:84	true	{"source": "torrent.baseName.matches(\".*Cap\\\\.\\\\d+.*\")"}
INFO	workflows.dummy.[0].if_else.if_action.[0].if_else.if_action	classifier/action_if_else.go:84
INFO	workflows.dummy.[0].if_else.if_action.[0].if_else.if_action.[0]	classifier/action_set_content_type.go:34	tv_show
INFO	workflows.dummy.[0].if_else.if_action.[1]	classifier/action_add_tag.go:48	[dummy]
INFO	workflows.custom.[1]	classifier/action_run_workflow.go:49	default
INFO	workflows.default.[0]	classifier/action_if_else.go:75
INFO	workflows.default.[0].if_else.condition	classifier/condition_expression.go:84	false	{"source": "([torrent.baseName] + torrent.files.map(f, f.basePath)).join(' ').matches(keywords.banned)"}
INFO	workflows.default.[0].if_else.else_action	classifier/action_if_else.go:89
INFO	workflows.default.[1]	classifier/action_if_else.go:75
INFO	workflows.default.[1].if_else.condition	classifier/condition_expression.go:84	false	{"source": "result.contentType == contentType.unknown"}
INFO	workflows.default.[1].if_else.else_action	classifier/action_if_else.go:89
INFO	workflows.default.[2]	classifier/action_find_match.go:48
INFO	workflows.default.[2].find_match.[0].[0]	classifier/action_parse_date.go:30	<nil>
INFO	workflows.default.[3]	classifier/action_if_else.go:75
INFO	workflows.default.[3].if_else.condition	classifier/condition_and.go:44
INFO	workflows.default.[3].if_else.condition.and.[0]	classifier/condition_expression.go:84	false	{"source": "torrent.hasHintedContentId && !result.hasAttachedContent"}
INFO	workflows.default.[3].if_else.else_action	classifier/action_if_else.go:89
INFO	workflows.default.[4]	classifier/action_if_else.go:75
INFO	workflows.default.[4].if_else.condition	classifier/condition_or.go:43
INFO	workflows.default.[4].if_else.condition.or.[0]	classifier/condition_expression.go:84	true	{"source": "result.contentType in [contentType.movie, contentType.tv_show]"}
INFO	workflows.default.[4].if_else.if_action	classifier/action_if_else.go:84
INFO	workflows.default.[4].if_else.if_action.[0]	classifier/action_find_match.go:48
INFO	workflows.default.[4].if_else.if_action.find_match.[0].[0]	classifier/action_parse_video_content.go:49	result	{"parsed": {"BaseTitle":"*** *** [HDTV 1080p ][Cap 999 ]","ContentType":"tv_show","Date":{"Day":0,"Month":0,"Year":0},"LanguageMulti":false}}
INFO	workflows.default.[5]	classifier/action_if_else.go:75
INFO	workflows.default.[5].if_else.condition	classifier/condition_expression.go:84	true	{"source": "!result.hasAttachedContent && result.hasBaseTitle"}
INFO	workflows.default.[5].if_else.if_action	classifier/action_if_else.go:84
INFO	workflows.default.[5].if_else.if_action.[0]	classifier/action_find_match.go:48
INFO	workflows.default.[5].if_else.if_action.find_match.[0].[0]	classifier/action_if_else.go:75
INFO	workflows.default.[5].if_else.if_action.find_match.[0].[0].if_else.condition	classifier/condition_expression.go:84	true	{"source": "flags.local_search_enabled"}
INFO	workflows.default.[5].if_else.if_action.find_match.[0].[0].if_else.if_action	classifier/action_if_else.go:84
INFO	workflows.default.[5].if_else.if_action.find_match.[0].if_else.if_action.[0]	classifier/action_attach_local_content_by_search.go:39	local search failed	{"type": "tv_show", "base_title": "*** *** [HDTV 1080p ][Cap 999 ]", "date": "-0001-11-30"}
INFO	workflows.default.[5].if_else.if_action.find_match.[1].[0]	classifier/action_if_else.go:75
INFO	workflows.default.[5].if_else.if_action.find_match.[1].[0].if_else.condition	classifier/condition_expression.go:84	false	{"source": "flags.apis_enabled && flags.tmdb_enabled"}
INFO	workflows.default.[5].if_else.if_action.find_match.[1].[0].if_else.else_action	classifier/action_if_else.go:89
INFO	workflows.default.[5].if_else.if_action.find_match.[1].if_else.else_action.[0]	classifier/action_unmatched.go:27
INFO	workflows.default.[6]	classifier/action_if_else.go:75
INFO	workflows.default.[6].if_else.condition	classifier/condition_or.go:43
INFO	workflows.default.[6].if_else.condition.or.[0]	classifier/condition_expression.go:84	false	{"source": "result.contentType in flags.delete_content_types"}
INFO	workflows.default.[6].if_else.condition.or.[1]	classifier/condition_expression.go:84	false	{"source": "flags.delete_xxx && result.contentType == contentType.xxx"}
INFO	workflows.default.[6].if_else.else_action	classifier/action_if_else.go:89
INFO	runner	classifier/runner.go:89	done	{"workflow": "custom", "result": {"BaseTitle":"*** *** [HDTV 1080p ][Cap 999 ]","ContentType":"tv_show","Date":{"Day":0,"Month":0,"Year":0},"LanguageMulti":false,"Tags":{"dummy":{}}}}

New actions and conditions should add log messages with ctx.logger.

@syp1975 syp1975 marked this pull request as ready for review December 27, 2025 19:53
giorgiobrullo added a commit to giorgiobrullo/bitmagnet that referenced this pull request Mar 1, 2026
Cherry-pick of PR bitmagnet-io#467. Adds CLASSIFIER_VERBOSE=true config option
that logs step-by-step classifier decisions including condition
evaluation, content matching, TMDB lookups, and final results.
Invaluable for debugging custom classifier workflows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant