logdetective 2.0.0__py3-none-any.whl → 2.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,8 @@ class DrainExtractor:
20
20
  context: bool = False,
21
21
  max_clusters=8,
22
22
  skip_snippets: SkipSnippets = SkipSnippets({}),
23
- ):
23
+ max_snippet_len: int = 2000
24
+ ): # pylint: disable=R0913,R0917
24
25
  config = TemplateMinerConfig()
25
26
  config.load(f"{os.path.dirname(__file__)}/drain3.ini")
26
27
  config.profiling_enabled = verbose
@@ -29,11 +30,12 @@ class DrainExtractor:
29
30
  self.verbose = verbose
30
31
  self.context = context
31
32
  self.skip_snippets = skip_snippets
33
+ self.max_snippet_len = max_snippet_len
32
34
 
33
35
  def __call__(self, log: str) -> list[Tuple[int, str]]:
34
36
  out = []
35
37
  # Create chunks
36
- chunks = list(get_chunks(log))
38
+ chunks = list(get_chunks(log, self.max_snippet_len))
37
39
  # Keep only chunks that don't match any of the excluded patterns
38
40
  chunks = [
39
41
  (_, chunk)
@@ -244,18 +244,18 @@ class InferenceConfig(BaseModel): # pylint: disable=too-many-instance-attribute
244
244
  class ExtractorConfig(BaseModel):
245
245
  """Model for extractor configuration of logdetective server."""
246
246
 
247
- context: bool = True
248
247
  max_clusters: int = 8
249
248
  verbose: bool = False
249
+ max_snippet_len: int = 2000
250
250
 
251
251
  def __init__(self, data: Optional[dict] = None):
252
252
  super().__init__()
253
253
  if data is None:
254
254
  return
255
255
 
256
- self.context = data.get("context", True)
257
256
  self.max_clusters = data.get("max_clusters", 8)
258
257
  self.verbose = data.get("verbose", False)
258
+ self.max_snippet_len = data.get("max_snippet_len", 2000)
259
259
 
260
260
 
261
261
  class GitLabInstanceConfig(BaseModel): # pylint: disable=too-many-instance-attributes
@@ -117,23 +117,25 @@ def requires_token_when_set(authentication: Annotated[str | None, Header()] = No
117
117
  LOG.info("LOGDETECTIVE_TOKEN env var not set, authentication disabled")
118
118
  # no token required, means local dev environment
119
119
  return
120
- token = None
121
120
  if authentication:
122
121
  try:
123
122
  token = authentication.split(" ", 1)[1]
124
- except (ValueError, IndexError):
123
+ except (ValueError, IndexError) as ex:
125
124
  LOG.warning(
126
- "Authentication header has invalid structure (%s), it should be 'Bearer TOKEN'",
125
+ "Authentication header has invalid structure '%s', it should be 'Bearer TOKEN'",
127
126
  authentication,
128
127
  )
129
128
  # eat the exception and raise 401 below
130
- token = None
129
+ raise HTTPException(
130
+ status_code=401,
131
+ detail=f"Invalid authentication, HEADER '{authentication}' not valid.",
132
+ ) from ex
131
133
  if token == API_TOKEN:
132
134
  return
133
- LOG.info(
134
- "LOGDETECTIVE_TOKEN env var is set (%s), clien token = %s", API_TOKEN, token
135
- )
136
- raise HTTPException(status_code=401, detail=f"Token {token} not valid.")
135
+ LOG.info("Provided token '%s' does not match expected value.", token)
136
+ raise HTTPException(status_code=401, detail=f"Token '{token}' not valid.")
137
+ LOG.error("No authentication header provided but LOGDETECTIVE_TOKEN env var is set")
138
+ raise HTTPException(status_code=401, detail="No token provided.")
137
139
 
138
140
 
139
141
  app = FastAPI(dependencies=[Depends(requires_token_when_set)], lifespan=lifespan)
@@ -12,7 +12,7 @@ In this case, we are {{ "%.2f" | format(certainty) }}% certain of the response {
12
12
  {% for snippet in snippets %}
13
13
  <li>
14
14
  <b>Line {{ snippet.line_number }}:</b> <code>{{ snippet.text }}</code>
15
- {{ snippet.explanation }}
15
+ {{ snippet.explanation.text }}
16
16
  </li>
17
17
  {% endfor %}
18
18
  </ul>
@@ -29,6 +29,7 @@ def mine_logs(log: str) -> List[Tuple[int, str]]:
29
29
  context=True,
30
30
  max_clusters=SERVER_CONFIG.extractor.max_clusters,
31
31
  skip_snippets=SKIP_SNIPPETS_CONFIG,
32
+ max_snippet_len=SERVER_CONFIG.extractor.max_snippet_len
32
33
  )
33
34
 
34
35
  LOG.info("Getting summary")
logdetective/utils.py CHANGED
@@ -39,7 +39,7 @@ def chunk_continues(text: str, index: int) -> bool:
39
39
  return False
40
40
 
41
41
 
42
- def get_chunks(text: str) -> Generator[Tuple[int, str], None, None]:
42
+ def get_chunks(text: str, max_len: int = 2000) -> Generator[Tuple[int, str], None, None]:
43
43
  """Split log into chunks according to heuristic
44
44
  based on whitespace and backslash presence.
45
45
  """
@@ -54,7 +54,7 @@ def get_chunks(text: str) -> Generator[Tuple[int, str], None, None]:
54
54
  chunk += text[i]
55
55
  if text[i] == "\n":
56
56
  next_line_number += 1
57
- if i + 1 < text_len and chunk_continues(text, i):
57
+ if i + 1 < text_len and chunk_continues(text, i) and i + 1 < max_len:
58
58
  i += 1
59
59
  continue
60
60
  yield (original_line_number, chunk)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: logdetective
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Log using LLM AI to search for build/test failures and provide ideas for fixing these.
5
5
  License: Apache-2.0
6
6
  Author: Jiri Podivin
@@ -20,23 +20,30 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
20
  Classifier: Topic :: Software Development :: Debuggers
21
21
  Provides-Extra: server
22
22
  Provides-Extra: server-testing
23
- Requires-Dist: aiohttp (>=3.7.4)
23
+ Provides-Extra: testing
24
+ Requires-Dist: aiohttp (>=3.7.4,<4.0.0)
24
25
  Requires-Dist: aiolimiter (>=1.0.0,<2.0.0) ; extra == "server"
26
+ Requires-Dist: aioresponses (>=0.7.8,<0.8.0) ; extra == "testing"
25
27
  Requires-Dist: alembic (>=1.13.3,<2.0.0) ; extra == "server" or extra == "server-testing"
26
28
  Requires-Dist: backoff (==2.2.1) ; extra == "server" or extra == "server-testing"
27
29
  Requires-Dist: drain3 (>=0.9.11,<0.10.0)
28
- Requires-Dist: fastapi (>=0.111.1) ; extra == "server" or extra == "server-testing"
29
- Requires-Dist: huggingface-hub (>0.23.2)
30
+ Requires-Dist: fastapi (>=0.111.1,<1.0.0) ; extra == "server" or extra == "server-testing"
31
+ Requires-Dist: flexmock (>=0.12.2,<0.13.0) ; extra == "testing"
32
+ Requires-Dist: huggingface-hub (>0.23.2,<0.35.0)
30
33
  Requires-Dist: koji (>=1.35.0,<2.0.0) ; extra == "server" or extra == "server-testing"
31
- Requires-Dist: llama-cpp-python (>0.2.56,!=0.2.86)
34
+ Requires-Dist: llama-cpp-python (>0.2.56,!=0.2.86,<1.0.0)
32
35
  Requires-Dist: matplotlib (>=3.8.4,<4.0.0) ; extra == "server" or extra == "server-testing"
33
36
  Requires-Dist: numpy (>=1.26.0)
34
37
  Requires-Dist: openai (>=1.82.1,<2.0.0) ; extra == "server" or extra == "server-testing"
35
38
  Requires-Dist: psycopg2 (>=2.9.9,<3.0.0) ; extra == "server"
36
39
  Requires-Dist: psycopg2-binary (>=2.9.9,<3.0.0) ; extra == "server-testing"
37
40
  Requires-Dist: pydantic (>=2.8.2,<3.0.0)
41
+ Requires-Dist: pytest (>=8.4.1,<9.0.0) ; extra == "testing"
42
+ Requires-Dist: pytest-asyncio (>=1.1.0,<2.0.0) ; extra == "testing"
43
+ Requires-Dist: pytest-mock (>=3.14.1,<4.0.0) ; extra == "server-testing"
38
44
  Requires-Dist: python-gitlab (>=4.4.0)
39
45
  Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
46
+ Requires-Dist: responses (>=0.25.7,<0.26.0) ; extra == "server-testing"
40
47
  Requires-Dist: sentry-sdk[fastapi] (>=2.17.0,<3.0.0) ; extra == "server" or extra == "server-testing"
41
48
  Requires-Dist: sqlalchemy (>=2.0.36,<3.0.0) ; extra == "server" or extra == "server-testing"
42
49
  Project-URL: homepage, https://github.com/fedora-copr/logdetective
@@ -1,7 +1,7 @@
1
1
  logdetective/__init__.py,sha256=VqRngDcuFT7JWms8Qc_MsOvajoXVOKPr-S1kqY3Pqhc,59
2
2
  logdetective/constants.py,sha256=aCwrkBrDdS_kbNESK-Z-ewg--DSzodV2OMgwEq3UE38,2456
3
3
  logdetective/drain3.ini,sha256=ni91eCT1TwTznZwcqWoOVMQcGEnWhEDNCoTPF7cfGfY,1360
4
- logdetective/extractors.py,sha256=BkQe7FMLDoKVWitP85Vpv1qle1Fo1FeupKm0wVlcALI,1859
4
+ logdetective/extractors.py,sha256=gRiEcS1M_0Otu9zzT-tGm2ez3DoCKHYrQwJXZAZS0lk,1995
5
5
  logdetective/logdetective.py,sha256=DECG4qnmYHlCcQ5Waj3Esr4wSb6LtM4m7qqtmZqYDX0,6151
6
6
  logdetective/models.py,sha256=h01nagxgb8sR9Js_00DMoZv6GvwHjcOk0MeKttftDHk,2460
7
7
  logdetective/prompts-summary-first.yml,sha256=3Zfp4NNOfaFYq5xBlBjeQa5PdjYfS4v17OtJqQ-DRpU,821
@@ -24,16 +24,16 @@ logdetective/server/gitlab.py,sha256=MrAprXLTN6Q15qBC_Y2y42iKdtmIfed_pfjEt0gABvc
24
24
  logdetective/server/koji.py,sha256=LG1pRiKUFvYFRKzgQoUG3pUHfcEwMoaMNjUSMKw_pBA,5640
25
25
  logdetective/server/llm.py,sha256=_JRbEpNHzXWy0BuwjFhhuwLdPzFi4yKikZHwoibWiek,9736
26
26
  logdetective/server/metric.py,sha256=QrrX1FmMa7sc57av0P9UFOiCIFYVLs1opOWV3ObYo0s,4086
27
- logdetective/server/models.py,sha256=ogMh00LAPUD8f5HjMWBfOsRxhcTvxbAZ6-MzmG4PhzE,19244
27
+ logdetective/server/models.py,sha256=SY3wdYgyNcggdCcslDX6QM-aMTTtI4OAG5UQtWrSIWM,19267
28
28
  logdetective/server/plot.py,sha256=C98U9prGoPkp8_t4v2dovdZuwOhSbxXSeB_K9Q2r3NE,14607
29
- logdetective/server/server.py,sha256=rpl5WtnesxPz_Zahy2bKN5wMIjbvdE1sM1ulvxvDiGw,24416
30
- logdetective/server/templates/gitlab_full_comment.md.j2,sha256=mD98HA-wQlv-H98M9Bb63lCROpcF4TkSpoat90c7eNY,1942
29
+ logdetective/server/server.py,sha256=zap8Mz3NTFvaDJMNQDATbPYk6MhQ9o1J9gJECnGWvuQ,24694
30
+ logdetective/server/templates/gitlab_full_comment.md.j2,sha256=H4NPjm3l8X5d0TNtfyZZZj_gHY1Y7hWEqY6RaVA8qt0,1947
31
31
  logdetective/server/templates/gitlab_short_comment.md.j2,sha256=vPisU1c98LPKEwlKtMrtlqnEOlbykPZK96MpHAf-o88,1758
32
- logdetective/server/utils.py,sha256=6RnEDsUgx6S3m6PzMcAO_Smsu_U-MHoP6FGKiaERPcY,4224
32
+ logdetective/server/utils.py,sha256=ixEXSc93Zdwy94YkExdNJ1vRCe90dNP7DQpy8XlFYRU,4288
33
33
  logdetective/skip_snippets.yml,sha256=reGlhPPCo06nNUJWiC2LY-OJOoPdcyOB7QBTSMeh0eg,487
34
- logdetective/utils.py,sha256=UAhPWbOGdTR7PWc1dEQk8FSxBSsO0UgfdyY8AKGfMJY,7781
35
- logdetective-2.0.0.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
36
- logdetective-2.0.0.dist-info/METADATA,sha256=so6qpVEedLsX8ZvyQbiwAF4AOOWBlWZ0pV5At4xvPSg,20104
37
- logdetective-2.0.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
38
- logdetective-2.0.0.dist-info/entry_points.txt,sha256=3K_vXja6PmcA8sNdUi63WdImeiNhVZcEGPTaoJmltfA,63
39
- logdetective-2.0.0.dist-info/RECORD,,
34
+ logdetective/utils.py,sha256=Ur4EPCAeuvymFcUO10SpbCBI2tdcZ33s-fjCn9pfgUY,7822
35
+ logdetective-2.0.2.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
36
+ logdetective-2.0.2.dist-info/METADATA,sha256=nDKMJPHfVQkCNGBszgka3b0Y0MBAfGrU_-aZRIKmOqM,20560
37
+ logdetective-2.0.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
38
+ logdetective-2.0.2.dist-info/entry_points.txt,sha256=3K_vXja6PmcA8sNdUi63WdImeiNhVZcEGPTaoJmltfA,63
39
+ logdetective-2.0.2.dist-info/RECORD,,