Elasticsearch: Impossible d'utiliser le client Java en raison de NoClassDefFoundError : org/apache/log4j/Priority

Créé le 13 juil. 2016  ·  53Commentaires  ·  Source: elastic/elasticsearch

J'ai dû ajouter ces dépendances pour résoudre:

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>log4j-over-slf4j</artifactId>
            <version>1.5.11</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-nop</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

Version d'Elasticsearch :
5.0.0-alpha4

Version JVM :
version Java "1.8.0_60"
Environnement d'exécution Java(TM) SE (version 1.8.0_60-b27)
Machine virtuelle serveur Java HotSpot(TM) 64 bits (version 25.60-b23, mode mixte)

Version du système d'exploitation :
OSX 10.11.5

Description du problème, y compris le comportement attendu par rapport au comportement réel :
Impossible d'utiliser le client Java, en raison de NoDefFound de ESLogger.

Étapes à reproduire :

  1. Créer un projet Maven
  2. Dépend de
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>5.0.0-alpha4</version>
        </dependency>
  1. Essayez de créer un client :
    private Client client = TransportClient.builder().build().addTransportAddress(
            new InetSocketTransportAddress(new InetSocketAddress("localhost", 9300)));

Fournir des journaux (le cas échéant) :

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Priority
    at org.elasticsearch.common.logging.ESLoggerFactory.getLogger(ESLoggerFactory.java:42)
    at org.elasticsearch.common.logging.ESLoggerFactory.getLogger(ESLoggerFactory.java:46)
    at org.elasticsearch.common.logging.Loggers.getLogger(Loggers.java:123)
    at org.elasticsearch.common.settings.Setting.<clinit>(Setting.java:110)
    at org.elasticsearch.common.logging.ESLoggerFactory.<clinit>(ESLoggerFactory.java:33)
    at org.elasticsearch.common.logging.Loggers.getLogger(Loggers.java:119)
    at org.elasticsearch.transport.netty.NettyInternalESLoggerFactory.newInstance(NettyInternalESLoggerFactory.java:33)
    at org.elasticsearch.common.netty.NettyUtils$1.newInstance(NettyUtils.java:91)
    at org.jboss.netty.logging.InternalLoggerFactory.getInstance(InternalLoggerFactory.java:67)
    at org.jboss.netty.logging.InternalLoggerFactory.getInstance(InternalLoggerFactory.java:60)
    at org.jboss.netty.util.ThreadRenamingRunnable.<clinit>(ThreadRenamingRunnable.java:32)
    at org.elasticsearch.common.netty.NettyUtils.<clinit>(NettyUtils.java:95)
    at org.elasticsearch.transport.netty.NettyTransport.<clinit>(NettyTransport.java:145)
    at org.elasticsearch.client.transport.TransportClient$Builder.newPluginService(TransportClient.java:108)
    at org.elasticsearch.client.transport.TransportClient$Builder.build(TransportClient.java:120)
    at edge.model.TestElastic.<clinit>(TestElastic.java:10)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority
    at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 16 more

Commentaire le plus utile

Comme je viens de rencontrer le même problème, je voudrais partager ma solution à cela. Je sais que c'est plutôt grossier, mais peut fonctionner au moins pour certaines personnes.

https://github.com/ctron/de.dentrassi.elasticsearch.log4j2-mock/

J'ai écrit une petite implémentation fictive de log4j2-core qui a suffisamment de fonctionnalités pour faire croire à Elasticsearch qu'il a correctement configuré log4j2. Donc, si vous l'utilisez en combinaison avec org.apache.logging.log4j:log4j-to-slf4j , vous devriez avoir toute votre sortie sur SLF4J et simplement ignorer les appels internes à log4j-core que fait ES pour manipuler la configuration log4j pendant l'exécution.

Tous les 53 commentaires

Salut @fakeh

Merci d'avoir essayé l'alpha. Ce que vous signalez est correct, et il est répertorié dans les modifications avec rupture : https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_java_api_changes.html#_elasticsearch_will_no_longer_detect_logging_implementations

Merci pour la réponse rapide. Si les bibliothèques sont nécessaires, pourquoi ne pas extraire les dépendances de manière transitive ?

Nous n'utilisons pas du tout de dépendances transitives.

Salut @clintongormley , existe-t-il un document expliquant la raison pour laquelle Elasticsearch 5.0 Java SDK utilise Log4j2 au lieu de Slf4j qui est à mon humble avis beaucoup moins intrusif?

Salut @clintongormley , existe-t-il un document expliquant la raison pour laquelle Elasticsearch 5.0 Java SDK utilise Log4j2 au lieu de Slf4j qui est à mon humble avis beaucoup moins intrusif?

Étant donné qu'Elasticsearch est un serveur , nous ne ressentons pas le besoin de parler à une couche d'abstraction de journalisation. Nous l'aurions utilisé si nous avions mieux aimé l'API, mais ce n'est pas le cas.

Le client de transport est un problème dans ce cas, car il utilise la base de code d'Elasticsearch comme s'il s'agissait d'une bibliothèque. Ce n'est pas une chose avec laquelle nous pouvons vivre à long terme car cela nous enferme dans les choix que nous pouvons faire. Ainsi, le client REST java elasticsearch devient une chose, bien qu'il soit honnêtement de niveau trop bas pour que les développeurs Java apprécient vraiment de l'utiliser à ce stade.

Malheureusement, le client Java Elasticsearch n'est pas un serveur. Si nous voulons utiliser l'API Jar dans une de nos applications, ce choix nous oblige à utiliser log4j.

Malheureusement, il ne semble pas y avoir de bibliothèque log4j2-over-slf4j , la bibliothèque log4j-over-slf4j ne semble fonctionner qu'avec log4j 1.x.

Éditer:
Je pense avoir trouvé un pont qui permet de continuer à utiliser le logback, voir http://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-to-slf4j/2.7

Malheureusement, le client Java Elasticsearch n'est pas un serveur. Si nous voulons utiliser l'API Jar dans une de nos applications, ce choix nous oblige à utiliser log4j.

C'est le problème avec le client de transport. C'est le serveur. Les mêmes morceaux. Vous ne voulez pas que ce soit le serveur et nous non plus. Ainsi le client REST qui est malheureusement loin d'être prêt.

Je pense avoir trouvé un pont qui permet de continuer à utiliser le logback, voir http://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-to-slf4j/2.7

Oui, je n'ai pas lu votre modification et j'étais sur le point de publier https://logging.apache.org/log4j/2.0/log4j-to-slf4j/index.html qui ressemble au même lien.

Euh, on dirait qu'il parle du même artefact, plutôt.

@davidbilge Peut-être qu'entre-temps, vous pouvez masquer le serveur elasticsearch lorsqu'il est utilisé avec le client de transport ?
Dans ce cas, cet article peut vous aider : https://www.elastic.co/blog/to-shade-or-not-to-shade

@dadoonet Merci pour l'idée, je vais me pencher là-dessus. Pour l'instant, je suis parfaitement bien en utilisant le pont log4j-to-slf4j .

@davidbilge Je me demande s'il vaut la peine d'ajouter cela dans la doc. Je veux dire dans la documentation Java de Transport Client. Souhaitez-vous décrire ce que vous avez fait pour aider les autres utilisateurs ?
Comme ce qui a été fait avec cette page spécifique? https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/_deploying_in_jboss_eap6_module.html

Chose sûre. Les dépendances dans mon pom.xml ressemblent essentiellement à ceci :

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>transport</artifactId>
    <version>5.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-to-slf4j</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.7</version>
</dependency>

Cela résout les java.lang.ClassNotFoundException manquants si vous utilisez un enregistreur qui implémente slf4j (comme le fait logback).

C'est le problème avec le client de transport. C'est le serveur

Le client n'est pas le serveur. Vous ne pouvez pas dire "le client est le serveur", c'est absurde, cela n'a aucun sens. Le client est le client, le serveur est le serveur, point final.

Je comprends ce que vous voulez dire - le client réutilise certaines classes du serveur.

il utilise la base de code d'Elasticsearch comme s'il s'agissait d'une bibliothèque

C'est clair.

Mais, lorsque vous l'épelez réellement de cette façon, par exemple de manière correcte, le correctif devient évident - découplez les classes partagées du serveur et placez-les dans une bibliothèque séparée, ne dépendant pas de Log4J. Banal.

Le client n'est pas le serveur. Vous ne pouvez pas dire "le client est le serveur", c'est absurde, cela n'a aucun sens. Le client est le client, le serveur est le serveur, point final.

Mais, quand vous l'épelez réellement de cette façon, par exemple de manière correcte

Celles-ci établissent une relation d'opposition plutôt qu'une relation de collaboration. Nous préférons fortement ce dernier, et cela compte beaucoup pour nous.

Je comprends ce que vous voulez dire - le client réutilise certaines classes du serveur.

Cela ne peut pas être à la fois "absurde" et "n'a aucun sens", et vous comprenez ce qu'il veut dire. Vous avez laissé de côté une phrase clé qui explique exactement ce qu'il voulait dire :

C'est le serveur. Les mêmes morceaux .

Les deux phrases vont ensemble.

alors le correctif devient évident - découplez les classes partagées du serveur et placez-les dans une bibliothèque séparée [...] Trivial.

La solution est évidente, mais évidente n'est pas la même chose que triviale. Il y a beaucoup d'enchevêtrement. Nous connaissons le correctif, nous voulons faire le correctif, mais à ce sujet, pour l'effort du client, nous privilégions le pragmatisme à l'idéalisme (voir les commentaires précédents sur ce même sujet).

Ça ne peut pas être à la fois "absurde" et "n'avoir aucun sens"

D'accord. Choisissez celui que vous aimez le plus.

Les deux phrases vont ensemble.

Vous réalisez les implications de déclarer que deux bases de code qui partagent des classes communes sont les mêmes ("les classes de partage client et serveur, donc le client est le serveur") ? Prenons un exemple : Tomcat utilise la journalisation java util et Weblogic utilise la journalisation java util - donc Tomcat est Weblogic (mais pas l'inverse) ? Absurde ou insensé - choisissez-en un que vous aimez.

La solution est évidente, mais évidente n'est pas la même chose que triviale

Vous choisissez des mots au lieu de comprendre le sens derrière les mots. En parlant de confrontation - ne choisissons pas les mots et ne commençons pas un concours de démagogie, n'est-ce pas ?

Il serait intéressant de savoir quel type d'enchevêtrement empêche de simplement déplacer des classes partagées dans une bibliothèque partagée. Les informations sur le problème - et non les opinions des commentaires sur le problème - seraient collaboratives au lieu d'être contradictoires.

Bravo @mvmn - façon de tuer un fil...

Les informations sur le problème - et non les opinions des commentaires sur le problème - seraient collaboratives au lieu d'être contradictoires.

Les dépendances ci-dessus n'aident pas si j'exécute elasticsearch (v5.1.2) intégré (nous le faisons pour les tests)...

dès que je crée un index, par exemple

        CreateIndexRequest createIndexRequest = new CreateIndexRequest("indexname");
        IndicesAdminClient indices = es.getNode().client().admin().indices();
        indices.create(createIndexRequest).actionGet();

J'ai compris:

11:27:32.397 [main] INFO  org.elasticsearch.http.HttpServer - publish_address {127.0.0.1:9200}, bound_addresses {[fe80::1]:9200}, {[::1]:9200}, {127.0.0.1:9200}
11:27:32.397 [main] INFO  org.elasticsearch.node.Node - started
Exception in thread "elasticsearch[V3ONMVd][clusterService#updateTask][T#1]" java.lang.NoClassDefFoundError: org/apache/logging/log4j/core/config/Configurator
    at org.elasticsearch.common.logging.Loggers.setLevel(Loggers.java:149)
    at org.elasticsearch.common.logging.Loggers.setLevel(Loggers.java:144)
    at org.elasticsearch.index.SearchSlowLog.setLevel(SearchSlowLog.java:111)
    at org.elasticsearch.index.SearchSlowLog.<init>(SearchSlowLog.java:106)
    at org.elasticsearch.index.IndexModule.<init>(IndexModule.java:127)
    at org.elasticsearch.indices.IndicesService.createIndexService(IndicesService.java:421)
    at org.elasticsearch.indices.IndicesService.createIndex(IndicesService.java:394)
    at org.elasticsearch.cluster.metadata.MetaDataCreateIndexService$1.execute(MetaDataCreateIndexService.java:352)
    at org.elasticsearch.cluster.ClusterStateUpdateTask.execute(ClusterStateUpdateTask.java:45)
    at org.elasticsearch.cluster.service.ClusterService.runTasksForExecutor(ClusterService.java:581)
    at org.elasticsearch.cluster.service.ClusterService$UpdateTask.run(ClusterService.java:920)
    at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingRunnable.run(ThreadContext.java:458)
    at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.runAndClean(PrioritizedEsThreadPoolExecutor.java:238)
    at org.elasticsearch.common.util.concurrent.PrioritizedEsThreadPoolExecutor$TieBreakingPrioritizedRunnable.run(PrioritizedEsThreadPoolExecutor.java:201)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.core.config.Configurator
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

il semble que nous soyons condamnés à passer à log4j simplement parce que nous utilisons elasticsearch intégré dans nos tests :(

il semble que nous soyons condamnés à passer à log4j simplement parce que nous utilisons elasticsearch intégré dans nos tests :(

En fait, cela est indiqué dans le fil - vous devez avoir Log4J dans le chemin de classe si vous utilisez ElasticSearch (que ce soit un serveur ou un client - peu importe).

Vous pouvez toujours utiliser un autre système de journalisation - mais vous devez avoir des éléments Log4J dans votre chemin de classe (ce qui peut provoquer des conflits pour certains systèmes de journalisation ou la détection de chemin de classe à l'aide d'éléments tels que Spring Boot).

Quelqu'un a-t-il réussi à exécuter la version 5.* de TransportClient dans l'application Spring Boot/Spring IO Platform ?
Si oui, veuillez partager comment vous avez réussi à résoudre les conflits de dépendance.
Pour moi, c'est soit ClassNotFoundException pour org.apache.logging.log4j.core.config.Configurator lorsque log4j-core n'est pas ajouté en tant que dépendance ou SLF4JLoggerContext ne peut pas être converti en org.apache.logging.log4j.core.LoggerContext avec l'ajout de log4j- dépendance centrale.
J'utilise SLF4J avec Logback :

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.8</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.1.8</version>
    </dependency>        
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>transport</artifactId>
        <version>5.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-to-slf4j</artifactId>
        <version>2.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.7</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>

J'essaie d'éviter l'excès d'ombrage de dépendance que j'ai vu proposé à certains endroits.

@kjussakov Pourriez-vous s'il vous plaît ouvrir un sujet sur le forum et créer un lien vers celui-ci à partir d'ici ? Cependant, lorsque vous ouvrez ce sujet, veuillez fournir une trace de pile, je ne peux pas vous aider sans trace de pile. Avant de faire cela, pourriez-vous s'il vous plaît regarder mon exemple sur # 22671 et voir s'il vous aide à résoudre vos problèmes ? En particulier, je pense que vous pourriez être en mesure de supprimer la dépendance log4j-api.

Essayez ceci dans votre pom.xml

    <properties>
        <elasticsearch.version>5.1.2</elasticsearch.version>
    </properties>

@kjussakov pouvez-vous ajouter un commentaire avec le lien vers le nouveau sujet ?

Salut tout le monde,
Merci pour votre réponse rapide! Je vais commencer par faire un exemple minimal possible qui a le problème que j'ai décrit, puis ouvrir un nouveau sujet dans le forum. J'ai déjà commencé avec un simple projet maven avec les dépendances que j'ai mentionnées ci-dessus. Cela suit également la doc officielle 5.*

Sans aucune dépendance liée à Spring, il semble que cela fonctionne, alors je vais maintenant essayer d'en ajouter d'autres jusqu'à ce que je le casse.

Vous tiendrons au courant.

Meilleures salutations,
Rumen

Et voici le lien vers le nouveau sujet

Je décris la solution de contournement que j'ai trouvée pour résoudre la dépendance log4j lors de l'exécution de nos tests avec le nœud Elasticsearch intégré.

@kjussakov Ajouter

compile group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: '2.7'

Cela fonctionne pour moi avec Spring Boot 1.4.2.

Salut,
J'utilise la configuration ci-dessous avec elasticsearch 5.2.1, et j'obtiens toujours l'erreur java.lang.ClassNotFoundException: org.apache.logging.log4j.core.Filter.

Quelqu'un peut-il m'aider à résoudre ce problème ?

ma configuration:
"org.slf4j:slf4j- api:1.7.21 ",
"org.apache.logging.log4j:log4j- api:2.7 ",
"org.apache.logging.log4j:log4j-to-slf4j:2.7",

Trace de la pile:
Exception dans le thread "principal" java.lang.NoClassDefFoundError : org/apache/logging/log4j/core/Filter
à java.lang.Class.getDeclaredConstructors0 (méthode native)
à java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
à java.lang.Class.getConstructor0(Class.java:3075)
à java.lang.Class.getConstructor(Class.java:1825)
sur org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:134)
sur org.springframework.boot.logging.LoggingSystem.get(LoggingSystem.java:125)
à org.springframework.boot.logging.LoggingApplicationListener.onApplicationStartedEvent(LoggingApplicationListener.java:189)
à org.springframework.boot.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:173)
à org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:163)
à org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:136)
à org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:119)
à org.springframework.boot.context.event.EventPublishingRunListener.publishEvent(EventPublishingRunListener.java:111)
à org.springframework.boot.context.event.EventPublishingRunListener.started(EventPublishingRunListener.java:60)
à org.springframework.boot.SpringApplicationRunListeners.started(SpringApplicationRunListeners.java:48)
à org.springframework.boot.SpringApplication.run(SpringApplication.java:293)
à org.springframework.boot.SpringApplication.run(SpringApplication.java:1112)
à org.springframework.boot.SpringApplication.run(SpringApplication.java:1101)
sur com.audiencescience.media.search.Application.main(Application.java:14)
Causé par : java.lang.ClassNotFoundException : org.apache.logging.log4j.core.Filter
sur java.net.URLClassLoader.findClass(URLClassLoader.java:381)
à java.lang.ClassLoader.loadClass(ClassLoader.java:424)
à sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
à java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 18 de plus

Le stacktrace n'est pas lié à elasticsearch pour autant que je sache.

@pritamm Si votre problème est lié à Elasticsearch (il n'en a pas l'air), veuillez poser des questions sur le forum .

@nik9000

Nous l'aurions utilisé si nous avions mieux aimé l'API, mais ce n'est pas le cas.

Mon gars...

Bonjour, le fait que l'artefact de transport ES 5.x org.elasticsearch.client attend explicitement log4j2 2.7 a rendu les choses assez difficiles pour nous. Je ne comprends pas la raison exacte pour laquelle il n'utilise pas l'API slf4j. L'utilisation log4j-over-slf4j n'est pas une option car il y aura très probablement log4j-slf4j-impl dans le chemin de classe pour traiter les journaux des bibliothèques "standard" qui ne font pas de choix explicite sur le cadre de journalisation.

Notre cas d'utilisation particulier - pas si fantaisiste :
Nous utilisons le client ES 5.x dans le code pour une topologie Storm. Les packs de distribution Storm log4j2 2.1 - qui se trouve sur le chemin de classe de tous les processus Storm sur le cluster. Le client ES n'est pas satisfait de cette version en raison de certaines nouvelles modifications de l'API log4j2. Je suppose donc quelles sont les options :

  • remplacer tous les jars log4j2 2.1 sur le cluster Storm par 2.7
  • essayez de lancer un *.jar ombré qui contient log4j2 2.7 avec la relocalisation de org.apache.logging.log4j déplacé vers un autre emplacement, META-INF/log4j-provider.properties mis à jour pour pointer vers ce nouvel emplacement, etc., etc. - a passé une demi-journée dessus, ça ne marche toujours pas !

... ne connaissant pas les fonctionnalités exactes spécifiques à log4j2 sur lesquelles vous comptez (pouvoir enregistrer des objets ?), il semble que l'utilisation de slf4j aurait été plus conviviale :/

Comme je viens de rencontrer le même problème, je voudrais partager ma solution à cela. Je sais que c'est plutôt grossier, mais peut fonctionner au moins pour certaines personnes.

https://github.com/ctron/de.dentrassi.elasticsearch.log4j2-mock/

J'ai écrit une petite implémentation fictive de log4j2-core qui a suffisamment de fonctionnalités pour faire croire à Elasticsearch qu'il a correctement configuré log4j2. Donc, si vous l'utilisez en combinaison avec org.apache.logging.log4j:log4j-to-slf4j , vous devriez avoir toute votre sortie sur SLF4J et simplement ignorer les appels internes à log4j-core que fait ES pour manipuler la configuration log4j pendant l'exécution.

@ctron

https://github.com/ctron/de.dentrassi.elasticsearch.log4j2-mock/

Nice :) Une terrible solution à un problème idiot. Je l'utilise!

@ctron Merci mille fois, cela fonctionne comme un charme. C'est bien de voir que quelqu'un essaie de trouver des solutions alors que les développeurs visent les problèmes 8-(

Nous ne visons pas les problèmes @fjalvingh. En fait, nous nous efforçons de rendre l'utilisation d'Elasticsearch agréable pour les développeurs. Nous prenons cette accusation très au sérieux, alors je vous demande maintenant de préciser ce que vous pensez que nous faisons pour viser les troubles afin que nous puissions rectifier la situation. Sinon, ne lancez pas de telles déclarations aussi librement.

@ctron Pourquoi exactement avez-vous traversé tous les ennuis ? log4j-to-slf4j semble faire exactement ce que vous décrivez. Est-ce que je manque quelque chose?

(voir ma réponse précédente )

@jasontedor Vous déclarez que la séparation des classes partagées en JAR partagé n'est pas triviale, mais vous n'expliquez jamais pourquoi. Nous savons tous les deux qu'il n'y a rien de non trivial dans la création d'un JAR partagé et le déplacement de certaines classes d'un JAR à un autre. Pourquoi ne pas développer le problème réel que vous avez, afin que nous puissions peut-être trouver des solutions pour vous aider à le résoudre, au lieu de simplement nous dire à quel point nous sommes mauvais pour avoir même demandé une solution.

@mvmn Cela a été expliqué précédemment, le client est complètement imbriqué avec le serveur, il y a bien plus à faire que de simplement déplacer des classes partagées.

au lieu de simplement nous dire à quel point nous sommes mauvais pour avoir même demandé une solution

Cela ne s'est jamais produit. Nous ressentons votre douleur. Comme dit déjà dans ce fil : personne n'aime l'enchevêtrement, nous souhaitons que ce ne soit pas une chose, mais nous ne pouvons pas claquer des doigts et le faire disparaître.

Eh bien, @jasontedor , ma remarque est venue d'un peu de frustration. J'ai passé plus d'une journée à mettre à niveau notre application vers ElasticSearch 5.5. Il s'est avéré qu'il y avait énormément de travail pour faire fonctionner un nœud local alors que cela fonctionnait très facilement auparavant. Et la façon de faire fonctionner ce serveur n'était décidément pas évidente.
Le problème supplémentaire causé par ES hard en fonction d'une _implémentation_ de journalisation a causé encore plus de problèmes.

J'ai également été rebuté par la façon dont les discussions se sont déroulées ici. Il est apparu que la forme était plus importante que le fait. Au lieu d'aider à trouver des solutions, il y a des discussions sur la façon de dire les choses correctement.

Le fait d'avoir à approfondir beaucoup de choses, d'avoir à contourner beaucoup de choses faites au code qui rendaient difficile de faire ce qui était auparavant simple, a provoqué ma remarque.

Je suis désolé que vous ayez éprouvé tant de frustration ici en raison de l'infrastructure de journalisation. Je déteste que cela cause de la douleur aux utilisateurs. Pourriez-vous, s'il vous plaît, élaborer sur les détails techniques de ce qui vous a causé de la douleur afin que nous puissions en tenir compte dans notre réflexion ? J'avais espéré que le fait de préciser que nous sommes liés à l'API Log4j mais pas à l'implémentation pour le client aiderait à clarifier la situation. Pouvez-vous expliquer pourquoi ce n'est pas le cas?

Il est apparu que la forme était plus importante que le fait. Au lieu d'aider à trouver des solutions, il y a des discussions sur la façon de dire les choses correctement.

La forme est importante. Nous avons une communauté ici, nous avons des normes, nous les maintiendrons et nous ne tolérerons pas d'être traités comme des adversaires.

De plus, je ne suis pas d'accord, nous n'avons pas aidé dans ce fil. Nous avons fourni des exemples d'implémentations, clarifié les dépendances, écouté les commentaires, etc.

La douleur n'était pas seulement causée par l'infrastructure de journalisation ;) Mon principal défi était de faire fonctionner un nœud de serveur intégré, car c'était la solution choisie il y a quelques années. Cela s'est avéré difficile. Tout d'abord parce que NodeBuilder a été supprimé et même si les notes indiquaient que des fonctionnalités similaires pouvaient être obtenues en utilisant le constructeur Node avec Settings, cela s'est avéré difficile à faire (j'avais besoin d'un plugin pour obtenir la fonctionnalité HTTP et pour cela, vous devez remplacer une classe) .
Après cela, le problème de journalisation est apparu. Le problème principal ici est qu'ES dépend d'une _implémentation_ de journalisation (log4j2-core) car il essaie apparemment de modifier la _configuration_ de journalisation au moment de l'exécution.

L'utilisation d'un bocal de pont fonctionne bien pour basculer les enregistreurs eux-mêmes afin d'envoyer leur sortie à une autre implémentation d'enregistreur. Mais le pont ne contient pas les pièces utilisées par ES pour modifier la configuration (car elles dépendent de l'implémentation). D'où l'erreur, d'où la frustration, et donc le bonheur avec la grande contribution de @ctron .
Changer d'implémentation de journalisation n'est pas un petit problème pour nous. Je pense que ES est un excellent produit, ne vous méprenez pas. Mais avec un grand pouvoir vient une grande responsabilité ;) Donc, faire des changements comme ceux-ci peut faire mal.

En ce qui concerne l'aide, j'étais moins qu'heureux, et cela se voyait.

Je comprends parfaitement que vous vouliez avoir des normes normales de communication. Je ne pense pas avoir franchi une ligne ici.

Je me demande si le type de solution acceptée au problème : l'utilisation du pont log4j-to-slf4j ne comporte pas certains risques. Citant la documentation log4j2 :

L'utilisation de la liaison Log4j 2 SLF4J (log4j-slf4j-impl-2.0.jar) avec l'adaptateur SLF4J (log4j-to-slf4j-2.0.jar) ne doit jamais être tentée, car cela entraînera le routage sans fin des événements entre SLF4J et Log4j 2.

Je pense que l'utilisation de log4j-slf4j-impl est très courante dans les cas où les applications suivent l'approche "standard" consistant à utiliser l'API slf4j et à lier l'implémentation ultérieurement.

Peut-être que les gens se demandaient pourquoi Elasticsearch ne procédait pas de la même manière. Un commentaire plus haut a mentionné que vous n'aimez pas l'API slf4j.

Mon principal défi était de faire fonctionner un nœud de serveur intégré car c'était la solution choisie il y a quelques années.

@fjalvingh Je suis désolé d'apprendre les problèmes que vous rencontrez avec l'intégration du serveur. Malheureusement, nous ne prenons plus en charge ce cas d'utilisation . Je vous encourage à migrer vers une véritable instance de serveur (je suppose que c'est pour les tests, c'est ce que nous encourageons les utilisateurs à faire maintenant).

Le problème principal ici est qu'ES dépend d'une implémentation de journalisation (log4j2-core) car il essaie apparemment de modifier la configuration de journalisation au moment de l'exécution.

C'est correct, le serveur lie la configuration au démarrage et cela nécessite un core. Ce n'est pas le cas pour le client de transport, c'est pourquoi nous pouvons nous en tirer en fonction de l'API mais pas de l'implémentation.

Je comprends parfaitement que vous vouliez avoir des normes normales de communication. Je ne pense pas avoir franchi une ligne ici.

Je suis d'accord, vous n'avez franchi aucune ligne. Cependant, puisque vous avez affirmé que les développeurs visaient les problèmes, puis plus tard que nous nous concentrions sur la forme plutôt que sur les faits au lieu d'aider les utilisateurs, je dois expliquer pourquoi nous nous concentrons sur la forme lorsque nous voyons un comportement non collaboratif que nous ne tolérerons pas, et en désaccord avec vos affirmations selon lesquelles nous visons les problèmes et n'essayons pas d'aider.

Peut-être que les gens se demandaient pourquoi Elasticsearch ne procédait pas de la même manière. Un commentaire plus haut a mentionné que vous n'aimez pas l'API slf4j.

Je peux expliquer cela. Nous avons choisi Log4j comme backend de journalisation. Nous l'avons choisi pour des raisons précises :

  • la flexibilité qu'il offre à nos utilisateurs finaux pour configurer la journalisation (par exemple, journaux roulants, journaux de compression, divers ajouts, fonctionnalités demandées par nos utilisateurs, etc.)
  • nous ne voulons prendre en charge qu'un seul backend de journalisation, en maintenir un est déjà assez difficile
  • fonctionnalités spécifiques de l'API Log4j que nous souhaitons utiliser (comme un exemple parmi d'autres, construction paresseuse de messages paramétrés lorsqu'un certain niveau de journalisation n'est pas activé, par exemple trace)
  • l'utilisation de SLF4J entraînerait encore une autre dépendance

Lorsqu'une abstraction/façade comme SLF4J est utilisée :

  • nous perdons la possibilité d'utiliser des fonctionnalités spécifiques de l'API Log4j que nous voulons utiliser dans l'implémentation du serveur et sommes plutôt liés au plus petit dénominateur commun de l'API de façade (personnellement, j'ai le même problème avec les ORM)
  • il envoie un signal mitigé indiquant qu'il est acceptable d'échanger le backend de journalisation pour le serveur

Dans l'ensemble, il me semble simplement que ES a des priorités différentes de celles de certains de ses utilisateurs. Et ces priorités ont changé avec le temps. Et en général c'est bien.

Mais cela cause également des problèmes aux utilisateurs qui dépendent de ces fonctionnalités. Ces personnes chercheront donc des alternatives et se demanderont peut-être pourquoi ces changements ont été apportés.

Comme ES est un projet open source, le bricoler est une approche valable. Désormais, les personnes derrière ES peuvent aborder cela de deux manières. Prenez ces personnes au sérieux et essayez d'adopter ces solutions de contournement, en leur simplifiant la vie tout en maintenant leurs propres priorités. Ou s'en tenir à leur position et s'en moquer, ce qui compliquera les choses pour les autres à l'avenir.

Je ne pense pas avoir besoin de dire à qui que ce soit quelle est la voie du succès.

Le problème que je vois ici est qu'il a été décidé qu'une couche d'abstraction comme slf4j n'était pas nécessaire sur la base d'une fausse prémisse : que le code qui l'utilisait n'était utilisé que comme serveur, pas comme bibliothèque, alors que ce n'est pas vraiment vrai. Je comprends que l'équipe de développement aimerait que cela ne soit pas vrai à un moment donné dans le futur, mais le fait demeure qu'il _est_ utilisé comme une bibliothèque, et que peut-être la chose la plus conviviale à faire pour les développeurs de la JVM qui ne le font pas (de votre propre aveu) avez d'excellentes alternatives client, à l'exception de celle qui dépend fortement de log4j2, aurait peut-être été d'utiliser slf4j même si vous n'aimiez pas mieux l'API que log4j2.

En ce qui concerne certaines des raisons spécifiques énumérées ci-dessus pour utiliser directement log4j :

la flexibilité qu'il offre à nos utilisateurs finaux pour configurer la journalisation (par exemple, journaux roulants, journaux de compression, divers ajouts, fonctionnalités demandées par nos utilisateurs, etc.)

Autant que je sache, l'utilisation de SLF4J soutenu par log4j n'empêche ni n'élimine cette flexibilité.

nous ne voulons prendre en charge qu'un seul backend de journalisation, en maintenir un est déjà assez difficile

Écrivez donc votre code pour prendre en charge SLF4J, et vos outils de configuration et de maintenance pour prendre en charge un support log4j, et indiquez clairement que l'utilisation d'autres backends dans les serveurs ES n'est pas prise en charge.

Je comprends qu'il y a, comme toujours, des compromis en jeu, mais la discussion jusqu'à présent ne couvre pas vraiment complètement les compromis impliqués dans la décision qui a été réellement prise (c'est-à-dire si une couche d'abstraction doit être utilisée dans le code qui est distribué comme une bibliothèque)

Le problème que je vois ici est qu'il a été décidé qu'une couche d'abstraction comme slf4j n'était pas nécessaire sur la base d'une fausse prémisse : que le code qui l'utilisait n'était utilisé que comme serveur, pas comme bibliothèque, alors que ce n'est pas vraiment vrai.

Je suis désolé, mais c'est tout simplement faux. Nous avons pris en compte l'impact que l'utilisation directe de Log4j aurait sur les utilisateurs du client de transport. Nous n'avions clairement pas prévu tous les problèmes que cela pourrait causer, mais nous l'avons absolument délibéré et avons vraiment considéré l'impact que cela aurait sur nos utilisateurs avant de nous engager dans cette voie.

En ce qui concerne certaines des raisons spécifiques énumérées ci-dessus pour utiliser directement log4j :

la flexibilité qu'il offre à nos utilisateurs finaux pour configurer la journalisation (par exemple, journaux roulants, journaux de compression, divers ajouts, fonctionnalités demandées par nos utilisateurs, etc.)

Autant que je sache, l'utilisation de SLF4J soutenu par log4j n'empêche ni n'élimine cette flexibilité.

Je pense qu'il y a un malentendu ici. Je n'ai pas prétendu ni voulu impliquer que l'utilisation de SLF4J empêcherait cela. J'énumérais simplement les raisons pour lesquelles nous avons choisi Log4j et pourquoi nous avons choisi de ne pas utiliser la façade SLF4J, il n'est pas nécessairement vrai que toutes les raisons fournies couvrent les deux aspects de notre prise de décision ici. Je suis désolé pour la confusion.

Je suis désolé, mais c'est tout simplement faux. Nous avons pris en compte l'impact que l'utilisation directe de Log4j aurait sur les utilisateurs du client de transport. Nous n'avions clairement pas prévu tous les problèmes que cela pourrait causer, mais nous l'avons absolument délibéré et avons vraiment considéré l'impact que cela aurait sur nos utilisateurs avant de nous engager dans cette voie.

Eh bien, vous me pardonnerez peut-être d'avoir fait une hypothèse basée sur ce que j'ai lu dans cette conversation jusqu'à présent. La déclaration faite très tôt dans cette conversation :

Étant donné qu'Elasticsearch est un serveur, nous ne ressentons pas le besoin de parler à une couche d'abstraction de journalisation. Nous l'aurions utilisé si nous avions mieux aimé l'API, mais ce n'est pas le cas.

n'a donné aucune indication que l'attention était accordée aux clients Java à l'époque, et était même au présent, ce qui implique que le besoin d'une couche d'abstraction ne se faisait toujours pas sentir. Cela dit, je vous fais confiance, mais l'impression que j'ai en lisant cette conversation était que le client du transport était une réflexion après coup, donc je suppose qu'il y avait un problème de mauvaise communication là-bas.

J'aimerais vraiment résoudre les problèmes techniques que les utilisateurs rencontrent ici. Je pense que les problèmes réels se perdent dans la discussion (cela ne veut pas dire que nous devrions arrêter la discussion, nous ne devrions pas nous arrêter car nous apprécions vraiment les commentaires de la communauté ici).

Je voudrais demander ceci : si vous rencontrez un problème technique avec une configuration prise en charge (c'est-à-dire non intégrée, ce qui a été soulevé comme un problème ici à plusieurs reprises, mais nous ne le prenons pas en charge), veuillez ouvrir un nouveau problème, envoyez-moi un ping sur le problème, et un lien vers celui-ci à partir d'ici. Si vous rencontrez un problème technique couvert par un problème nouvellement ouvert, veuillez commenter ou 👍 le problème.

Eh bien, vous me pardonnerez peut-être d'avoir fait une hypothèse basée sur ce que j'ai lu dans cette conversation jusqu'à présent.

Oui bien sûr!

La déclaration faite très tôt dans cette conversation :

Étant donné qu'Elasticsearch est un serveur, nous ne ressentons pas le besoin de parler à une couche d'abstraction de journalisation. Nous l'aurions utilisé si nous avions mieux aimé l'API, mais ce n'est pas le cas.

Cette déclaration est regrettable car elle ne reflète pas correctement la réalité des conversations et des décisions internes (je suis désolé @ nik9000); étant donné cette déclaration, je peux voir pourquoi vous êtes arrivé à la conclusion que vous avez faite. Pour mémoire :

  • nous avons eu des conversations internes sur l'impact que le passage à Log4j aurait sur les utilisateurs du client de transport
  • nous ne sommes pas parvenus à la conclusion de le faire sauter en pensant uniquement au serveur ou parce que le client de transport s'en va
  • au lieu de cela, nous sommes arrivés à la conclusion que l'utilisation du pont résoudrait les besoins que nous avions prévus
  • nous avons fourni de la documentation depuis le début sur la façon d'utiliser un autre enregistreur
  • nous avons envisagé d'écrire un article de blog couvrant cette transition, y compris l'impact sur le client de transport (bien que nous ayons finalement décidé que la documentation ci-dessus serait suffisante)
  • J'ai personnellement expérimenté différents backends de journalisation avec le client de transport pour m'assurer que ce que nous voulions ici fonctionnerait comme prévu

De toute évidence, le monde réel est plus désordonné que les échantillons que j'ai expérimentés, il semble donc qu'il y ait des problèmes imprévus que nous devons résoudre. Énumérons clairement ces problèmes et voyons ce que nous pouvons faire .

Prenez ces personnes au sérieux et essayez d'adopter ces solutions de contournement, en leur simplifiant la vie tout en maintenant leurs propres priorités. Ou s'en tenir à leur position et s'en moquer, ce qui compliquera les choses pour les autres à l'avenir.

Désolé, c'est une fausse dichotomie.

Donc pour le moment, la meilleure solution est le clige de @ctron (merci @ctron !!) ?
Ou est-ce que j'ai raté quelque chose dans ce fil trop long?

@ctron , merci beaucoup !

Alors que les gars ici ont passé BEAUCOUP de temps à méta-discuter de l'utilisation des bons mots dans la discussion, @ctron a réussi ! Tu es le gagnant absolu, mon frère !

Cette page vous a été utile?
0 / 5 - 0 notes