npm package: @horustracer/clientwrapper
Description: Horus's ClientWrapper
Author: NY19
Latest version: 1.0.5

# What is Horus?

<b>Horus</b> is a Distributed Tracing and Monitoring Tool for gRPC-Node Applications. 

Our team aims to provide the user a seamless experience in adding tracing and monitoring functionality to their application with our NPM Packages!<br/><br/>


<b>\*\*\* Check out our GitHub Repo for Step-By-Step Guides, Explanations, API, and more: https://github.com/oslabs-beta/Horus/ \*\*\*</b>


<b>Core Features</b> :zap:
- Horus traces, logs and monitors gRPC requests. Tracing and logging features include:
    1. Provides data on which gRPC method was called for a specific gRPC request.
    2. How long it took to complete the gRPC request.
    3. Date/Time of Completion.
    4. Traces any additional Intraservice Requests that were made in completing that request.
    5. Request data will be outputted in a text file (but users can also visualize the data with our Neo4J Integration.)
- Alerts user whenever gRPC request times go beyond a threshold of (+/-) 2 STD of its average request time using Slack Webhooks.
- We provide a mock-microservice which performs gRPC requests AND <b>intraservice gRPC requests</b> between 2 different services. 
- Neo4j Integration to visualize data.
<br/>

<b>The Mock-Microservice app. (in master branch) that we provide is a <b>bookstore app.</b> with the following services: </b>
<br/>
- Books Service
- Customers Service
<br/>

And yes, it does support intraservice gRPC requests! (Check out our setup tutorial in the table of contents below).

*All modules can be found under the npm organization @horustracer.*
*If you have any questions, please reach out to the team at: HorusTracerOfficial@gmail.com*

<br/>
<br/>



# Installation


Installing Horus into your application is quick and easy. 
<br>
<b>Follow the steps below</b> to set up the <b>ClientWrapper, ServerWrapper, and any intraservice requests</b> that you have. 

*For a more in depth guide to installing Horus, check the tutorial right below the installation section.*

<b>NPM Installation: </b>
```js
npm install @horustracer/ClientWrapper
npm install @horustracer/ServerWrapper
            
or 
            
npm install @horustracer/ClientWrapper @horustracer/ServerWrapper 
```
<br/>

<b>1. Setting up the ClientWrapper</b>
<br/>

- Import the ClientWrapper from @horustracer/ClientWrapper into your stub (gRPC client) file. 
- Initialize a new instance of the ClientWrapper, passing in the gRPC client, service and output text file name. 
- Then export the ClientWrapper in the place of your previous stub.

```js
/*
The Horus ClientWrapper does its magic by "wrapping" your preexisting gRPC stub (gRPC client). 
Think of it as a middleman which lives between you (the developer) and your stub. 
Horus uses a similar approach for the ServerWrapper, except it wraps your server methods rather than the gRPC server itself.
*/

const HorusClientWrapper = require('@horustracer/ClientWrapper');
const grpc = require("grpc");
const protoLoader = require("@grpc/proto-loader");
const path = require('path');
const PROTO_PATH = path.join(__dirname, "../protos/books.proto");

const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  arrays: true
});

const BooksService = grpc.loadPackageDefinition(packageDefinition).BooksService;

const client = new BooksService (
  "localhost:30043",
  grpc.credentials.createInsecure()
);

const ClientWrapper = new HorusClientWrapper(client, BooksService, 'books.txt');

module.exports = ClientWrapper;
```
<br/>

<b>2. Setting up the ServerWrapper</b>
<br/>

- Import the ServerWrapper into your server file. 
- Rather than invoking the server.addService method, create a new instance of the ServerWrapper, passing in the server, proto, and methods as arguments.

```js
/*
In order to wrap your server methods, Horus instead uses the ServerWrapper object (see the example below). 
A new instance of the ServerWrapper is created, passing in the plain gRPC server object, service, and methods.
*/

const HorusServerWrapper = require('@horustracer/ServerWrapper);
const grpc = require('grpc');
const protoLoader = require("@grpc/proto-loader");
const path = require('path');
const controller = require("./booksController.js");
const PROTO_PATH = path.join(__dirname, '../protos/books.proto');

const ServerWrapper = new HorusServerWrapper(server, booksProto.BooksService.service, {
  CreateBook: async (call, callback) => {
    const book = call.request;

    let result = await controller.CreateBook(book);

    callback(null, result);
})

server.bind("127.0.0.1:30043", grpc.ServerCredentials.createInsecure());
server.start();
```
<br/>

<b>3. Intraservice Requests</b>
<br/>

- <b>***If you don't have any intraservice requests, you're all done and can skip this part.***</b>

```js
/*
If you do, invoke the makeHandShakeWithServer method in your intraservice request's callback. 
The makeHandShakeWithServer method lives on the ClientWrapper. It's first argument is the ServerWrapper it's being invoked in and the second is the name of the intraservice request. 
(Remember, your stub should be exporting the ClientWrapper rather than the gRPC client);
*/

const HorusServerWrapper = require('@horustracer/ServerWrapper);
const booksStub = require('../stubs/booksStubs.js)

const CustomerServerWrapper = new HorusServerWrapper(server, customersProto.CustomersService.service, {
  GetCustomer: async (call, callback) => {
    const customerId = call.request;

    const customer = await controller.GetCustomer(customerId);

    const customersFavoriteBookId = {favBookId: customer.favBookId};

    booksStub.GetBookById(customersFavoriteBookId, (error, response) => {

      booksStub.makeHandShakeWithServer(CustomerServerWrapper, 'GetBookById');

      callback(null, result);
    });
})
```

Once you have completed this step for your intraservice requests, you're all done.

<br/>
<br/>

<b>\*\*\* Check out our GitHub Repo for Step-By-Step Guides, Explanations, API, and more: https://github.com/oslabs-beta/Horus/ \*\*\*</b>