终于把sylar给赶工做完了,趁热打铁一波,把源码解析做一遍

再次感谢sylar-yin老师的无偿视频教学

日志模块一共定义了UNKNOW,DEBUG,INFO,WARN,ERROR,FATAL6种日志等级。

每次日志生成实际上都会生成一个LogEventWrap,其内部封装了一个LogEvent对象,在LogEventWrap析构时,会自动调用指定的logger来输出该LogEvent。又因为宏中使用了if,因此该行结束后LogEventWrap会直接析构掉自己,打印日志。

LogFormatter用于按照指定格式打印日志,内部包含了FormatItem类,用于解析给定的pattern。

LogAppender用于指定输出的方式(StdoutLogAppender,FileLogAppender),内含一个LogFormatter。

Logger内含一个std::list,每次调用输出函数时,每个符合日志等级的LogAppender都会调用自身的打印函数。

logmanager全局管理logger,自身为单例模式。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

#pragma once

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include"singleton.h"

#include"util.h"

#include"thread.h"

#define SYLAR_LOG_LEVEL(logger,level) \

if(logger->getLevel() <= level) \

sylar::LogEventWrap(sylar::LogEvent::ptr(new sylar::LogEvent(logger,level,\

__FILE__,__LINE__,0,sylar::GetThreadId(),\

sylar::GetFiberId(),time(0),sylar::Thread::GetName()))).getSS()

#define SYLAR_LOG_DEBUG(logger) SYLAR_LOG_LEVEL(logger,sylar::LogLevel::DEBUG)

#define SYLAR_LOG_INFO(logger) SYLAR_LOG_LEVEL(logger,sylar::LogLevel::INFO)

#define SYLAR_LOG_WARN(logger) SYLAR_LOG_LEVEL(logger,sylar::LogLevel::WARN)

#define SYLAR_LOG_ERROR(logger) SYLAR_LOG_LEVEL(logger,sylar::LogLevel::ERROR)

#define SYLAR_LOG_FATAL(logger) SYLAR_LOG_LEVEL(logger,sylar::LogLevel::FATAL)

#define SYLAR_LOG_FMT_LEVEL(logger,level,fmt,...) \

if(logger->getLevel()<=level) \

sylar::LogEventWrap(sylar::LogEvent::ptr(new sylar::LogEvent(logger,level,\

__FILE__,__LINE__,0,sylar::GetThreadId(),\

sylar::GetFiberId(),time(0),sylar::Thread::GetName()))).getEvent()->format(fmt,__VA_ARGS__)

#define SYLAR_LOG_FMT_DEBUG(logger,fmt,...) SYLAR_LOG_FMT_LEVEL(logger,sylar::LogLevel::DEBUG,fmt,__VA_ARGS__)

#define SYLAR_LOG_FMT_INFO(logger,fmt,...) SYLAR_LOG_FMT_LEVEL(logger,sylar::LogLevel::INFO,fmt,__VA_ARGS__)

#define SYLAR_LOG_FMT_WARN(logger,fmt,...) SYLAR_LOG_FMT_LEVEL(logger,sylar::LogLevel::WARN,fmt,__VA_ARGS__)

#define SYLAR_LOG_FMT_ERROR(logger,fmt,...) SYLAR_LOG_FMT_LEVEL(logger,sylar::LogLevel::ERROR,fmt,__VA_ARGS__)

#define SYLAR_LOG_FMT_FATAL(logger,fmt,...) SYLAR_LOG_FMT_LEVEL(logger,sylar::LogLevel::FATAL,fmt,__VA_ARGS__)

#define SYLAR_LOG_ROOT() sylar::LoggerMgr::GetInstance()->getRoot()

#define SYLAR_LOG_NAME(name) sylar::LoggerMgr::GetInstance()->getLogger(name)

namespace sylar {

class Logger;

class LoggerManager;

//日志级别

class LogLevel {

public:

enum Level {

UNKNOW = 0,

DEBUG = 1,

INFO,

WARN,

ERROR,

FATAL

};

//将level类型转为对应的字符输出

static const char * Tostring(LogLevel::Level level);

//将给定的字符转为level类

static LogLevel::Level FromString(const std::string & str);

};

//日志事件

class LogEvent {

public:

typedef std::shared_ptr ptr;

/// @brief 构造函数

/// @param logger 日志器

/// @param level 日志等级

/// @param file 当前文件名

/// @param line 当前行数

/// @param elapse 程序启动依赖的耗时

/// @param threadid 当前线程id

/// @param fiberId 当前协程id

/// @param time 当前时间

/// @param thread_name 线程名

LogEvent(std::shared_ptr logger,LogLevel::Level level,const char * file , int32_t line , uint32_t elapse,

uint32_t threadid,uint32_t fiberId,uint64_t time,const std::string & thread_name);

//返回文件名

const char * getFile() const {return m_file;}

//返回行号

int32_t getLine() const {return m_line;}

//返回运行时间

uint32_t getElapse() const {return m_elapse;}

//返回线程id

uint32_t getThreadId() const {return m_threadId;}

//返回协程id

uint32_t getFiberId() const {return m_fiberId;}

//返回当前时间

uint64_t getTime() const {return m_time;}

//返回线程名

const std::string& getThreadName()const {return m_threadName;}

//返回日志内容

std::string getContent() const {return m_ss.str();}

std::stringstream & getSS() {return m_ss;}

std::shared_ptr getLogger() {return m_logger;}

//返回日志等级

LogLevel::Level getLevel() {return m_level;}

//按照fmt格式写日志到m_ss里

void format(const char * fmt,...);

void format(const char * fmt,va_list al);

private:

const char * m_file = nullptr; //文件名

int32_t m_line = 0; //行号

uint32_t m_elapse = 0; //程序启动毫秒数

uint32_t m_threadId = 0; //线程id

uint32_t m_fiberId = 0; //协程id

uint64_t m_time =0; //时间戳

std::string m_threadName;

std::shared_ptr m_logger;

LogLevel::Level m_level;

std::stringstream m_ss;

};

class LogEventWrap{

public:

LogEventWrap(LogEvent::ptr event):m_event(event){};

~LogEventWrap();

std::stringstream & getSS(){return m_event->getSS();}

LogEvent::ptr getEvent(){return m_event;}

private:

LogEvent::ptr m_event;

};

//日志格式器

class LogFormatter {

public:

typedef std::shared_ptr ptr;

/// @brief 利用pattern解析出m_items,做到按指定格式输出字符的效果

/// @param pattern 用于解析的字符串

LogFormatter(const std::string pattern);

//调用自身m_items中所有FormatItem的format事件

//返回结果构成的字符串

std::string format(std::shared_ptrlogger, LogLevel::Level level,LogEvent::ptr event);

// private:

class FormatItem{

public:

typedef std::shared_ptr ptr;

// FormatItem(const std::string & fmt =""){}

virtual ~FormatItem(){}

virtual void format(std::ostream& os,std::shared_ptrlogger,LogLevel::Level level,LogEvent::ptr event) = 0;

};

//真正的解析函数

void init();

bool isError() const {return m_error;}

std::string getPattern() const {return m_pattern;}

private:

std::string m_pattern;

std::vector m_items;

bool m_error =false;

};

//日志输出地

class LogAppender{

friend class Logger;

public:

typedef std::shared_ptr ptr;

typedef Spinlock MutexType;

virtual ~LogAppender(){};

virtual void log(std::shared_ptr logger,LogLevel::Level level,LogEvent::ptr event) = 0;

virtual std::string toYamlString() = 0;

void setFormatter(LogFormatter::ptr val);

LogFormatter::ptr getFormatter();

void setLevel(LogLevel::Level level){m_level=level;}

protected:

LogLevel::Level m_level = LogLevel::DEBUG;

bool m_hasFormatter = false;

MutexType m_mutex;

LogFormatter::ptr m_formatter;

};

//日志器

class Logger : public std::enable_shared_from_this{

friend class LoggerManager;

public:

typedef std::shared_ptr ptr;

typedef Spinlock MutexType;

Logger(const std::string & name = "root");

//调用管理的LoggerAppender的每个format事件,level可指定

void log(LogLevel::Level level,LogEvent::ptr event);

//debug级别的log调用

void debug(LogEvent::ptr event);

//info级别的log调用

void info(LogEvent::ptr event);

//warn级别的log调用

void warn(LogEvent::ptr event);

//fatal级别的log调用

void fatal(LogEvent::ptr event);

//error级别的log调用

void error(LogEvent::ptr event);

void addAppender(LogAppender::ptr appender);

void delAppender(LogAppender::ptr appender);

void clearAppenders();

LogLevel::Level getLevel() const {return m_level;}

void setLevel(LogLevel::Level level){m_level = level;}

const std::string & getName()const {return m_name;}

void setFormatter(LogFormatter::ptr val);

void setFormatter(const std::string & val);

LogFormatter::ptr getFormatter();

std::string toYamlString();

private:

std::string m_name; //日志名称

LogLevel::Level m_level; //日志级别

MutexType m_mutex;

std::list m_appender; //Appender集合

LogFormatter::ptr m_formatter; //自带的formatter ,方便调试

Logger::ptr m_root;//默认的日志器

};

//输出到控制台的Appender

class StdoutLogAppender : public LogAppender {

public:

virtual std::string toYamlString() override;

typedef std::shared_ptr ptr;

virtual void log(std::shared_ptr logger,LogLevel::Level level,LogEvent::ptr event) override;

};

//输出到文件的Appender

class FileLogAppender : public LogAppender {

public:

typedef std::shared_ptr ptr;

FileLogAppender(const std::string filname);

virtual void log(std::shared_ptr logger,LogLevel::Level level,LogEvent::ptr event) override;

virtual std::string toYamlString() override;

//重新开打文件

bool reopen();

private:

std::string m_filename;

std::ofstream m_filestream;

};

//全局logger管理器

class LoggerManager{

public:

typedef Spinlock MutexType;

LoggerManager();

Logger::ptr getLogger(const std::string & name);

//do noting

void init();

Logger::ptr getRoot()const {return m_root;}

std::string toYamlString();

private:

std::map m_logger;

Logger::ptr m_root; //指向当前正在使用的日志器

MutexType m_mutex;

};

//静态单列模式

typedef Singleton LoggerMgr;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

#include"log.h"

#include

#include

#include

#include"config.h"

#include"thread.h"

namespace sylar{

const char *LogLevel::Tostring(LogLevel::Level level)

{

//宏替换,#name 等效于"name"

switch(level){

#define XX(name) \

case LogLevel::name: \

return #name;

XX(DEBUG);

XX(INFO);

XX(WARN);

XX(ERROR);

XX(FATAL);

#undef XX

default:

return "UNKNOW";

}

return "UNKNOW";

}

LogLevel::Level LogLevel::FromString(const std::string &str)

{

//用strcasecmp简化掉

#define XX(LEVEL,v) \

if(strcasecmp(str.c_str(),#v)==0){ \

return LogLevel::LEVEL; \

}

XX(DEBUG,debug)

XX(INFO,info)

XX(WARN,warn)

XX(ERROR,error)

XX(FATAL,fatal)

#undef XX

return LogLevel::UNKNOW;

}

//消息体

class MessageFormatItem : public LogFormatter::FormatItem

{

public:

MessageFormatItem(const std::string &str = "") {}

void format(std::ostream &os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override

{

os << event->getContent();

}

};

//日志等级

class LevelFormatItem : public LogFormatter::FormatItem{

public:

LevelFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << LogLevel::Tostring(level);

}

};

//运行时间

class ElapseFormatItem : public LogFormatter::FormatItem{

public:

ElapseFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getElapse();

}

};

//日志名称

class NameFormatItem : public LogFormatter::FormatItem{

public:

NameFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getLogger()->getName();

}

};

//线程id

class ThreadIdFormatItem : public LogFormatter::FormatItem{

public:

ThreadIdFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getThreadId();

}

};

// 协程id

class FiberIdFormatItem : public LogFormatter::FormatItem{

public:

FiberIdFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getFiberId();

}

};

//线程名

class ThreadNameFormat : public LogFormatter::FormatItem{

public:

ThreadNameFormat(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getThreadName();

}

};

//按指定格式输出时间

class DateTimeIdFormatItem : public LogFormatter::FormatItem{

public:

DateTimeIdFormatItem(const std::string & format = "%Y-%m-%d %H:%M:%S")

:m_format(format){

if(m_format.empty()){

m_format="%Y-%m-%d %H:%M:%S";

}

}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

struct tm tm;

time_t time = event->getTime();

localtime_r(&time,&tm);

char buf[64]={};

strftime(buf,sizeof(buf),m_format.c_str(),&tm);

os << buf;

}

private:

std::string m_format;

};

//文件名

class FilenameFormatItem : public LogFormatter::FormatItem{

public:

FilenameFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getFile();

}

};

//行号

class LineFormatItem : public LogFormatter::FormatItem{

public:

LineFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << event->getLine();

}

};

//换行

class NewLineFormatItem : public LogFormatter::FormatItem{

public:

NewLineFormatItem(const std::string & str = ""){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << std::endl;

}

};

//字符常量

class StringFormatItem : public LogFormatter::FormatItem{

public:

StringFormatItem(const std::string & str):

m_string(str) {}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << m_string;

}

private:

std::string m_string;

};

//制表符

class TabFormatItem : public LogFormatter::FormatItem{

public:

TabFormatItem(const std::string & str){}

void format(std::ostream& os,Logger::ptr logger,LogLevel::Level level,LogEvent::ptr event) override{

os << '\t';

}

private:

};

Logger::Logger(const std::string &name): m_name(name),m_level(LogLevel::DEBUG)

{

m_formatter.reset(new LogFormatter("%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%F%T[%p]%T[%c]%T%f:%l%T%m%n"));

}

void Logger::log(LogLevel::Level level, LogEvent::ptr event)

{

if(level >= m_level){

auto z = shared_from_this();

MutexType::Lock lock(m_mutex);

if(!m_appender.empty()){

for(auto & i : m_appender){

i->log(z,level,event);

}

}else if(m_root){

m_root->log(level,event);

}

}

}

void Logger::debug(LogEvent::ptr event)

{

log(LogLevel::DEBUG,event);

}

void Logger::info(LogEvent::ptr event)

{

log(LogLevel::INFO,event);

}

void Logger::warn(LogEvent::ptr event)

{

log(LogLevel::WARN,event);

}

void Logger::fatal(LogEvent::ptr event)

{

log(LogLevel::FATAL,event);

}

void Logger::error(LogEvent::ptr event)

{

log(LogLevel::ERROR,event);

}

void Logger::addAppender(LogAppender::ptr appender)

{

MutexType::Lock lock(m_mutex);

if(!appender->getFormatter()){

MutexType::Lock lock(appender->m_mutex);

appender->m_formatter=m_formatter;

}

m_appender.push_back(appender);

}

void Logger::delAppender(LogAppender::ptr appender)

{

MutexType::Lock lock(m_mutex);

for(auto it = m_appender.begin();it!=m_appender.end();++it){

if(*it == appender){

m_appender.erase(it);

break;

}

}

}

void Logger::clearAppenders()

{

MutexType::Lock lock(m_mutex);

m_appender.clear();

}

void Logger::setFormatter(LogFormatter::ptr val)

{

MutexType::Lock lock(m_mutex);

m_formatter=val;

for(auto & i :m_appender){

MutexType::Lock ll(i->m_mutex);

if(!i->m_hasFormatter){

i->m_formatter=m_formatter;

}

}

}

void Logger::setFormatter(const std::string &val)

{

sylar::LogFormatter::ptr new_val(new sylar::LogFormatter(val));

if(new_val->isError()){

std::cout<<"Logger setFormatter name=" <

<<"value = "<

<< std::endl;

return;

}

// m_formatter=new_val;

setFormatter(new_val);

}

LogFormatter::ptr Logger::getFormatter()

{

MutexType::Lock lock(m_mutex);

return m_formatter;

}

std::string Logger::toYamlString()

{

MutexType::Lock lock(m_mutex);

YAML::Node node;

node["name"] = m_name;

if(m_level != LogLevel::UNKNOW){

node["level"] = LogLevel::Tostring(m_level);

}

if(m_formatter){

node["formatter"] = m_formatter->getPattern();

}

for(auto & i: m_appender){

node["appender"].push_back(YAML::Load(i->toYamlString()));

}

std::stringstream ss;

ss << node;

return ss.str();

}

FileLogAppender::FileLogAppender(const std::string filename) : m_filename(filename)

{

reopen();

}

void FileLogAppender::log(std::shared_ptrlogger,LogLevel::Level level, LogEvent::ptr event)

{

if(level>=m_level){

MutexType::Lock lock(m_mutex);

m_filestream << m_formatter->format(logger,level,event);

}

}

std::string FileLogAppender::toYamlString()

{

MutexType::Lock lock(m_mutex);

YAML::Node node;

node["type"] = "FileLogAppender";

node["file"] = m_filename;

if(m_level != LogLevel::UNKNOW){

node["level"] = LogLevel::Tostring(m_level);

}

if(m_hasFormatter && m_formatter){

node["formatter"] = m_formatter->getPattern();

}

std::stringstream ss;

ss << node;

return ss.str();

}

bool FileLogAppender::reopen()

{

MutexType::Lock lock(m_mutex);

if(m_filestream){

m_filestream.close();

}

m_filestream.open(m_filename);

return !!m_filestream;

}

std::string StdoutLogAppender::toYamlString()

{

MutexType::Lock lock(m_mutex);

YAML::Node node;

node["type"] = "StdoutLogAppender";

if(m_level != LogLevel::UNKNOW){

node["level"] = LogLevel::Tostring(m_level);

}

if(m_hasFormatter&& m_formatter){

node["formatter"] = m_formatter->getPattern();

}

std::stringstream ss;

ss << node;

return ss.str();

}

void StdoutLogAppender::log(std::shared_ptr logger, LogLevel::Level level, LogEvent::ptr event)

{

if(level>=m_level){

MutexType::Lock lock(m_mutex);

std::cout<< m_formatter->format(logger,level,event);

}

}

LogFormatter::LogFormatter(const std::string pattern):m_pattern(pattern)

{

init();

}

std::string LogFormatter::format(std::shared_ptrlogger,LogLevel::Level level,LogEvent::ptr event)

{

std::stringstream ss;

for(auto & i:m_items){

i->format(ss,logger,level,event);

}

return ss.str();

}

//%xxx %xxx{xxx} %%

void LogFormatter::init()

{

//str,format,type

//type = 0 非转义

//type = 1 转义

std::vector> vec;

//用于存非转义字符

std::string nstr;

for(size_t i =0;i

//非转义字符

if(m_pattern[i]!='%'){

nstr.append(1,m_pattern[i]);

continue;

}

//处理%%

if((i+1)

if(m_pattern[i+1]=='%'){

nstr.append(1,'%');

++i;

continue;

}

}

//遇到了%

size_t n= i +1;

//{的开始位置

size_t fmt_begin = 0;

//是否进入{}的处理

int fmt_status = 0;

//%str{fmt}

size_t n = i + 1;

int fmt_status = 0;

size_t fmt_begin = 0;

std::string str;

std::string fmt;

while(n < m_pattern.size()) {

if(!fmt_status && (!isalpha(m_pattern[n]) && m_pattern[n] != '{'

&& m_pattern[n] != '}')) {

str = m_pattern.substr(i + 1, n - i - 1);

break;

}

if(fmt_status == 0) {

if(m_pattern[n] == '{') {

str = m_pattern.substr(i + 1, n - i - 1);

//std::cout << "*" << str << std::endl;

fmt_status = 1; //解析格式

fmt_begin = n;

++n;

continue;

}

} else if(fmt_status == 1) {

if(m_pattern[n] == '}') {

fmt = m_pattern.substr(fmt_begin + 1, n - fmt_begin - 1);

//std::cout << "#" << fmt << std::endl;

fmt_status = 0;

++n;

break;

}

}

++n;

if(n == m_pattern.size()) {

if(str.empty()) {

str = m_pattern.substr(i + 1);

}

}

}

if(fmt_status == 0) {

if(!nstr.empty()) {

vec.push_back(std::make_tuple(nstr, std::string(), 0));

nstr.clear();

}

vec.push_back(std::make_tuple(str, fmt, 1));

i = n - 1;

} else if(fmt_status == 1) {

std::cout << "pattern parse error: " << m_pattern << " - " << m_pattern.substr(i) << std::endl;

m_error = true;

vec.push_back(std::make_tuple("<>", fmt, 0));

}

}

if(!nstr.empty()){

vec.emplace_back(nstr,"",0);

nstr.clear();

}

//字符到仿函数的映射

static std::map> s_format_items = {

#define XX(str,C) \

{#str,[](const std::string & fmt ){return FormatItem::ptr(new C(fmt));}}

XX(m,MessageFormatItem),

XX(p,LevelFormatItem),

XX(r,ElapseFormatItem),

XX(c,NameFormatItem),

XX(t,ThreadIdFormatItem),

XX(n,NewLineFormatItem),

XX(d,DateTimeIdFormatItem),

XX(f,FilenameFormatItem),

XX(l,LineFormatItem),

XX(T,TabFormatItem),

XX(F,FiberIdFormatItem),

XX(N,ThreadNameFormat)

#undef XX

};

for(auto & i:vec){

//字符常量

if(std::get<2>(i)==0){

m_items.push_back(FormatItem::ptr(new StringFormatItem(std::get<0>(i))));

} else {

auto it = s_format_items.find(std::get<0>(i));

if(it == s_format_items.end()){

m_items.push_back(FormatItem::ptr(new StringFormatItem("<(i)+">>")));

m_error = true;

} else {

//填入fmt,有些不需要就填个空串,但仿函数一定要参数统一

m_items.push_back(it->second(std::get<1>(i)));

}

}

// std::cout << std::get<0>(i) << " - "<(i) << " - " << std::get<2>(i) <

}

//%m 消息体

//%p level

//%r 启动后时间

//%c 日志名称

//%t 线程id

//%n 回车换行

//%d 时间

//%d 文件名

//%l 行号

}

LogEvent::LogEvent(Logger::ptr logger,LogLevel::Level level,const char * file , int32_t line , uint32_t elapse,

uint32_t threadid,uint32_t fiberId,uint64_t time,const std::string & thread_name)

:m_file(file),m_line(line),m_elapse(elapse),m_threadId(threadid),m_fiberId(fiberId),

m_time(time),m_threadName(thread_name),m_logger(logger),m_level(level)

{

}

//销毁后自动输出变量

//if语句后声明周期就结束了,配和宏一起用

LogEventWrap::~LogEventWrap()

{

m_event->getLogger()->log(m_event->getLevel(),m_event);

}

void LogEvent::format(const char *fmt, ...)

{

//处理变长参数的固定写法

va_list al;

//将al指向fmt之后的一个位置

va_start(al,fmt);

format(fmt,al);

va_end(al);

}

void LogEvent::format(const char *fmt, va_list al)

{

char * buf = nullptr;

//vasprintf 将al以fmt格式输出到buf里,buf内存自动分配

int len = vasprintf(&buf,fmt,al);

if(len!=-1){

m_ss << std::string (buf,len);

free(buf);

}

}

LoggerManager::LoggerManager()

{

m_root.reset(new Logger);

m_root->addAppender(LogAppender::ptr(new StdoutLogAppender));

m_logger[m_root->m_name] = m_root;

init();

}

Logger::ptr LoggerManager::getLogger(const std::string &name)

{

MutexType::Lock lock(m_mutex);

auto it = m_logger.find(name);

if(it != m_logger.end()){

return it->second;

}

Logger::ptr logger(new Logger(name));

logger->m_root = m_root;

m_logger[name] = logger;

return logger;

}

//以下部分为yaml和配置文件之间相互转化辅助用

//appender在yaml文件中只会输出类型,format,filename

struct LogAppenderDefine{

int type = 0;

LogLevel::Level level = LogLevel::Level::UNKNOW;

std::string formatter;

std::string file;

bool operator==(const LogAppenderDefine & oth)const {

return type==oth.type&&

level == oth.level&&

formatter == oth.formatter&&

file == oth.file;

}

};

//同理,用于记录在yaml中log的信息

struct LogDefine {

std::string name;

LogLevel::Level level;

std::string formatter;

std::vector appenders;

bool operator==(const LogDefine& oth)const {

return name == oth.name &&

level == oth.level &&

formatter == oth.formatter &&

appenders == oth.appenders;

}

bool operator<(const LogDefine & oth) const{

return name < oth.name ;

}

};

//模板全特化

//string -> std::set

template<>

class LexicalCast> {

public:

std::set operator()(const std::string & v){

YAML::Node node = YAML::Load(v);

std::set vec;

for(size_t i = 0;i

const auto & n =node[i];

if(!n["name"].IsDefined()){

std::cout<<"log config error: name is null ,"<

continue;

}

LogDefine id;

id.name = n["name"].as();

id.level = LogLevel::FromString(n["level"].IsDefined()?n["level"].as():"");

if(n["formatter"].IsDefined()){

id.formatter = n["formatter"].as();

}

if(n["appender"].IsDefined()){

for(size_t i= 0;i

auto a =n["appender"][i];

if(!a["type"].IsDefined()){

std::cout<<"log config error: appender type is null ,"<

continue;

}

std::string type = a["type"].as();

LogAppenderDefine lad;

if(type == "FileLogAppender"){

lad.type=1;

if(!a["file"].IsDefined()){

std::cout<<"log config error: fileappender file is null ,"<

continue;

}

lad.file = a["file"].as();

if(a["formatter"].IsDefined()){

lad.formatter = a["formatter"].as();

}

}else if(type == "StdoutLogAppender"){

lad.type=2;

}else{

std::cout<<"log config error: appender type is invaild ,"<

continue;

}

id.appenders.push_back(lad);

}

}

vec.insert(id);

}

return vec;

}

};

//模板全特化

//std::set -> string

template<>

class LexicalCast,std::string> {

public:

std::string operator()(const std::set & v){

YAML::Node node ;

for(auto & i :v){

YAML::Node n;

n["name"] = i.name;

if(i.level != LogLevel::UNKNOW){

n["level"] =LogLevel::Tostring(i.level);

}

if(!i.formatter.empty()){

n["formatter"]=i.formatter;

}

for(auto &a:i.appenders){

YAML::Node na;

if(a.type==1){

na["type"]="FileLogAppender";

na["file"]=a.file;

}else if(a.type==2){

na["type"]="StdoutLogAppender";

}

if(a.level != LogLevel::UNKNOW){

na["level"] = LogLevel::Tostring(a.level);

}

na["level"] = LogLevel::Tostring(a.level);

if(!a.formatter.empty()){

na["formatter"]=a.formatter;

}

n["appender"].push_back(na);

}

node.push_back(n);

}

std::stringstream ss;

ss << node;

return ss.str();

}

};

ConfigVar>::ptr g_log_defines =

Config::Lookup("logs",std::set(),"logs config");

//静态对象托管,用于在main函数之前初始化对象

struct LogIniter{

LogIniter(){

g_log_defines->addListener([](const std::set & old_value,

const std::set & new_value){

SYLAR_LOG_INFO(SYLAR_LOG_ROOT()) << "on_logger_conf_changed";

//枚举新值中的旧值

for(auto & i :new_value){

auto it = old_value.find(i);

sylar::Logger::ptr logger;

if(it==old_value.end()){

//add logger

logger = SYLAR_LOG_NAME(i.name);

}else {

if(!(i == *it)){

//modify

logger = SYLAR_LOG_NAME(i.name);

}

}

logger->setLevel(i.level);

if(!i.formatter.empty()){

logger->setFormatter(i.formatter);

}

logger->clearAppenders();

for(auto & a:i.appenders){

sylar::LogAppender::ptr ap;

if(a.type==1){

ap.reset(new FileLogAppender(a.file));

}else if(a.type==2){

ap.reset(new StdoutLogAppender);

}

ap->setLevel(a.level);

if(!a.formatter.empty()){

LogFormatter::ptr fmt(new LogFormatter(a.formatter));

if(!fmt->isError()){

ap->setFormatter(fmt);

}else {

std::cout << "appender type = "<

}

}

logger->addAppender(ap);

}

}

//枚举旧值中的新值

for(auto & i :old_value){

auto it = new_value.find(i);

if(it == new_value.end()){

//delete

//不实际删除

auto logger = SYLAR_LOG_NAME(i.name);

logger->setLevel((LogLevel::Level)100);

logger->clearAppenders();

}

}

});

}

};

static LogIniter __log_init;

void LoggerManager::init()

{

}

std::string LoggerManager::toYamlString()

{

MutexType::Lock lock(m_mutex);

YAML::Node node;

for(auto & i : m_logger){

node.push_back(YAML::Load(i.second->toYamlString()));

}

std::stringstream ss;

ss << node;

return ss.str();

}

void LogAppender::setFormatter(LogFormatter::ptr val)

{

MutexType::Lock lock(m_mutex);

m_formatter = val;

if(m_formatter){

m_hasFormatter = true;

}

else {

m_hasFormatter = false;

}

}

LogFormatter::ptr LogAppender::getFormatter()

{

MutexType::Lock lock(m_mutex);

return m_formatter;

}

}