or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-services.mdbinary-logging.mdchannelz.mdhealth-checking.mdindex.mdload-balancing.mdmetrics.mdserver-reflection.md

binary-logging.mddocs/

0

# Binary Logging

1

2

Request and response logging system for debugging, auditing, and compliance. Binary logging captures detailed information about gRPC calls including headers, messages, and metadata in a structured format.

3

4

## Capabilities

5

6

### BinaryLogs

7

8

Factory class for creating binary logging instances with different configurations and sinks.

9

10

```java { .api }

11

/**

12

* Utility class for creating binary logging instances.

13

* Provides factory methods for different logging configurations.

14

*/

15

@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4017")

16

public final class BinaryLogs {

17

18

/**

19

* Creates a binary log that writes to a temp file

20

* @return BinaryLog instance configured with temporary file sink

21

* @throws IOException if temp file cannot be created

22

*/

23

public static BinaryLog createBinaryLog() throws IOException;

24

25

/**

26

* Creates a binary log with custom sink and config string

27

* @param sink Custom sink for writing log messages

28

* @param configStr Config string as defined by A16-binary-logging specification

29

* @return BinaryLog instance with custom configuration

30

* @throws IOException if sink initialization fails

31

*/

32

public static BinaryLog createBinaryLog(

33

BinaryLogSink sink,

34

String configStr

35

) throws IOException;

36

37

/**

38

* Creates a binary log with sink only (deprecated)

39

* @param sink Custom sink for writing log messages

40

* @return BinaryLog instance

41

* @throws IOException if sink initialization fails

42

* @deprecated Use createBinaryLog(BinaryLogSink, String) instead

43

*/

44

@Deprecated

45

public static BinaryLog createBinaryLog(BinaryLogSink sink) throws IOException;

46

}

47

```

48

49

**Usage Examples:**

50

51

```java

52

import io.grpc.BinaryLog;

53

import io.grpc.ServerBuilder;

54

import io.grpc.protobuf.services.BinaryLogs;

55

import io.grpc.protobuf.services.TempFileSink;

56

57

// Simple binary logging to temp file

58

BinaryLog binaryLog = BinaryLogs.createBinaryLog();

59

60

Server server = ServerBuilder.forPort(8080)

61

.setBinaryLog(binaryLog)

62

.addService(new MyService())

63

.build();

64

65

// Custom binary logging with configuration

66

BinaryLogSink customSink = new TempFileSink();

67

String config = "*"; // Log all methods

68

BinaryLog configuredLog = BinaryLogs.createBinaryLog(customSink, config);

69

70

Server configuredServer = ServerBuilder.forPort(8081)

71

.setBinaryLog(configuredLog)

72

.addService(new MyService())

73

.build();

74

```

75

76

### BinaryLogSink

77

78

Interface for implementing custom binary log sinks that handle the actual storage or transmission of log data.

79

80

```java { .api }

81

/**

82

* Interface for accepting binary log messages.

83

* Implement this interface to create custom log storage backends.

84

*/

85

@ExperimentalApi("https://github.com/grpc/grpc-java/issues/4017")

86

public interface BinaryLogSink extends Closeable {

87

88

/**

89

* Writes the message to the destination

90

* @param message Protocol buffer message containing log data

91

*/

92

void write(MessageLite message);

93

}

94

```

95

96

**Custom Sink Implementation Example:**

97

98

```java

99

import io.grpc.protobuf.services.BinaryLogSink;

100

import com.google.protobuf.MessageLite;

101

import java.io.FileOutputStream;

102

import java.io.IOException;

103

104

public class CustomFileSink implements BinaryLogSink {

105

private final FileOutputStream outputStream;

106

107

public CustomFileSink(String filename) throws IOException {

108

this.outputStream = new FileOutputStream(filename, true); // Append mode

109

}

110

111

@Override

112

public void write(MessageLite message) {

113

try {

114

// Write message size first

115

byte[] messageBytes = message.toByteArray();

116

byte[] sizeBytes = ByteBuffer.allocate(4)

117

.putInt(messageBytes.length)

118

.array();

119

120

outputStream.write(sizeBytes);

121

outputStream.write(messageBytes);

122

outputStream.flush();

123

124

} catch (IOException e) {

125

System.err.println("Failed to write binary log: " + e.getMessage());

126

}

127

}

128

129

@Override

130

public void close() throws IOException {

131

if (outputStream != null) {

132

outputStream.close();

133

}

134

}

135

}

136

```

137

138

### TempFileSink

139

140

Built-in implementation that writes logs to temporary files.

141

142

```java { .api }

143

/**

144

* Binary log sink that writes to temporary files.

145

* Useful for development and debugging scenarios.

146

*/

147

public class TempFileSink implements BinaryLogSink {

148

/** Creates a temp file sink that writes to a system temporary file */

149

public TempFileSink() throws IOException;

150

}

151

```

152

153

**Usage Example:**

154

155

```java

156

import io.grpc.protobuf.services.TempFileSink;

157

import io.grpc.protobuf.services.BinaryLogs;

158

159

// Create binary log with temp file sink

160

BinaryLogSink tempSink = new TempFileSink();

161

BinaryLog binaryLog = BinaryLogs.createBinaryLog(tempSink, "*");

162

163

// Use with server

164

Server server = ServerBuilder.forPort(8080)

165

.setBinaryLog(binaryLog)

166

.addService(new MyService())

167

.build();

168

169

// Don't forget to close the sink when done

170

Runtime.getRuntime().addShutdownHook(new Thread(() -> {

171

try {

172

tempSink.close();

173

} catch (IOException e) {

174

System.err.println("Error closing binary log sink: " + e.getMessage());

175

}

176

}));

177

```

178

179

## Configuration Patterns

180

181

Binary logging supports flexible configuration using the A16-binary-logging specification:

182

183

### Basic Configuration Examples

184

185

```java

186

// Log all methods on all services

187

String configAll = "*";

188

BinaryLog logAll = BinaryLogs.createBinaryLog(sink, configAll);

189

190

// Log specific service

191

String configService = "com.example.UserService/*";

192

BinaryLog logService = BinaryLogs.createBinaryLog(sink, configService);

193

194

// Log specific method

195

String configMethod = "com.example.UserService/GetUser";

196

BinaryLog logMethod = BinaryLogs.createBinaryLog(sink, configMethod);

197

198

// Log with size limits (header and message bytes)

199

String configLimited = "*{h:256;m:1024}";

200

BinaryLog logLimited = BinaryLogs.createBinaryLog(sink, configLimited);

201

```

202

203

### Advanced Configuration

204

205

```java

206

public class BinaryLogConfiguration {

207

208

public static BinaryLog createProductionLog() throws IOException {

209

// Production logging: limited data, specific services only

210

BinaryLogSink sink = new ProductionLogSink();

211

212

// Log only critical services with size limits

213

String config = "com.example.PaymentService/*{h:512;m:2048}," +

214

"com.example.AuthService/*{h:256;m:1024}";

215

216

return BinaryLogs.createBinaryLog(sink, config);

217

}

218

219

public static BinaryLog createDevelopmentLog() throws IOException {

220

// Development logging: full data for debugging

221

BinaryLogSink sink = new TempFileSink();

222

223

// Log everything with large limits

224

String config = "*{h:8192;m:65536}";

225

226

return BinaryLogs.createBinaryLog(sink, config);

227

}

228

229

public static BinaryLog createAuditLog() throws IOException {

230

// Audit logging: specific methods only

231

BinaryLogSink sink = new AuditLogSink();

232

233

// Log only sensitive operations

234

String config = "com.example.UserService/CreateUser," +

235

"com.example.UserService/DeleteUser," +

236

"com.example.PaymentService/ProcessPayment";

237

238

return BinaryLogs.createBinaryLog(sink, config);

239

}

240

}

241

```

242

243

## Integration with Monitoring Systems

244

245

### Structured Logging Integration

246

247

```java

248

import io.grpc.protobuf.services.BinaryLogSink;

249

import com.google.protobuf.MessageLite;

250

import io.grpc.binarylog.v1.GrpcLogEntry;

251

252

public class MonitoringLogSink implements BinaryLogSink {

253

private final Logger logger = LoggerFactory.getLogger(MonitoringLogSink.class);

254

255

@Override

256

public void write(MessageLite message) {

257

if (message instanceof GrpcLogEntry) {

258

GrpcLogEntry logEntry = (GrpcLogEntry) message;

259

260

// Extract key information for structured logging

261

Map<String, Object> logData = new HashMap<>();

262

logData.put("timestamp", logEntry.getTimestamp());

263

logData.put("type", logEntry.getType().name());

264

logData.put("logger", logEntry.getLogger().name());

265

266

if (logEntry.hasCallId()) {

267

logData.put("callId", logEntry.getCallId());

268

}

269

270

if (logEntry.hasClientHeader()) {

271

logData.put("method", logEntry.getClientHeader().getMethodName());

272

logData.put("authority", logEntry.getClientHeader().getAuthority());

273

}

274

275

// Send to monitoring system

276

logger.info("gRPC call logged: {}", logData);

277

}

278

}

279

280

@Override

281

public void close() throws IOException {

282

// Cleanup monitoring connections if needed

283

}

284

}

285

```

286

287

### Performance Monitoring

288

289

```java

290

public class PerformanceAwareBinaryLog {

291

private final BinaryLog binaryLog;

292

private final AtomicLong logCount = new AtomicLong(0);

293

294

public PerformanceAwareBinaryLog() throws IOException {

295

// Create custom sink that tracks performance

296

BinaryLogSink performanceSink = new BinaryLogSink() {

297

private final BinaryLogSink delegate = new TempFileSink();

298

299

@Override

300

public void write(MessageLite message) {

301

long count = logCount.incrementAndGet();

302

303

// Log performance warning if logging rate is high

304

if (count % 10000 == 0) {

305

System.out.println("Binary log count: " + count);

306

}

307

308

delegate.write(message);

309

}

310

311

@Override

312

public void close() throws IOException {

313

delegate.close();

314

}

315

};

316

317

// Use moderate configuration to balance debugging and performance

318

String config = "*{h:1024;m:4096}";

319

this.binaryLog = BinaryLogs.createBinaryLog(performanceSink, config);

320

}

321

322

public BinaryLog getBinaryLog() {

323

return binaryLog;

324

}

325

326

public long getLogCount() {

327

return logCount.get();

328

}

329

}

330

```

331

332

## Security and Compliance

333

334

Binary logging can capture sensitive data, so proper handling is essential:

335

336

```java

337

public class SecureBinaryLogSink implements BinaryLogSink {

338

private final BinaryLogSink delegate;

339

private final Set<String> sensitiveHeaders;

340

341

public SecureBinaryLogSink(BinaryLogSink delegate) {

342

this.delegate = delegate;

343

this.sensitiveHeaders = Set.of(

344

"authorization",

345

"x-api-key",

346

"cookie"

347

);

348

}

349

350

@Override

351

public void write(MessageLite message) {

352

// In a real implementation, you would need to parse and sanitize

353

// the message to remove sensitive data before delegating

354

355

// For demonstration, we'll just delegate

356

// In practice, implement message filtering here

357

delegate.write(message);

358

}

359

360

@Override

361

public void close() throws IOException {

362

delegate.close();

363

}

364

}

365

366

// Usage

367

BinaryLogSink secureHttp = new SecureBinaryLogSink(new TempFileSink());

368

BinaryLog secureLog = BinaryLogs.createBinaryLog(secureHttp, "*{h:512;m:0}"); // Headers only, no message bodies

369

```