neo4j / graphql

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
https://neo4j.com/docs/graphql-manual/current/
Apache License 2.0
502 stars 148 forks source link

Enable file logging #2647

Closed Hashdhi closed 1 year ago

Hashdhi commented 1 year ago

We wanted to enabled file logging .

  1. had tried with log4js . Log4js ,log level were coming as upper case(DEBUG/INFO) and it is failing as invalid log level neo4j internal expecting debug/info in lower case.

  2. tried using winston logging and didnt worked .

Could you please provide steps to enable file logging ? We are using console now const loggingConfig = {logging: neo4j.logging.console('debug')};

tbwiss commented 1 year ago

As of today, we have no logger or logging framework/system in place for the @neo4j/graphql library. We do however have debug logging, see docs.

Other (JS/TS-based products) at Neo4j are using loglevel, with its plugin system one should be able to store logs to files (or remote log servers and remote logging service).

If you would like to use file logging as a native feature of the @neo4j/graphql library please consider writing it up in a feature request!

Hashdhi commented 1 year ago

Thanks Thomas sure will raise feature req for logging as a native feature of the @neo4j/graphql moreover dont want as native support . Why its not supporting standard logging libraries [log4js,winston] ?

tbwiss commented 1 year ago

Could you post a (simplified) example code snippet of how the logging library log4js is used in your use case?

Hashdhi commented 1 year ago

Please find the attached log4j config and index.js . log-issue.zip

All i wanted is log to a file [Daily rotation and fixed message pattern layout so that I can feed the log file to ELK stack ]

Open to use any logging framework .

Please let me know if you need more detail .

loggingConfig===DEBUG I had printed in logger.js ======DEBUG level passed to logger.js it checks with enum levels are: error,warn,info,debug

Below is the error snippet

node_modules\neo4j-driver-core\lib\internal\logger.js:196 throw (0, error_1.newError)("Illegal logging level: " + configuredLevel + ". Supported levels are: " + Object.keys(levels)); ^

Neo4jError: Illegal logging level: DEBUG. Supported levels are: error,warn,info,debug at new Neo4jError (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver-core\lib\error.js:74:28) at newError (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver-core\lib\error.js:93:12) at extractConfiguredLevel (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver-core\lib\internal\logger.js:196:40) at Logger.create (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver-core\lib\internal\logger.js:72:25) at new Driver (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver-core\lib\driver.js:81:37) at Driver._createSuperInternal (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver\lib\driver.js:24:317) at new Driver (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver\lib\driver.js:52:19) at Object.driver (C:\selva\BT\neo4j-graphql\node_modules\neo4j-driver\lib\index.js:480:10) at Object. (C:\selva\BT\neo4j-graphql\index.js:31:22) at Module._compile (node:internal/modules/cjs/loader:1159:14) { constructor: [Function: Neo4jError], code: 'N/A' }

tbwiss commented 1 year ago

@Hashdhi, below is the modified code you sent of a fileLogger which writes the logs of the neo4j-driver to a app.log file.

const { ApolloServer } = require("apollo-server");
const { Neo4jGraphQL, CypherRuntime } = require("@neo4j/graphql");
const neo4j = require("neo4j-driver");
const fs = require("fs");
const path = require("path");
const dotenv = require("dotenv");
const log4js = require('log4js');
// Load contents of .env as environment variables
dotenv.config();

const typeDefs = fs
  .readFileSync(path.join(__dirname, "schema.graphql"))
  .toString("utf-8");

log4js.configure({ // just copied the content from the log4js.json file to share the code easier.
  appenders: {
    console: {
      type: "console",
      layout: {
        type: "pattern",
        pattern: "%d - %c:[%p]: %m",
      },
    },
    fileLog: {
      type: "file",
      filename: "app.log",
      layout: {
        type: "pattern",
        pattern: "%d - %c:[%p]: %m",
      },
    },
  },
  categories: {
    file: {
      appenders: ["fileLog"],
      level: "debug",
    },
    default: {
      appenders: ["console", "fileLog"],
      level: "debug",
    },
  },
});

const fileLogger = log4js.getLogger("fileLog"); // instantiate the file logger prior to opening a connection to the Neo4j database

const connectionConfig = {
  maxConnectionLifetime: 1 * 60 * 60 * 1000,
  maxConnectionPoolSize: 100,
  connectionAcquisitionTimeout: 1 * 60 * 1000,
  connectionTimeout: 20 * 1000,
  logging: { // More information here: https://neo4j.com/docs/api/javascript-driver/current/function/index.html#static-function-driver 
    level: "debug",  // default level is 'info'. Change to your requirements
    logger: (level, message) => {
      console.log(`level: ${level}, message: ${message}`); // <- this is just to showcase. not required.
      fileLogger.log(message); // <- Likely needs to be adjusted to fit your requirements.
    },
  },
  queryOptions: {
    runtime: CypherRuntime.INTERPRETED,
  }
};

// Create Neo4j driver instance
const driver = neo4j.driver(
  process.env.NEO4J_URI,
  neo4j.auth.basic(process.env.NEO4J_USER, process.env.NEO4J_PASSWORD),
  connectionConfig
);

const neoSchema = new Neo4jGraphQL({ typeDefs, driver });

neoSchema.getSchema().then((schema) => {
  const server = new ApolloServer({
    schema: schema
  });

  server.listen().then(({ url }) => {
    console.log(`${global.Date.now()} GraphQL server ready on ${url}`);
  });
});
Hashdhi commented 1 year ago

Thanks a lot Thomas