Пример #1
0
func TestLogger_WithFields(t *testing.T) {
	ctx := l.WithField("file", "1.png")
	ctx.Debug("uploading")
	ctx.Info("upload complete")

	ctx = l.WithField("payload", l.Fields{
		"file": "medium.png",
		"type": "image/png",
		"size": 1 << 20,
	})
	ctx.Debug("uploading")
	ctx.Info("upload complete")
}
Пример #2
0
func TestLogger_Trace_error(t *testing.T) {
	func() (err error) {
		defer l.WithField("file", "error.png").Trace("upload").Stop(&err)
		return fmt.Errorf("boom")
	}()

}
Пример #3
0
func BenchmarkLogger_medium(b *testing.B) {
	for i := 0; i < b.N; i++ {
		l.WithField("payload", l.Fields{
			"file": "medium.png",
			"type": "image/png",
			"size": 1 << 20,
		}).Info("upload")
	}
}
Пример #4
0
// Common behaviours to persist and publish populated Execution entity into our data layer and message bus
func (app FIXClient) processExecutionReport(er *proto.Execution) quickfix.MessageRejectError {

	// Find the Order by using the OrderKey without the Version
	// Need to try to LOAD the order, if that fails then alert stating unsolicited order received
	keyVersion := strings.Split(er.ClientOrderId, ".")
	if len(keyVersion) != 2 {
		return quickfix.ValueIsIncorrect(tag.ClOrdID)
	}
	if oKey, err := strconv.Atoi(keyVersion[0]); err != nil {
		return quickfix.ValueIsIncorrect(tag.ClOrdID)
	} else {
		if ord, err := app.OrderStore.OrderGetByOrderKey(int32(oKey)); err != nil {
			log.WithError(err).Warnf("Received ExecutionReport with OrderKey(%v) does not exist.", oKey)
			return nil // TODO: ignore or quickfix.ValueIsIncorrect(tag.ClOrdID)
		} else {
			er.OrderId = ord.OrderId
		}
	}

	// Persist the execution report
	if err := app.OrderStore.ExecutionCreate(er); err == nil {
		//publish to message bus
		data, _ := er.Marshal()
		app.MessageBus.Publish("order.Execution", data)
	} else {
		log.WithField("execution", er).WithError(err).Error("[ MC ] ERROR Create Reject Execution")
	}

	// Do any validating and if we are good to continue

	// Check if we need to cancel any execution
	// Check if we need to correct any execution
	switch er.ExecType {
	case proto.Execution_TRADE_CANCEL:
	case proto.Execution_TRADE_CORRECT:
	//TODO: TryGetAmendedExecution
	case proto.Execution_RESTATED:
	case proto.Execution_REJECTED:
	}

	// Check if the trade is fully filled or is done for day or canceled
	// .. Send message to TradePump to say trade filled and already to book.

	return nil
}
Пример #5
0
func (self *OrderRouter) reject(o *proto.Order, reason string) {

	execution := &proto.Execution{
		OrderId:            o.OrderId,
		OrderKey:           o.OrderKey,
		ClientOrderId:      fmt.Sprintf("%v.%v", o.OrderKey, o.Version),
		ExecType:           proto.Execution_REJECTED,
		OrderStatus:        proto.OrderStatus_REJECTED,
		BrokerExecDatetime: time.Now().UTC().Format(time.RFC3339Nano),
		Text:               reason,
	}

	if err := self.orderStore.ExecutionCreate(execution); err == nil {
		//publish to message bus
		data, _ := execution.Marshal()
		self.msgbus.Publish("order.Execution", data)
	} else {
		log.WithField("execution", execution).WithError(err).Error("[ OR ] ERROR Create Reject Execution")
	}

}
Пример #6
0
func NewService(c Config) *Service {

	// Hardware Info
	uuid = fmt.Sprint(hostname, ":", pid)
	log.Infof("Service [%v] starting @ %v", c.ServiceName, uuid)

	// Service handle
	svc := &Service{
		Config:          c,
		Status:          proto.STARTING,
		shutdownChannel: make(chan bool),
	}

	// Messaging bus
	messageBus, err := messagebus.Connect(svc.Config.MessageBusURL)
	svc.messageBus = messageBus
	if err != nil {
		log.WithField("MessageBusURL", svc.Config.MessageBusURL).Fatal("error: Cannot connect to message bus")
	}

	//Heartbeating
	currDateTime := time.Now().UTC().Format(time.RFC3339)
	hbMsg := &proto.Heartbeat{
		Name:             svc.Config.ServiceName,
		Id:               uuid,
		Status:           proto.STARTING,
		Machine:          hostname,
		CreationDatetime: currDateTime,
		CurrentDatetime:  currDateTime,
	}
	svc.lastHBMsg = hbMsg
	hbTicker := time.NewTicker(time.Second * time.Duration(svc.Config.HeartbeatFreq))
	go func(shutdownChannel chan bool) {
		publish_address := "service.Heartbeat." + svc.Config.ServiceName

		for range hbTicker.C {
			hbMsg.CurrentDatetime = time.Now().UTC().Format(time.RFC3339)
			hbMsg.Status = svc.Status

			if data, _ := hbMsg.Marshal(); data != nil {
				messageBus.Publish(publish_address, data)
			}

			select {
			case <-shutdownChannel:
				hbTicker.Stop()

				//Publish Stop heartbeat
				if svc.Status != proto.ERROR {
					svc.Status = proto.STOPPED
				}
				hbMsg.CurrentDatetime = time.Now().UTC().Format(time.RFC3339)
				hbMsg.Status = svc.Status
				if data, _ := hbMsg.Marshal(); data != nil {
					messageBus.Publish(publish_address, data)
				}

				messageBus.Close()

				log.Info("Server Terminated")
				return
			}
		}
	}(svc.shutdownChannel)

	return svc
}
Пример #7
0
func TestLogger_Trace_info(t *testing.T) {
	func() (err error) {
		defer l.WithField("file", "info.png").Trace("upload").Stop(&err)
		return nil
	}()
}
Пример #8
0
func TestLogger_WithField(t *testing.T) {
	ctx := l.WithField("file", "3.png").WithField("user", "Chao")
	ctx.Debug("uploading")
	ctx.Info("upload complete")
}
Пример #9
0
// start the logic spinning code for OrderRouter, using a single for..select.. pattern so there is no need to lock resources
// hence to avoid synchronisation issues
func (self *OrderRouter) Start() {
	go func() {
		for {
			select {
			case <-self.stopChan:
				self.msgbus.Close()
				self.msgbusService.Close()
				return

			// update known market connector list based on their heartbeat status
			case hbMsg := <-self.mcChan:
				svcName := strings.Replace(hbMsg.Name, "MC.", "", 1)
				if hbMsg.Status == service.RUNNING {
					self.mclist[svcName] = time.Now()
				} else {
					delete(self.mclist, svcName)
				}
			// remove market connector if we have not heard from it for a while
			case <-time.After(6 * time.Second):
				for name, lastHb := range self.mclist {
					if time.Since(lastHb).Seconds() > 6 {
						delete(self.mclist, name)
					}
				}
			case req := <-self.reqChan:
				func() { // wrap in func for defer reply

					requestError := ""
					var order *proto.Order

					// make sure reply message sent in the end
					defer func() {
						var data []byte
						errCode := int32(0)
						if requestError != "" {
							errCode = int32(-1)
						}
						switch req.RequestType {
						case REQ_NEW:
							resp := &proto.NewOrderResponse{
								ErrorCode:    errCode,
								ErrorMessage: &requestError,
								Order:        order,
							}
							data, _ = resp.Marshal()
						case REQ_CANCEL:
							resp := &proto.CancelOrderResponse{
								ErrorCode:    errCode,
								ErrorMessage: &requestError,
								Order:        order,
							}
							data, _ = resp.Marshal()
						case REQ_REPLACE:
							resp := &proto.ReplaceOrderResponse{
								ErrorCode:    errCode,
								ErrorMessage: &requestError,
								Order:        order,
							}
							data, _ = resp.Marshal()
						}
						self.msgbus.Publish(req.ReplyAddr, data)
					}()

					// Prepare order
					if req.RequestType == REQ_CANCEL || req.RequestType == REQ_REPLACE {
						// retrieve previous order for state check
						if prev_order, err := self.orderStore.OrderGet(req.OrderId); err != nil {
							requestError = "Order does not exists"
							return
						} else {
							// rule.1: working orders
							if prev_order.MessageType == proto.Order_NEW {
								if !(prev_order.OrderStatus == proto.OrderStatus_PARTIALLY_FILLED ||
									prev_order.OrderStatus == proto.OrderStatus_NEW) {
									requestError = fmt.Sprintf("Disallowed due to order status: %s", prev_order.OrderStatus)
									return
								}
							}
							// rule.2: pending cancel rejected
							if prev_order.MessageType == proto.Order_CANCEL {
								if !(prev_order.OrderStatus == proto.OrderStatus_REJECTED) {
									requestError = "Pending cancel on order"
									return
								}
							}
							// rule.2: pending replace acked by broker
							if prev_order.MessageType == proto.Order_REPLACE {
								if !(prev_order.OrderStatus == proto.OrderStatus_NEW ||
									prev_order.OrderStatus == proto.OrderStatus_REPLACED ||
									prev_order.OrderStatus == proto.OrderStatus_REJECTED) {
									requestError = "Pending replace on order"
									return
								}
							}

							// prepare for new order entry
							if req.RequestType == REQ_CANCEL {
								pReq := req.Request.(*proto.CancelOrderRequest)
								order = prev_order
								order.OrderId = 0                                                // wipe order id for new id
								order.Version++                                                  // bump up order key version
								order.SubmitDatetime = time.Now().UTC().Format(time.RFC3339Nano) // timing this cancel
								order.Trader = pReq.Trader                                       // trader who tries to cancel
								order.TraderId = pReq.TraderId                                   // trader who tries to cancel
								order.Source = pReq.Source                                       // source of cancel
								order.MessageType = proto.Order_CANCEL
								order.OrderStatus = proto.OrderStatus_CANCEL_RECEIVED
							}
							if req.RequestType == REQ_REPLACE {
								pReq := req.Request.(*proto.ReplaceOrderRequest)
								pReq.Order.OrderKey = prev_order.OrderKey

								order := pReq.Order
								order.OrderId = 0                                                // wipe order id for new id
								order.OrderKey = prev_order.OrderKey                             // in case client failed to provide correct order key
								order.Version = prev_order.Version + 1                           // bump up order key version
								order.SubmitDatetime = time.Now().UTC().Format(time.RFC3339Nano) // timing this replace
								order.Trader = pReq.Trader                                       // trader who tries to replace
								order.TraderId = pReq.TraderId                                   // trader who tries to replace
								order.MessageType = proto.Order_REPLACE
								order.OrderStatus = proto.OrderStatus_REPLACE_RECEIVED
							}

							//TODO: check ClientGUID consistency
						}
					} else {
						// New order
						pReq := req.Request.(*proto.NewOrderRequest)
						order = pReq.Order
						order.OrderId = 0
						order.Version = 0
					}

					// Persist order entry
					if err := self.orderStore.OrderCreate(order); err != nil {
						requestError = fmt.Sprint(err)
						log.WithError(err).Error("[ OR ] ERROR Create order")
						return
					}

					//TODO: allocations

					// Check target market connector is up
					if _, ok := self.mclist[order.MarketConnector]; ok == false {
						log.Warnf("OR->CL REJECT OrderKey: %v MC: %v : %v", order.OrderKey, order.MarketConnector, "LINK TO BROKER DOWN")

						// REJECT due to market connector down
						requestError = "LINK TO BROKER DOWN"

						// create Reject execution
						self.reject(order, "LINK TO BROKER DOWN")

					} else {
						log.WithField("order", order).Infof("OR->MC OrderKey: %v", order.OrderKey)

						// relay order with idents to its market connector
						// todo: special case on MC.AlgoAggregator
						var data []byte
						switch req.RequestType {
						case REQ_NEW:
							request := req.Request.(*proto.NewOrderRequest)
							data, _ = request.Marshal()
						case REQ_CANCEL:
							request := req.Request.(*proto.CancelOrderRequest)
							data, _ = request.Marshal()
						case REQ_REPLACE:
							request := req.Request.(*proto.ReplaceOrderRequest)
							data, _ = request.Marshal()
						}
						self.msgbus.Publish("order.NewOrderRequest.MC."+order.MarketConnector, data)
					}
				}()
			}
		}
	}()
}