-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Standard logger interface #25
Comments
Do you have any suggestions? I know of |
Sure, a drop-in replacement for Especially |
hi @Magicking I experimented this night with a simple implementation of application insights for our services. cheers config.gopackage insights
import "github.com/Microsoft/ApplicationInsights-Go/appinsights"
type InsightsConfig struct {
InstrumentationKey string
Role string
Version string
}
func createTelemetryClient(config *InsightsConfig) appinsights.TelemetryClient {
client := appinsights.NewTelemetryClient(config.InstrumentationKey)
if len(config.Role) > 0 {
client.Context().Tags.Cloud().SetRole(config.Role)
}
if len(config.Version) > 0 {
client.Context().Tags.Application().SetVer(config.Version)
}
return client
} logrus.goTo log normal application logging, we do something like this: package insights
import (
"encoding/json"
"fmt"
"github.com/Microsoft/ApplicationInsights-Go/appinsights"
"github.com/Microsoft/ApplicationInsights-Go/appinsights/contracts"
"github.com/sirupsen/logrus"
)
func SetupLogrus(config *InsightsConfig) {
hook := &LogrusHook{
Client: createTelemetryClient(config),
}
logrus.AddHook(hook)
}
type LogrusHook struct {
Client appinsights.TelemetryClient
}
func (hook *LogrusHook) Levels() []logrus.Level {
return logrus.AllLevels
}
func (hook *LogrusHook) Fire(entry *logrus.Entry) error {
if _, ok := entry.Data["message"]; !ok {
entry.Data["message"] = entry.Message
}
level := convertSeverityLevel(entry.Level)
telemetry := appinsights.NewTraceTelemetry(entry.Message, level)
for key, value := range entry.Data {
value = formatData(value)
telemetry.Properties[key] = fmt.Sprintf("%v", value)
}
hook.Client.Track(telemetry)
return nil
}
func convertSeverityLevel(level logrus.Level) contracts.SeverityLevel {
switch level {
case logrus.PanicLevel:
return contracts.Critical
case logrus.FatalLevel:
return contracts.Critical
case logrus.ErrorLevel:
return contracts.Error
case logrus.WarnLevel:
return contracts.Warning
case logrus.InfoLevel:
return contracts.Information
case logrus.DebugLevel, logrus.TraceLevel:
return contracts.Verbose
default:
return contracts.Information
}
}
func formatData(value interface{}) (formatted interface{}) {
switch value := value.(type) {
case json.Marshaler:
return value
case error:
return value.Error()
case fmt.Stringer:
return value.String()
default:
return value
}
} ginto log incoming requsts, we wrote a simple middleware for gin package insights
import (
"strconv"
"time"
"github.com/Microsoft/ApplicationInsights-Go/appinsights"
"github.com/gin-gonic/gin"
)
func SetupGin(engine *gin.Engine, config *InsightsConfig) {
engine.Use(InsightsWithConfig(config))
}
func InsightsWithConfig(config *InsightsConfig) gin.HandlerFunc {
client := createTelemetryClient(config)
return func(c *gin.Context) {
url := c.Request.RequestURI
start := time.Now()
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
// Process request
c.Next()
if path == "/readiness" || path == "/liveness" {
return
}
end := time.Now()
duration := end.Sub(start)
clientIP := c.ClientIP()
method := c.Request.Method
statusCode := c.Writer.Status()
userAgent := c.Request.UserAgent()
//errorMessage := c.Errors.ByType(gin.ErrorTypePrivate).String()
bodySize := c.Writer.Size()
if query != "" {
path = path + "?" + query
}
telemetry := appinsights.NewRequestTelemetry(method, url, duration, strconv.Itoa(statusCode))
telemetry.Timestamp = end
telemetry.MarkTime(start, end)
telemetry.Source = clientIP
telemetry.Success = statusCode >= 200 && statusCode < 400
telemetry.Properties["user-agent"] = userAgent
telemetry.Measurements["body-size"] = float64(bodySize)
client.Track(telemetry)
}
} restywe use resty as rest client for calling other microservices or external services. package insights
import (
"fmt"
"net/url"
"strconv"
"github.com/Microsoft/ApplicationInsights-Go/appinsights"
"gopkg.in/resty.v1"
)
func SetupResty(config *InsightsConfig) {
resty.OnAfterResponse(restyHandler(config))
}
func restyHandler(config *InsightsConfig) func(*resty.Client, *resty.Response) error {
client := createTelemetryClient(config)
return func(c *resty.Client, response *resty.Response) error {
request := response.Request
start := request.Time
duration := response.Time()
statusCode := response.StatusCode()
name := fmt.Sprintf("%s %s", request.Method, request.URL)
success := statusCode < 400 || statusCode == 401
target := request.RawRequest.Host
// Sanitize URL for the request name
if parsedUrl, err := url.Parse(request.URL); err == nil {
// Remove the query
parsedUrl.RawQuery = ""
parsedUrl.ForceQuery = false
// Remove the fragment
parsedUrl.Fragment = ""
// Remove the user info, if any.
parsedUrl.User = nil
// Write back to name
name = parsedUrl.String()
}
name = fmt.Sprintf("%s %s", request.Method, name)
telemetry := appinsights.NewRemoteDependencyTelemetry(name, "HTTP", target, success)
telemetry.Data = request.URL
telemetry.ResultCode = strconv.Itoa(statusCode)
telemetry.MarkTime(start, start.Add(duration))
client.Track(telemetry)
return nil
}
} your mainif key, ok := os.LookupEnv("AZURE_INSTRUMENTATION_KEY"); ok {
insightsConfig := &insights.InsightsConfig{
Role: NAMEOFYOURAPP,
Version: VERSIONOFYOURAPP,
InstrumentationKey: key,
}
insights.SetupGin(router, insightsConfig) // remove if not using gin
insights.SetupResty(insightsConfig) // remove if not using resty
insights.SetupLogrus(insightsConfig) // remove if not using logrus
} |
With the following middleware, we get empty Operation name in Azure application insight Performance menu. What am I missing here, any suggestion is much appreciated.
|
@probal I figure out the solution that you have to specify the operation name through telemetry tag in this middleware as well like telemetry.Tags[contracts.OperationName] = fmt.Sprintf("%s %s", method, c.Request.URL.Path) |
Using a standard logger interface would allow having a drop-in replacement for Go logging with ApplicationInsights
The text was updated successfully, but these errors were encountered: