mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
added different logging strategies
This commit is contained in:
parent
eeacff886f
commit
3ecd594b81
@ -62,6 +62,8 @@ Also now all
|
||||
* create and update dates in entities now use date with fractional seconds.
|
||||
* `@PrimaryGeneratedColumn` decorator now accept generation strategy as first argument (default is `increment`), instead of column type.
|
||||
Column type must be passed in options object, e.g. `@PrimaryGeneratedColumn({ type: "bigint"})`
|
||||
* Logger interface has changed. Custom logger supply mechanism has changed
|
||||
* Now `logging` options in connection options is simple "true", or "all", or list of logging modes can be supplied
|
||||
|
||||
### DEPRECATIONS
|
||||
|
||||
@ -83,6 +85,7 @@ Also now all
|
||||
* sql queries are highlighted in console
|
||||
* added `@Generated` decorator. It can accept `strategy` option with values `increment` and `uuid`.
|
||||
Default is `increment`. It always generates value for column, except when column defined as `nullable` and user sets `null` value in to column.
|
||||
* added logging of log-running requests
|
||||
|
||||
### OTHER API CHANGES
|
||||
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
# Extra features
|
||||
|
||||
* Using custom logger
|
||||
* Using in browsers
|
||||
|
||||
155
docs/logging.md
Normal file
155
docs/logging.md
Normal file
@ -0,0 +1,155 @@
|
||||
# Logging
|
||||
|
||||
* Enabling logging
|
||||
* Logging options
|
||||
* Log long-running sql queries
|
||||
* Changing default logger
|
||||
* Using custom logger
|
||||
|
||||
## Enabling logging
|
||||
|
||||
You can enable all queries logging by simply setting `logging: true` in your connection options:
|
||||
|
||||
```typescript
|
||||
{
|
||||
name: "mysql",
|
||||
type: "mysql",
|
||||
host: "localhost",
|
||||
port: 3306,
|
||||
username: "test",
|
||||
password: "test",
|
||||
database: "test",
|
||||
...
|
||||
logging: true
|
||||
}
|
||||
```
|
||||
|
||||
This configuration will enable all executing queries logging + errors of failed queries.
|
||||
|
||||
## Logging options
|
||||
|
||||
You can enable different types of logging in connection options:
|
||||
|
||||
```typescript
|
||||
{
|
||||
host: "localhost",
|
||||
...
|
||||
logging: ["query", "error"]
|
||||
}
|
||||
```
|
||||
|
||||
If you want to enable only logging of failed queries then only enable `error` in configuration:
|
||||
|
||||
```typescript
|
||||
{
|
||||
host: "localhost",
|
||||
...
|
||||
logging: ["error"]
|
||||
}
|
||||
```
|
||||
|
||||
There are few other options you can use:
|
||||
|
||||
* `query` - enables all query logging
|
||||
* `error` - enables failed query error logging
|
||||
* `schema` - enables schema build process logging
|
||||
* `warn` - enables internal orm warning messages logging
|
||||
* `info` - enables internal orm informative messages logging
|
||||
* `log` - enables internal orm log messages logging
|
||||
|
||||
You can specify as many of logging options as needed.
|
||||
If you want to enable all logging you can simply specify `logging: "all"`:
|
||||
|
||||
```typescript
|
||||
{
|
||||
host: "localhost",
|
||||
...
|
||||
logging: "all"
|
||||
}
|
||||
```
|
||||
|
||||
## Log long-running queries
|
||||
|
||||
If you have performance issues you can log queries that execute too much time
|
||||
by setting `maxQueryExecutionTime` option in connection options:
|
||||
|
||||
```typescript
|
||||
{
|
||||
host: "localhost",
|
||||
...
|
||||
maxQueryExecutionTime: 1000
|
||||
});
|
||||
```
|
||||
|
||||
This code will log all queries which run more then `1 second`.
|
||||
|
||||
## Changing default logger
|
||||
|
||||
There are several loggers TypeORM ships with 3 different types of loggers:
|
||||
|
||||
* `advanced-console` - this is default logger which logs all messages into console using color
|
||||
and sql syntax highlighting (using [chalk]() package)
|
||||
* `simple-console` - this is simple console logger which is exactly the same as advanced, but it does not use any color highlighting.
|
||||
This logger can be used if you have problems / or don't like colorized logs
|
||||
* `file` - this logger writes all logs into `ormlogs.log` file in the root folder of your project (near `package.json` and `ormconfig.json`)
|
||||
|
||||
You can enable any of them in connection options this way:
|
||||
|
||||
```typescript
|
||||
{
|
||||
host: "localhost",
|
||||
...
|
||||
logger: "simple-console",
|
||||
logging: true
|
||||
}
|
||||
```
|
||||
|
||||
## Using custom logger
|
||||
|
||||
You can create your own logger class by implementing `Logger` interface and
|
||||
specifying your custom logger in connection options:
|
||||
|
||||
```typescript
|
||||
import {Logger} from "typeorm";
|
||||
|
||||
export class MyCustomLogger implements Logger {
|
||||
|
||||
// implement all methods from logger class
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
And specify it in connection options:
|
||||
|
||||
```typescript
|
||||
import {createConnection} from "typeorm";
|
||||
import {MyCustomLogger} from "./logger/MyCustomLogger";
|
||||
|
||||
createConnection({
|
||||
name: "mysql",
|
||||
type: "mysql",
|
||||
host: "localhost",
|
||||
port: 3306,
|
||||
username: "test",
|
||||
password: "test",
|
||||
database: "test",
|
||||
logger: MyCustomLogger()
|
||||
});
|
||||
```
|
||||
|
||||
If you defined your connection options in `ormconfig` file,
|
||||
then you can use it and override following way:
|
||||
|
||||
```typescript
|
||||
import {createConnection, getConnectionOptions} from "typeorm";
|
||||
import {MyCustomLogger} from "./logger/MyCustomLogger";
|
||||
|
||||
// getConnectionOptions will read options from your ormconfig file
|
||||
// and return it in connectionOptions object
|
||||
// then you can simply append additional properties to it
|
||||
getConnectionOptions().then(connectionOptions => {
|
||||
return createConnection(Object.assign(connectionOptions, {
|
||||
logger: new MyCustomLogger()
|
||||
}))
|
||||
});
|
||||
```
|
||||
@ -4,4 +4,24 @@
|
||||
* Specify custom column name
|
||||
* Specify custom foreign column name
|
||||
* Specify custom many-to-many junction table name
|
||||
* Creating your own `NamingStrategy`
|
||||
* Creating your own `NamingStrategy`
|
||||
|
||||
|
||||
## Creating your own `NamingStrategy`
|
||||
|
||||
If you defined your connection options in `ormconfig` file,
|
||||
then you can simply use it and override it following way:
|
||||
|
||||
```typescript
|
||||
import {createConnection, getConnectionOptions} from "typeorm";
|
||||
import {MyNamingStrategy} from "./logger/MyNamingStrategy";
|
||||
|
||||
// getConnectionOptions will read options from your ormconfig file
|
||||
// and return it in connectionOptions object
|
||||
// then you can simply append additional properties to it
|
||||
getConnectionOptions().then(connectionOptions => {
|
||||
return createConnection(Object.assign(connectionOptions, {
|
||||
namingStrategy: new MyNamingStrategy()
|
||||
}))
|
||||
});
|
||||
```
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import {ConnectionOptions, createConnection} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
import {QueryFailedError} from "../../src/error/QueryFailedError";
|
||||
|
||||
const options: ConnectionOptions = {
|
||||
// type: "oracle",
|
||||
@ -22,35 +23,41 @@ const options: ConnectionOptions = {
|
||||
// username: "test",
|
||||
// password: "test",
|
||||
// database: "test",
|
||||
"type": "mssql",
|
||||
"host": "192.168.1.6",
|
||||
"username": "sa",
|
||||
"password": "admin12345",
|
||||
"database": "test",
|
||||
// "type": "mssql",
|
||||
// "host": "192.168.1.6",
|
||||
// "username": "sa",
|
||||
// "password": "admin12345",
|
||||
// "database": "test",
|
||||
// port: 1521,
|
||||
// type: "sqlite",
|
||||
// database: "temp/sqlitedb.db",
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logFailedQueryError: false,
|
||||
logSchemaCreation: true
|
||||
},
|
||||
type: "sqlite",
|
||||
database: "temp/sqlitedb.db",
|
||||
logging: ["query", "error"],
|
||||
// logging: ["error", "schema", "query"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post]
|
||||
};
|
||||
|
||||
createConnection(options).then(connection => {
|
||||
createConnection(options).then(async connection => {
|
||||
|
||||
let post = new Post();
|
||||
post.text = "Hello how are you?";
|
||||
post.title = "hello";
|
||||
post.likesCount = 100;
|
||||
try {
|
||||
await connection.query("CREATE DATABASE 'aaaa' AND DIE");
|
||||
|
||||
let postRepository = connection.getRepository(Post);
|
||||
} catch (err) {
|
||||
console.log("-------------------------------");
|
||||
console.log("ERRROR: ", err instanceof QueryFailedError);
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
postRepository
|
||||
.save(post)
|
||||
.then(post => console.log("Post has been saved: ", post))
|
||||
.catch(error => console.log("Cannot save. Error: ", error));
|
||||
// let post = new Post();
|
||||
// post.text = "Hello how are you?";
|
||||
// post.title = "hello";
|
||||
// post.likesCount = 100;
|
||||
|
||||
// let postRepository = connection.getRepository(Post);
|
||||
|
||||
// postRepository
|
||||
// .save(post)
|
||||
// .then(post => console.log("Post has been saved: ", post))
|
||||
// .catch(error => console.log("Cannot save. Error: ", error));
|
||||
|
||||
}, error => console.log("Cannot connect: ", error));
|
||||
|
||||
@ -9,9 +9,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [EverythingEntity]
|
||||
};
|
||||
|
||||
@ -12,10 +12,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [__dirname + "/entity/*"]
|
||||
};
|
||||
|
||||
@ -10,12 +10,7 @@ const options: ConnectionOptions = {
|
||||
username: "test",
|
||||
password: "test",
|
||||
database: "test",
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logFailedQueryError: true,
|
||||
logOnlyFailedQueries: true,
|
||||
logSchemaCreation: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, BasePost]
|
||||
};
|
||||
|
||||
@ -9,10 +9,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post]
|
||||
};
|
||||
|
||||
@ -11,10 +11,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Author, Category]
|
||||
};
|
||||
|
||||
@ -12,10 +12,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Author, Category, PostMetadata]
|
||||
};
|
||||
|
||||
@ -15,9 +15,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
// logQueries: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, PostDetails, PostCategory, PostMetadata, PostImage, PostInformation, PostAuthor]
|
||||
};
|
||||
|
||||
@ -11,10 +11,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Author, Category]
|
||||
};
|
||||
|
||||
@ -11,10 +11,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Author, Category]
|
||||
};
|
||||
|
||||
@ -9,10 +9,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Category]
|
||||
};
|
||||
|
||||
@ -11,10 +11,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Author, Category]
|
||||
};
|
||||
|
||||
@ -10,10 +10,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Author]
|
||||
};
|
||||
|
||||
@ -11,10 +11,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Question, Counters]
|
||||
};
|
||||
|
||||
@ -9,10 +9,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post]
|
||||
};
|
||||
|
||||
@ -12,11 +12,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
// logQueries: true,
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [
|
||||
Person,
|
||||
|
||||
@ -12,11 +12,7 @@ const options: ConnectionOptions = {
|
||||
username: "root",
|
||||
password: "admin",
|
||||
database: "test",
|
||||
logging: {
|
||||
// logQueries: true,
|
||||
logOnlyFailedQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [
|
||||
Person,
|
||||
|
||||
@ -21,10 +21,7 @@ const options: ConnectionOptions = {
|
||||
port: 1521,
|
||||
sid: "xe.oracle.docker",
|
||||
autoSchemaSync: true,
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
entities: [Post, PostDetails, PostCategory, PostMetadata, PostImage, PostInformation, PostAuthor]
|
||||
};
|
||||
|
||||
|
||||
@ -6,10 +6,7 @@ import {Category} from "./entity/Category";
|
||||
const options: ConnectionOptions = {
|
||||
type: "sqlite",
|
||||
database: "temp/sqlitedb.db",
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logSchemaCreation: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [Post, Category]
|
||||
};
|
||||
|
||||
@ -9,11 +9,7 @@ const options: ConnectionOptions = {
|
||||
database: "temp/sqlitedb.db",
|
||||
tablesPrefix: "samples_", // pay attention on this prefix
|
||||
autoSchemaSync: true,
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logSchemaCreation: true,
|
||||
logFailedQueryError: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
entities: [Post, Author, Category],
|
||||
};
|
||||
|
||||
|
||||
@ -11,9 +11,7 @@ const options: ConnectionOptions = {
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaSync: true,
|
||||
logging: {
|
||||
logQueries: true,
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
entities: [Post, Author],
|
||||
};
|
||||
|
||||
@ -45,9 +43,7 @@ createConnection(options).then(async connection => {
|
||||
username: "test",
|
||||
password: "test",
|
||||
database: "test",
|
||||
logging: {
|
||||
logQueries: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
entities: [
|
||||
Post,
|
||||
Author
|
||||
|
||||
@ -15,9 +15,7 @@ const options: ConnectionOptions = {
|
||||
password: "admin",
|
||||
database: "test",
|
||||
autoSchemaSync: true,
|
||||
logging: {
|
||||
logQueries: true,
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
entities: [Post, Author, User],
|
||||
};
|
||||
|
||||
|
||||
@ -6,10 +6,7 @@ const options: ConnectionOptions = {
|
||||
type: "mongodb",
|
||||
host: "localhost",
|
||||
database: "test",
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logSchemaCreation: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
// autoSchemaSync: true,
|
||||
entities: [Post]
|
||||
};
|
||||
|
||||
@ -9,10 +9,7 @@ const options: ConnectionOptions = {
|
||||
username: "sa",
|
||||
password: "admin12345",
|
||||
database: "test",
|
||||
logging: {
|
||||
logFailedQueryError: true,
|
||||
// logQueries: true
|
||||
},
|
||||
logging: ["query", "error"],
|
||||
autoSchemaSync: true,
|
||||
entities: [__dirname + "/entity/*"]
|
||||
};
|
||||
|
||||
@ -3,6 +3,7 @@ import {EntitySchema} from "../entity-schema/EntitySchema";
|
||||
import {LoggerOptions} from "../logger/LoggerOptions";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
|
||||
import {DatabaseType} from "../driver/types/DatabaseType";
|
||||
import {Logger} from "../logger/Logger";
|
||||
|
||||
/**
|
||||
* BaseConnectionOptions is set of connection options shared by all database types.
|
||||
@ -81,6 +82,16 @@ export interface BaseConnectionOptions {
|
||||
*/
|
||||
readonly logging?: LoggerOptions;
|
||||
|
||||
/**
|
||||
* Logger instance used to log queries and events in the ORM.
|
||||
*/
|
||||
readonly logger?: "advanced-console"|"simple-console"|"file"|Logger;
|
||||
|
||||
/**
|
||||
* Maximum number of milliseconds query should be executed before logger log a warning.
|
||||
*/
|
||||
readonly maxQueryExecutionTime?: number;
|
||||
|
||||
/**
|
||||
* Drops the schema each time connection is being established.
|
||||
* Be careful with this option and don't use this in production - otherwise you'll loose all production data.
|
||||
|
||||
@ -21,12 +21,12 @@ import {EntityMetadataValidator} from "../metadata-builder/EntityMetadataValidat
|
||||
import {ConnectionOptions} from "./ConnectionOptions";
|
||||
import {QueryRunnerProviderAlreadyReleasedError} from "../error/QueryRunnerProviderAlreadyReleasedError";
|
||||
import {EntityManagerFactory} from "../entity-manager/EntityManagerFactory";
|
||||
import {LoggerFactory} from "../logger/LoggerFactory";
|
||||
import {DriverFactory} from "../driver/DriverFactory";
|
||||
import {ConnectionMetadataBuilder} from "./ConnectionMetadataBuilder";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
import {SqliteDriver} from "../driver/sqlite/SqliteDriver";
|
||||
import {LoggerFactory} from "../logger/LoggerFactory";
|
||||
|
||||
/**
|
||||
* Connection is a single database ORM connection to a specific database.
|
||||
@ -96,7 +96,7 @@ export class Connection {
|
||||
constructor(options: ConnectionOptions) {
|
||||
this.name = options.name || "default";
|
||||
this.options = options;
|
||||
this.logger = new LoggerFactory().create(this.options.logging || {});
|
||||
this.logger = new LoggerFactory().create(this.options.logger, this.options.logging);
|
||||
this.driver = new DriverFactory().create(this);
|
||||
this.manager = new EntityManagerFactory().create(this);
|
||||
this.namingStrategy = options.namingStrategy || new DefaultNamingStrategy();
|
||||
|
||||
@ -32,11 +32,7 @@ export class ConnectionOptionsEnvReader {
|
||||
migrations: PlatformTools.getEnvVariable("TYPEORM_MIGRATIONS") ? PlatformTools.getEnvVariable("TYPEORM_MIGRATIONS").split(",") : [],
|
||||
subscribers: PlatformTools.getEnvVariable("TYPEORM_SUBSCRIBERS") ? PlatformTools.getEnvVariable("TYPEORM_SUBSCRIBERS").split(",") : [],
|
||||
entitySchemas: PlatformTools.getEnvVariable("TYPEORM_ENTITY_SCHEMAS") ? PlatformTools.getEnvVariable("TYPEORM_ENTITY_SCHEMAS").split(",") : [],
|
||||
logging: {
|
||||
logQueries: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_QUERIES")),
|
||||
logFailedQueryError: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_FAILED_QUERIES")),
|
||||
logOnlyFailedQueries: OrmUtils.toBoolean(PlatformTools.getEnvVariable("TYPEORM_LOGGING_ONLY_FAILED_QUERIES")),
|
||||
},
|
||||
logging: PlatformTools.getEnvVariable("TYPEORM_LOGGING"),
|
||||
cli: {
|
||||
entitiesDir: PlatformTools.getEnvVariable("TYPEORM_ENTITIES_DIR"),
|
||||
migrationsDir: PlatformTools.getEnvVariable("TYPEORM_MIGRATIONS_DIR"),
|
||||
|
||||
@ -32,11 +32,7 @@ export class ConnectionOptionsXmlReader {
|
||||
entities: connection.entities ? connection.entities[0].entity : [],
|
||||
subscribers: connection.subscribers ? connection.subscribers[0].entity : [],
|
||||
entitySchemas: connection.entitySchemas ? connection.entitySchemas[0].entity : [],
|
||||
logging: {
|
||||
logQueries: connection.logging && connection.logging[0].logQueries ? connection.logging[0].logQueries[0] : undefined,
|
||||
logFailedQueryError: connection.logging && connection.logging[0].logFailedQueryError ? connection.logging[0].logFailedQueryError[0] : undefined,
|
||||
logOnlyFailedQueries: connection.logging && connection.logging[0].logOnlyFailedQueries ? connection.logging[0].logOnlyFailedQueries[0] : undefined,
|
||||
}
|
||||
logging: connection.logging[0] ? connection.logging[0].split(",") : undefined,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import {ReadStream} from "fs";
|
||||
import {EntityManager} from "../../entity-manager/EntityManager";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
import {InsertResult} from "../InsertResult";
|
||||
import {QueryFailedError} from "../../error/QueryFailedError";
|
||||
|
||||
/**
|
||||
* Runs queries on a single mysql database connection.
|
||||
@ -166,9 +167,8 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
this.driver.connection.logger.logQuery(query, parameters, this);
|
||||
databaseConnection.query(query, parameters, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
return fail(err);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
return fail(new QueryFailedError(query, parameters, err));
|
||||
}
|
||||
|
||||
ok(result);
|
||||
|
||||
@ -13,6 +13,7 @@ import {OracleDriver} from "./OracleDriver";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
import {ReadStream} from "fs";
|
||||
import {EntityManager} from "../../entity-manager/EntityManager";
|
||||
import {QueryFailedError} from "../../error/QueryFailedError";
|
||||
|
||||
/**
|
||||
* Runs queries on a single oracle database connection.
|
||||
@ -177,9 +178,8 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
this.driver.connection.logger.logQuery(query, parameters, this);
|
||||
const handler = (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
return fail(err);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
return fail(new QueryFailedError(query, parameters, err));
|
||||
}
|
||||
|
||||
ok(result.rows || result.outBinds);
|
||||
|
||||
@ -14,6 +14,7 @@ import {ReadStream} from "fs";
|
||||
import {EntityManager} from "../../entity-manager/EntityManager";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
import {InsertResult} from "../InsertResult";
|
||||
import {QueryFailedError} from "../../error/QueryFailedError";
|
||||
|
||||
/**
|
||||
* Runs queries on a single postgres database connection.
|
||||
@ -113,8 +114,7 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
|
||||
connection.query(`SET search_path TO '${this.schemaName}', 'public';`, (err: any) => {
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(`SET search_path TO '${this.schemaName}', 'public';`, [], this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
this.driver.connection.logger.logQueryError(err, `SET search_path TO '${this.schemaName}', 'public';`, [], this);
|
||||
fail(err);
|
||||
} else {
|
||||
ok(connection);
|
||||
@ -191,9 +191,8 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
this.driver.connection.logger.logQuery(query, parameters, this);
|
||||
databaseConnection.query(query, parameters, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
fail(err);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
fail(new QueryFailedError(query, parameters, err));
|
||||
} else {
|
||||
ok(result.rows);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import {ReadStream} from "fs";
|
||||
import {EntityManager} from "../../entity-manager/EntityManager";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
import {InsertResult} from "../InsertResult";
|
||||
import {QueryFailedError} from "../../error/QueryFailedError";
|
||||
|
||||
/**
|
||||
* Runs queries on a single sqlite database connection.
|
||||
@ -145,9 +146,8 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
this.driver.connection.logger.logQuery(query, parameters, this);
|
||||
databaseConnection.all(query, parameters, (err: any, result: any) => {
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
fail(err);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
fail(new QueryFailedError(query, parameters, err));
|
||||
} else {
|
||||
ok(result);
|
||||
}
|
||||
@ -180,8 +180,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
const databaseConnection = await this.connect();
|
||||
databaseConnection.run(sql, parameters, function (err: any): void {
|
||||
if (err) {
|
||||
__this.driver.connection.logger.logFailedQuery(sql, parameters, this);
|
||||
__this.driver.connection.logger.logQueryError(err, this);
|
||||
__this.driver.connection.logger.logQueryError(err, sql, parameters, this);
|
||||
fail(err);
|
||||
} else {
|
||||
const generatedMap = generatedColumns.reduce((map, generatedColumn) => {
|
||||
|
||||
@ -14,6 +14,7 @@ import {ReadStream} from "fs";
|
||||
import {MssqlParameter} from "./MssqlParameter";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
import {EntityManager} from "../../entity-manager/EntityManager";
|
||||
import {QueryFailedError} from "../../error/QueryFailedError";
|
||||
|
||||
/**
|
||||
* Runs queries on a single mysql database connection.
|
||||
@ -288,10 +289,9 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
let promiseIndex = this.queryResponsibilityChain.indexOf(promise);
|
||||
let waitingPromiseIndex = this.queryResponsibilityChain.indexOf(waitingPromise);
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError((err.originalError && err.originalError.info) ? err.originalError.info.message : err, this);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
resolveChain();
|
||||
return fail(err);
|
||||
return fail(new QueryFailedError(query, parameters, err));
|
||||
}
|
||||
|
||||
ok(result.recordset);
|
||||
@ -346,8 +346,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
let promiseIndex = this.queryResponsibilityChain.indexOf(promise);
|
||||
let waitingPromiseIndex = this.queryResponsibilityChain.indexOf(waitingPromise);
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError((err.originalError && err.originalError.info) ? err.originalError.info.message : err, this);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
resolveChain();
|
||||
return fail(err);
|
||||
}
|
||||
@ -378,7 +377,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
const generatedColumnSql = generatedColumns.length > 0 ? ` OUTPUT ${generatedColumnNames}` : "";
|
||||
const sql = columns.length > 0
|
||||
? `INSERT INTO "${tableName}"(${columns}) ${generatedColumnSql} VALUES (${values})`
|
||||
: `INSERT INTO "${tableName}" ${generatedColumnSql} DEFAULT VALUES `;
|
||||
: `INSERT INTO "${tableName}" DEFAULT VALUES `;
|
||||
|
||||
const parameters = this.driver.parametrizeMap(tableName, keyValues);
|
||||
const parametersArray = Object.keys(parameters).map(key => parameters[key]);
|
||||
|
||||
@ -14,6 +14,7 @@ import {ReadStream} from "fs";
|
||||
import {EntityManager} from "../../entity-manager/EntityManager";
|
||||
import {OrmUtils} from "../../util/OrmUtils";
|
||||
import {InsertResult} from "../InsertResult";
|
||||
import {QueryFailedError} from "../../error/QueryFailedError";
|
||||
|
||||
/**
|
||||
* Declare a global function that is only available in browsers that support WebSQL.
|
||||
@ -195,9 +196,8 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
ok(rows);
|
||||
|
||||
}, (tx: any, err: any) => {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters, this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
return fail(err);
|
||||
this.driver.connection.logger.logQueryError(err, query, parameters, this);
|
||||
return fail(new QueryFailedError(query, parameters, err));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -241,8 +241,7 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
});
|
||||
|
||||
}, (tx: any, err: any) => {
|
||||
this.driver.connection.logger.logFailedQuery(sql, parameters, this);
|
||||
this.driver.connection.logger.logQueryError(err, this);
|
||||
this.driver.connection.logger.logQueryError(err, sql, parameters, this);
|
||||
return fail(err);
|
||||
});
|
||||
});
|
||||
|
||||
17
src/error/QueryFailedError.ts
Normal file
17
src/error/QueryFailedError.ts
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Thrown when query execution has failed.
|
||||
*/
|
||||
export class QueryFailedError extends Error {
|
||||
|
||||
constructor(query: string, parameters: any[]|undefined, driverError: any) {
|
||||
super(driverError.toString().replace(/error: /, "").replace(/Error: /, ""));
|
||||
Object.setPrototypeOf(this, QueryFailedError.prototype);
|
||||
Object.assign(this, {
|
||||
...driverError,
|
||||
name: "QueryFailedError",
|
||||
query: query,
|
||||
parameters: parameters || []
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
10
src/index.ts
10
src/index.ts
@ -21,6 +21,7 @@ import {PromiseUtils} from "./util/PromiseUtils";
|
||||
export * from "./container";
|
||||
export * from "./common/ObjectType";
|
||||
export * from "./common/ObjectLiteral";
|
||||
export * from "./error/QueryFailedError";
|
||||
export * from "./decorator/columns/Column";
|
||||
export * from "./decorator/columns/CreateDateColumn";
|
||||
export * from "./decorator/columns/DiscriminatorColumn";
|
||||
@ -140,6 +141,13 @@ export function getConnectionManager(): ConnectionManager {
|
||||
return getFromContainer(ConnectionManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads connection options stored in ormconfig configuration file.
|
||||
*/
|
||||
export async function getConnectionOptions(connectionName: string = "default"): Promise<ConnectionOptions> {
|
||||
return new ConnectionOptionsReader().get(connectionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection and registers it in the manager.
|
||||
*
|
||||
@ -149,7 +157,7 @@ export function getConnectionManager(): ConnectionManager {
|
||||
*/
|
||||
export async function createConnection(options?: ConnectionOptions): Promise<Connection> {
|
||||
if (!options)
|
||||
options = await new ConnectionOptionsReader().get("default");
|
||||
options = await getConnectionOptions();
|
||||
|
||||
return getConnectionManager().create(options).connect();
|
||||
}
|
||||
|
||||
101
src/logger/AdvancedConsoleLogger.ts
Normal file
101
src/logger/AdvancedConsoleLogger.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {PlatformTools} from "../platform/PlatformTools";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {Logger} from "./Logger";
|
||||
const chalk = require("chalk");
|
||||
|
||||
/**
|
||||
* Performs logging of the events in TypeORM.
|
||||
* This version of logger uses console to log events and does not use syntax highlighting.
|
||||
*/
|
||||
export class AdvancedConsoleLogger implements Logger {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private options?: LoggerOptions) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Logs query and parameters used in it.
|
||||
*/
|
||||
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || this.options === true || (this.options instanceof Array && this.options.indexOf("query") !== -1)) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
console.log(chalk.gray.underline("executing query") + ": " + PlatformTools.highlightSql(sql));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs query that is failed.
|
||||
*/
|
||||
logQueryError(error: string, query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || this.options === true || (this.options instanceof Array && this.options.indexOf("error") !== -1)) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
console.log(chalk.underline.red(`query failed:`) + " " + chalk.bold(PlatformTools.highlightSql(sql)));
|
||||
console.log(chalk.underline.red(`error:`), error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs query that is slow.
|
||||
*/
|
||||
logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
console.log(chalk.underline.yellow(`query is slow:`) + " " + chalk.bold(PlatformTools.highlightSql(sql)));
|
||||
console.log(chalk.underline.yellow(`execution time:`), time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs events from the schema build process.
|
||||
*/
|
||||
logSchemaBuild(message: string, queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("schema") !== -1)) {
|
||||
console.log(chalk.underline(message));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform logging using given logger, or by default to the console.
|
||||
* Log has its own level and message.
|
||||
*/
|
||||
log(level: "log"|"info"|"warn", message: any, queryRunner?: QueryRunner) {
|
||||
switch (level) {
|
||||
case "log":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("log") !== -1))
|
||||
console.log(message);
|
||||
break;
|
||||
case "info":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("info") !== -1))
|
||||
console.info(message);
|
||||
break;
|
||||
case "warn":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("warn") !== -1))
|
||||
console.warn(chalk.yellow(message));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Converts parameters to a string.
|
||||
* Sometimes parameters can have circular objects and therefor we are handle this case too.
|
||||
*/
|
||||
protected stringifyParams(parameters: any[]) {
|
||||
try {
|
||||
return JSON.stringify(parameters);
|
||||
|
||||
} catch (error) { // most probably circular objects in parameters
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
111
src/logger/FileLogger.ts
Normal file
111
src/logger/FileLogger.ts
Normal file
@ -0,0 +1,111 @@
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {Logger} from "./Logger";
|
||||
import {writeFileSync} from "fs";
|
||||
|
||||
/**
|
||||
* Performs logging of the events in TypeORM.
|
||||
*/
|
||||
export class FileLogger implements Logger {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private options?: LoggerOptions) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Logs query and parameters used in it.
|
||||
*/
|
||||
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || this.options === true || (this.options instanceof Array && this.options.indexOf("query") !== -1)) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
this.write("executing query" + ": " + sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs query that is failed.
|
||||
*/
|
||||
logQueryError(error: string, query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || this.options === true || (this.options instanceof Array && this.options.indexOf("error") !== -1)) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
this.write([
|
||||
`query failed: ` + sql,
|
||||
`error:`, error
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs query that is slow.
|
||||
*/
|
||||
logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
this.write([
|
||||
`query is slow: ` + sql,
|
||||
`execution time: ` + time
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs events from the schema build process.
|
||||
*/
|
||||
logSchemaBuild(message: string, queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("schema") !== -1)) {
|
||||
this.write(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform logging using given logger, or by default to the console.
|
||||
* Log has its own level and message.
|
||||
*/
|
||||
log(level: "log"|"info"|"warn"|"error", message: any, queryRunner?: QueryRunner) {
|
||||
switch (level) {
|
||||
case "log":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("log") !== -1))
|
||||
this.write(message);
|
||||
break;
|
||||
case "info":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("info") !== -1))
|
||||
this.write(message);
|
||||
break;
|
||||
case "warn":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("warn") !== -1))
|
||||
this.write(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Writes given strings into the log file.
|
||||
*/
|
||||
protected write(strings: string|string[]) {
|
||||
strings = strings instanceof Array ? strings : [strings];
|
||||
writeFileSync("ormlogs.log", strings.join("\r\n")); // todo: make async
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts parameters to a string.
|
||||
* Sometimes parameters can have circular objects and therefor we are handle this case too.
|
||||
*/
|
||||
protected stringifyParams(parameters: any[]) {
|
||||
try {
|
||||
return JSON.stringify(parameters);
|
||||
|
||||
} catch (error) { // most probably circular objects in parameters
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,113 +1,34 @@
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {PlatformTools} from "../platform/PlatformTools";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
const chalk = require("chalk");
|
||||
|
||||
/**
|
||||
* Performs logging of the events in TypeORM.
|
||||
*
|
||||
* todo: implement logging of too long running queries (there should be option to control max query execution time)
|
||||
*/
|
||||
export class Logger {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private options: LoggerOptions) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
export interface Logger {
|
||||
|
||||
/**
|
||||
* Logs query and parameters used in it.
|
||||
*/
|
||||
logQuery(query: string, parameters: any[]|undefined, queryRunner?: QueryRunner) {
|
||||
if (this.options.logQueries ||
|
||||
PlatformTools.getEnvVariable("LOGGER_CLI_SCHEMA_SYNC")) {
|
||||
this.log("query", query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : ""), queryRunner);
|
||||
}
|
||||
}
|
||||
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner): any;
|
||||
|
||||
/**
|
||||
* Logs query that failed.
|
||||
* Logs query that is failed.
|
||||
*/
|
||||
logFailedQuery(query: string, parameters: any[]|undefined, queryRunner?: QueryRunner) {
|
||||
if (this.options.logQueries ||
|
||||
this.options.logOnlyFailedQueries ||
|
||||
PlatformTools.getEnvVariable("LOGGER_CLI_SCHEMA_SYNC"))
|
||||
this.log("error", `query failed: ${query}${parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : ""}`, queryRunner);
|
||||
}
|
||||
logQueryError(error: string, query: string, parameters?: any[], queryRunner?: QueryRunner): any;
|
||||
|
||||
/**
|
||||
* Logs failed query's error.
|
||||
* Logs query that is slow.
|
||||
*/
|
||||
logQueryError(error: any, queryRunner?: QueryRunner) {
|
||||
if (this.options.logFailedQueryError ||
|
||||
PlatformTools.getEnvVariable("LOGGER_CLI_SCHEMA_SYNC"))
|
||||
this.log("error", "error during executing query:" + error, queryRunner);
|
||||
}
|
||||
logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner): any;
|
||||
|
||||
/**
|
||||
* Logs events from the schema build process.
|
||||
*/
|
||||
logSchemaBuild(message: string, queryRunner?: QueryRunner) {
|
||||
if (this.options.logSchemaCreation ||
|
||||
PlatformTools.getEnvVariable("LOGGER_CLI_SCHEMA_SYNC"))
|
||||
this.log("schema-build", message, queryRunner);
|
||||
}
|
||||
logSchemaBuild(message: string, queryRunner?: QueryRunner): any;
|
||||
|
||||
/**
|
||||
* Perform logging using given logger, or by default to the console.
|
||||
* Log has its own level and message.
|
||||
*/
|
||||
log(level: "query"|"schema-build"|"log"|"info"|"warn"|"error", message: any, queryRunner?: QueryRunner) {
|
||||
if (!this.options) return;
|
||||
|
||||
if (this.options.logger) {
|
||||
this.options.logger(level, message, queryRunner);
|
||||
|
||||
} else {
|
||||
switch (level) {
|
||||
case "schema-build":
|
||||
console.log(chalk.underline(message));
|
||||
break;
|
||||
case "query":
|
||||
console.log(chalk.gray.underline("executing query") + ": " + PlatformTools.highlightSql(message));
|
||||
break;
|
||||
case "log":
|
||||
console.log(message);
|
||||
break;
|
||||
case "info":
|
||||
console.info(message);
|
||||
break;
|
||||
case "warn":
|
||||
console.warn(message);
|
||||
break;
|
||||
case "error":
|
||||
console.error(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Converts parameters to a string.
|
||||
* Sometimes parameters can have circular objects and therefor we are handle this case too.
|
||||
*/
|
||||
protected stringifyParams(parameters: any[]) {
|
||||
try {
|
||||
return JSON.stringify(parameters);
|
||||
|
||||
} catch (error) { // most probably circular objects in parameters
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
log(level: "log"|"info"|"warn", message: any, queryRunner?: QueryRunner): any;
|
||||
|
||||
}
|
||||
@ -1,5 +1,8 @@
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {Logger} from "./Logger";
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {SimpleConsoleLogger} from "./SimpleConsoleLogger";
|
||||
import {AdvancedConsoleLogger} from "./AdvancedConsoleLogger";
|
||||
import {FileLogger} from "./FileLogger";
|
||||
|
||||
/**
|
||||
* Helps to create logger instances.
|
||||
@ -9,8 +12,24 @@ export class LoggerFactory {
|
||||
/**
|
||||
* Creates a new logger depend on a given connection's driver.
|
||||
*/
|
||||
create(options: LoggerOptions): Logger {
|
||||
return new Logger(options);
|
||||
create(logger?: "advanced-console"|"simple-console"|"file"|Logger, options?: LoggerOptions): Logger {
|
||||
if (logger instanceof Object)
|
||||
return logger as Logger;
|
||||
|
||||
if (logger) {
|
||||
switch (logger) {
|
||||
case "simple-console":
|
||||
return new SimpleConsoleLogger(options);
|
||||
|
||||
case "file":
|
||||
return new FileLogger(options);
|
||||
|
||||
case "advanced-console":
|
||||
return new AdvancedConsoleLogger(options);
|
||||
}
|
||||
}
|
||||
|
||||
return new AdvancedConsoleLogger(options);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,32 +1,4 @@
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
/**
|
||||
* Logging options.
|
||||
*/
|
||||
export interface LoggerOptions {
|
||||
|
||||
/**
|
||||
* Some specific logger to be used. By default it is a console.
|
||||
*/
|
||||
readonly logger?: (level: string, message: any, queryRunner?: QueryRunner) => void;
|
||||
|
||||
/**
|
||||
* Set to true if you want to log every executed query.
|
||||
*/
|
||||
readonly logQueries?: boolean;
|
||||
|
||||
/**
|
||||
* Set to true if you want to log only failed query.
|
||||
*/
|
||||
readonly logOnlyFailedQueries?: boolean;
|
||||
|
||||
/**
|
||||
* Set to true if you want to log error of the failed query.
|
||||
*/
|
||||
readonly logFailedQueryError?: boolean;
|
||||
|
||||
/**
|
||||
* If set to true then schema creation logs will be logged.
|
||||
*/
|
||||
readonly logSchemaCreation?: boolean;
|
||||
|
||||
}
|
||||
export type LoggerOptions = boolean|"all"|("query"|"schema"|"error"|"warn"|"info"|"log")[];
|
||||
|
||||
98
src/logger/SimpleConsoleLogger.ts
Normal file
98
src/logger/SimpleConsoleLogger.ts
Normal file
@ -0,0 +1,98 @@
|
||||
import {LoggerOptions} from "./LoggerOptions";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {Logger} from "./Logger";
|
||||
|
||||
/**
|
||||
* Performs logging of the events in TypeORM.
|
||||
*/
|
||||
export class SimpleConsoleLogger implements Logger {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private options?: LoggerOptions) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Logs query and parameters used in it.
|
||||
*/
|
||||
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || this.options === true || (this.options instanceof Array && this.options.indexOf("query") !== -1)) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
console.log("executing query" + ": " + sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs query that is failed.
|
||||
*/
|
||||
logQueryError(error: string, query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || this.options === true || (this.options instanceof Array && this.options.indexOf("error") !== -1)) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
console.log(`query failed: ` + sql);
|
||||
console.log(`error:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs query that is slow.
|
||||
*/
|
||||
logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner) {
|
||||
const sql = query + (parameters && parameters.length ? " -- PARAMETERS: " + this.stringifyParams(parameters) : "");
|
||||
console.log(`query is slow: ` + sql);
|
||||
console.log(`execution time: ` + time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs events from the schema build process.
|
||||
*/
|
||||
logSchemaBuild(message: string, queryRunner?: QueryRunner) {
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("schema") !== -1)) {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform logging using given logger, or by default to the console.
|
||||
* Log has its own level and message.
|
||||
*/
|
||||
log(level: "log"|"info"|"warn"|"error", message: any, queryRunner?: QueryRunner) {
|
||||
switch (level) {
|
||||
case "log":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("log") !== -1))
|
||||
console.log(message);
|
||||
break;
|
||||
case "info":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("info") !== -1))
|
||||
console.info(message);
|
||||
break;
|
||||
case "warn":
|
||||
if (this.options === "all" || (this.options instanceof Array && this.options.indexOf("warn") !== -1))
|
||||
console.warn(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Converts parameters to a string.
|
||||
* Sometimes parameters can have circular objects and therefor we are handle this case too.
|
||||
*/
|
||||
protected stringifyParams(parameters: any[]) {
|
||||
try {
|
||||
return JSON.stringify(parameters);
|
||||
|
||||
} catch (error) { // most probably circular objects in parameters
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user