Sie können definitiv viel Zeit damit verbringen, dieses Problem zu überarbeiten.
Für Sprachen mit kanonischen Protokollierungsimplementierungen müssen Sie den kanonischen Protokollierer nur direkt in jeder Klasse instanziieren.
Versuchen Sie bei Sprachen ohne kanonische Implementierung, ein Protokollierungs-Fassaden-Framework zu finden und sich daran zu halten. slf4j ist eine gute Wahl in Java.
Persönlich würde ich mich lieber an eine einzelne konkrete Protokollierungsimplementierung halten und alles an syslog senden. Alle guten Tools zur Protokollanalyse können Sysout-Protokolle von mehreren App-Servern zu einem umfassenden Bericht zusammenfassen.
Wenn eine Funktionssignatur einen oder zwei Abhängigkeitsdienste sowie einige "echte" Argumente enthält, platziere ich die Abhängigkeiten zuletzt:
int calculateFooBarSum(int foo, int bar, IntegerSummationService svc)
Da meine Systeme in der Regel nur fünf oder weniger solcher Dienste enthalten, stelle ich immer sicher, dass die Dienste über alle Funktionssignaturen hinweg in derselben Reihenfolge enthalten sind. Die alphabetische Reihenfolge ist so gut wie jede andere. (Abgesehen davon: Wenn Sie diesen methodischen Ansatz für den Umgang mit Mutex beibehalten, verringern Sie auch die Wahrscheinlichkeit, dass Deadlocks auftreten.)
Wenn Sie feststellen, dass Sie mehr als ein Dutzend Abhängigkeiten in Ihre App einschleusen, muss das System wahrscheinlich in separate Subsysteme aufgeteilt werden (kann ich sagen, Microservices?).