Last active
October 22, 2021 19:04
-
-
Save saleem-mirza/004ffee97e38a1488e2ca3107c5785c8 to your computer and use it in GitHub Desktop.
Azure Log Analytics Logger in Golang
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/hmac" | |
"crypto/sha256" | |
"encoding/base64" | |
"net/http" | |
"time" | |
"unicode/utf8" | |
"strconv" | |
"bytes" | |
"strings" | |
"log" | |
) | |
const ( | |
// Replace with your Workspace ID | |
customerId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" | |
// Replace with your Primary or Secondary ID | |
sharedKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | |
//Specify the name of the record type that you'll be creating | |
logType = "GoLogType" | |
//Specify a field with the created time for the records | |
timeStampField = "DateValue" | |
) | |
func BuildSignature(message, secret string) (string, error) { | |
keyBytes, err := base64.StdEncoding.DecodeString(secret) | |
if err != nil { | |
return "", err | |
} | |
mac := hmac.New(sha256.New, keyBytes) | |
mac.Write([]byte(message)) | |
return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil | |
} | |
func PostData(data string) (error) { | |
dateString := time.Now().UTC().Format(time.RFC1123) | |
dateString = strings.Replace(dateString, "UTC", "GMT", -1) | |
stringToHash := "POST\n" + strconv.Itoa(utf8.RuneCountInString(data)) + "\napplication/json\n" + "x-ms-date:" + dateString + "\n/api/logs" | |
hashedString, err := BuildSignature(stringToHash, sharedKey) | |
if err != nil { | |
log.Println(err.Error()) | |
return err | |
} | |
signature := "SharedKey " + customerId + ":" + hashedString | |
url := "https://" + customerId + ".ods.opinsights.azure.com/api/logs?api-version=2016-04-01" | |
client := &http.Client{} | |
req, err := http.NewRequest("POST", url, bytes.NewReader([]byte(data))) | |
if err != nil { | |
return err | |
} | |
req.Header.Add("Log-Type", logName) | |
req.Header.Add("Authorization", signature) | |
req.Header.Add("Content-Type", "application/json") | |
req.Header.Add("x-ms-date", dateString) | |
req.Header.Add("time-generated-field", timeStampField) | |
resp, err := client.Do(req) | |
defer resp.Body.Close() | |
if err == nil { | |
log.Println(resp.Status) | |
return nil | |
} | |
return err | |
} | |
func main() { | |
var json = `[{"DemoField1":"DemoValue1","DemoField2":"DemoValue2"},{"DemoField3":"DemoValue3"}]` | |
PostData(json) | |
} |
I got the answer from someone on reddit:
utf8.RuneCountInString(data)
should just be the length in bytes, not in Runes, so len(data)
worked for me
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @saleem-mirza! Thanks for this snippet! Really useful! Sometimes I get a 403 status that says my auth header is not correct. It seems related to the contents of my json and the content length. Do you have a clue on how to normalise my json/strings so that this will go correctly?